refactor: update data source and repository structure by removing unused files, enhancing model integration, and adjusting import paths for better organization
This commit is contained in:
@@ -1,213 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/common/dio_error_handler.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/user_info/user_info_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/user_profile_model/user_profile_model.dart';
|
||||
import 'package:rasadyar_chicken/data/repositories/auth/auth_repository.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/captcha/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum AuthType { useAndPass, otp }
|
||||
|
||||
enum AuthStatus { init }
|
||||
|
||||
enum OtpStatus { init, sent, verified, reSend }
|
||||
|
||||
class AuthLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
late AnimationController _textAnimationController;
|
||||
late Animation<double> textAnimation;
|
||||
RxBool showCard = false.obs;
|
||||
RxBool rememberMe = false.obs;
|
||||
|
||||
Rx<GlobalKey<FormState>> formKeyOtp = GlobalKey<FormState>().obs;
|
||||
Rx<GlobalKey<FormState>> formKeySentOtp = GlobalKey<FormState>().obs;
|
||||
Rx<TextEditingController> usernameController = TextEditingController().obs;
|
||||
Rx<TextEditingController> passwordController = TextEditingController().obs;
|
||||
Rx<TextEditingController> phoneOtpNumberController = TextEditingController().obs;
|
||||
Rx<TextEditingController> otpCodeController = TextEditingController().obs;
|
||||
|
||||
var captchaController = Get.find<CaptchaWidgetLogic>();
|
||||
|
||||
RxnString phoneNumber = RxnString(null);
|
||||
RxBool isLoading = false.obs;
|
||||
RxBool isDisabled = true.obs;
|
||||
|
||||
GService gService = Get.find<GService>();
|
||||
TokenStorageService tokenStorageService = Get.find<TokenStorageService>();
|
||||
|
||||
Rx<AuthType> authType = AuthType.useAndPass.obs;
|
||||
Rx<AuthStatus> authStatus = AuthStatus.init.obs;
|
||||
Rx<OtpStatus> otpStatus = OtpStatus.init.obs;
|
||||
RxnString deviceName = RxnString(null);
|
||||
|
||||
RxInt secondsRemaining = 120.obs;
|
||||
Timer? _timer;
|
||||
|
||||
AuthRepository authRepository = diChicken.get<AuthRepository>();
|
||||
|
||||
final Module _module = Get.arguments;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
_textAnimationController =
|
||||
AnimationController(vsync: this, duration: const Duration(milliseconds: 1200))
|
||||
..repeat(reverse: true, count: 2).whenComplete(() {
|
||||
showCard.value = true;
|
||||
});
|
||||
|
||||
textAnimation = CurvedAnimation(parent: _textAnimationController, curve: Curves.easeInOut);
|
||||
|
||||
initUserPassData();
|
||||
getDeviceModel();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_textAnimationController.dispose();
|
||||
_timer?.cancel();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void startTimer() {
|
||||
_timer?.cancel();
|
||||
secondsRemaining.value = 120;
|
||||
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
if (secondsRemaining.value > 0) {
|
||||
secondsRemaining.value--;
|
||||
} else {
|
||||
timer.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void stopTimer() {
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
String get timeFormatted {
|
||||
final minutes = secondsRemaining.value ~/ 60;
|
||||
final seconds = secondsRemaining.value % 60;
|
||||
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
bool _isFormValid() {
|
||||
final isCaptchaValid = captchaController.formKey.currentState?.validate() ?? false;
|
||||
final isFormValid = formKey.currentState?.validate() ?? false;
|
||||
return isCaptchaValid && isFormValid;
|
||||
}
|
||||
|
||||
Future<void> submitLoginForm() async {
|
||||
if (!_isFormValid()) return;
|
||||
AuthRepository authTmp = diChicken.get<AuthRepository>();
|
||||
isLoading.value = true;
|
||||
await safeCall<UserProfileModel?>(
|
||||
call: () => authTmp.login(
|
||||
authRequest: {
|
||||
"username": usernameController.value.text,
|
||||
"password": passwordController.value.text,
|
||||
},
|
||||
),
|
||||
onSuccess: (result) async {
|
||||
await gService.saveSelectedModule(_module);
|
||||
await tokenStorageService.saveModule(_module);
|
||||
await tokenStorageService.saveAccessToken(_module, result?.accessToken ?? '');
|
||||
await tokenStorageService.saveRefreshToken(_module, result?.accessToken ?? '');
|
||||
var tmpRoles = result?.role?.where((element) {
|
||||
final allowedRoles = {'poultryscience', 'steward', 'killhouse'};
|
||||
final lowerElement = element.toString().toLowerCase().trim();
|
||||
return allowedRoles.contains(lowerElement);
|
||||
}).toList();
|
||||
|
||||
await tokenStorageService.saveRoles(_module, tmpRoles ?? []);
|
||||
if (rememberMe.value) {
|
||||
await tokenStorageService.saveUserPass(
|
||||
_module,
|
||||
usernameController.value.text,
|
||||
passwordController.value.text,
|
||||
);
|
||||
}
|
||||
|
||||
authTmp.stewardAppLogin(
|
||||
token: result?.accessToken ?? '',
|
||||
queryParameters: {
|
||||
"mobile": usernameController.value.text,
|
||||
"device_name": deviceName.value,
|
||||
},
|
||||
);
|
||||
|
||||
if (tmpRoles!.length > 1) {
|
||||
Get.offAndToNamed(ChickenRoutes.role);
|
||||
} else {
|
||||
Get.offAllNamed(ChickenRoutes.initSteward);
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
if (error is DioException) {
|
||||
diChicken.get<DioErrorHandler>().handle(error);
|
||||
if ((error.type == DioExceptionType.unknown) ||
|
||||
(error.type == DioExceptionType.connectionError)) {
|
||||
getUserInfo(usernameController.value.text);
|
||||
}
|
||||
}
|
||||
captchaController.getCaptcha();
|
||||
},
|
||||
);
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
Future<void> getUserInfo(String value) async {
|
||||
isLoading.value = true;
|
||||
await safeCall<UserInfoModel?>(
|
||||
call: () async => await authRepository.getUserInfo(value),
|
||||
onSuccess: (result) async {
|
||||
if (result != null) {
|
||||
await newSetupAuthDI(result.backend ?? '');
|
||||
await diChicken.allReady();
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
if (error is DioException) {
|
||||
diChicken.get<DioErrorHandler>().handle(error);
|
||||
}
|
||||
captchaController.getCaptcha();
|
||||
},
|
||||
);
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
void initUserPassData() {
|
||||
UserLocalModel? userLocalModel = tokenStorageService.getUserLocal(Module.chicken);
|
||||
if (userLocalModel?.username != null && userLocalModel?.password != null) {
|
||||
usernameController.value.text = userLocalModel?.username ?? '';
|
||||
passwordController.value.text = userLocalModel?.password ?? '';
|
||||
rememberMe.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getDeviceModel() async {
|
||||
final deviceInfo = DeviceInfoPlugin();
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
final info = await deviceInfo.androidInfo;
|
||||
print('Device: ${info.manufacturer} ${info.model}');
|
||||
print('Android version: ${info.version.release}');
|
||||
deviceName.value =
|
||||
'Device:${info.manufacturer} Model:${info.model} version ${info.version.release}';
|
||||
} else if (Platform.isIOS) {
|
||||
final info = await deviceInfo.iosInfo;
|
||||
print('Device: ${info.utsname.machine} (${info.name})');
|
||||
print('System version: ${info.systemVersion}');
|
||||
deviceName.value =
|
||||
'Device:${info.utsname.machine} Model:${info.model} version ${info.systemVersion}';
|
||||
} else {
|
||||
print('Unsupported platform');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,355 +0,0 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/captcha/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class AuthPage extends GetView<AuthLogic> {
|
||||
const AuthPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
backGroundWidget: backGroundDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topRight,
|
||||
end: Alignment.bottomLeft,
|
||||
colors: [
|
||||
const Color(0xFFB2C9FF).withValues(alpha: 1.0), // 0%
|
||||
const Color(0xFF40BB93).withValues(alpha: 0.11), // 50%
|
||||
const Color(0xFF93B6D3).withValues(alpha: 1.0), // 100%
|
||||
],
|
||||
stops: const [0.0, 0.5, 1.0],
|
||||
),
|
||||
backgroundPath: Assets.images.patternChicken.path,
|
||||
),
|
||||
onPopScopTaped: () => Get.back(result: -1),
|
||||
child: Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.r),
|
||||
child: FadeTransition(
|
||||
opacity: controller.textAnimation,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 12,
|
||||
children: [
|
||||
Text(
|
||||
'به سامانه رصدطیور خوش آمدید!',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan25Bold.copyWith(color: AppColor.darkGreyDarkActive),
|
||||
),
|
||||
Text(
|
||||
'سامانه رصد و پایش زنجیره تامین، تولید و توزیع کالا های اساسی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDarkActive),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Obx(() {
|
||||
final screenHeight = MediaQuery.of(context).size.height;
|
||||
final targetTop = (screenHeight - 676) / 2;
|
||||
|
||||
return AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 1200),
|
||||
curve: Curves.linear,
|
||||
top: controller.showCard.value ? targetTop : screenHeight,
|
||||
left: 10.r,
|
||||
right: 10.r,
|
||||
child: Container(
|
||||
width: 381.w,
|
||||
height: 676.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 50.h),
|
||||
LogoWidget(
|
||||
vecPath: Assets.vec.rasadToyorSvg.path,
|
||||
width: 85.w,
|
||||
height: 85.h,
|
||||
titleStyle: AppFonts.yekan20Bold.copyWith(color: Color(0xFF4665AF)),
|
||||
title: 'رصدطیور',
|
||||
),
|
||||
SizedBox(height: 20.h),
|
||||
useAndPassFrom(),
|
||||
SizedBox(height: 24.h),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'مطالعه بیانیه ',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Get.bottomSheet(
|
||||
privacyPolicyWidget(),
|
||||
isScrollControlled: true,
|
||||
enableDrag: true,
|
||||
ignoreSafeArea: false,
|
||||
);
|
||||
},
|
||||
text: 'حریم خصوصی',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget useAndPassFrom() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 30.r),
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: AutofillGroup(
|
||||
child: Column(
|
||||
children: [
|
||||
RTextField(
|
||||
label: 'نام کاربری',
|
||||
maxLength: 11,
|
||||
maxLines: 1,
|
||||
controller: controller.usernameController.value,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [PersianFormatter()],
|
||||
initText: controller.usernameController.value.text,
|
||||
autofillHints: [AutofillHints.username],
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: AppColor.textColor, width: 1),
|
||||
),
|
||||
onChanged: (value) async {
|
||||
controller.usernameController.value.text = value;
|
||||
if (value.length == 11) {
|
||||
await controller.getUserInfo(value);
|
||||
}
|
||||
},
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 6, 8),
|
||||
child: Assets.vec.callSvg.svg(width: 12, height: 12),
|
||||
),
|
||||
suffixIcon: controller.usernameController.value.text.trim().isNotEmpty
|
||||
? clearButton(() {
|
||||
controller.usernameController.value.clear();
|
||||
controller.usernameController.refresh();
|
||||
})
|
||||
: null,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '⚠️ شماره موبایل را وارد کنید';
|
||||
} else if (value.length < 10) {
|
||||
return '⚠️ شماره موبایل باید 11 رقم باشد';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(color: AppColor.redNormal),
|
||||
labelStyle: AppFonts.yekan13,
|
||||
boxConstraints: const BoxConstraints(
|
||||
maxHeight: 40,
|
||||
minHeight: 40,
|
||||
maxWidth: 40,
|
||||
minWidth: 40,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 26),
|
||||
ObxValue(
|
||||
(passwordController) => RTextField(
|
||||
label: 'رمز عبور',
|
||||
filled: false,
|
||||
obscure: true,
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: AppColor.textColor, width: 1),
|
||||
),
|
||||
controller: passwordController.value,
|
||||
autofillHints: [AutofillHints.password],
|
||||
variant: RTextFieldVariant.password,
|
||||
initText: passwordController.value.text,
|
||||
inputFormatters: [PersianFormatter()],
|
||||
onChanged: (value) {
|
||||
passwordController.refresh();
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '⚠️ رمز عبور را وارد کنید';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(color: AppColor.redNormal),
|
||||
labelStyle: AppFonts.yekan13,
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
|
||||
child: Assets.vec.keySvg.svg(width: 12, height: 12),
|
||||
),
|
||||
boxConstraints: const BoxConstraints(
|
||||
maxHeight: 34,
|
||||
minHeight: 34,
|
||||
maxWidth: 34,
|
||||
minWidth: 34,
|
||||
),
|
||||
),
|
||||
controller.passwordController,
|
||||
),
|
||||
SizedBox(height: 26),
|
||||
CaptchaWidget(),
|
||||
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
controller.rememberMe.value = !controller.rememberMe.value;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return Checkbox(
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
visualDensity: VisualDensity(horizontal: -4, vertical: 4),
|
||||
tristate: true,
|
||||
value: data.value,
|
||||
onChanged: (value) {
|
||||
data.value = value ?? false;
|
||||
},
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
|
||||
activeColor: AppColor.blueNormal,
|
||||
);
|
||||
}, controller.rememberMe),
|
||||
Text(
|
||||
'مرا به خاطر بسپار',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Obx(() {
|
||||
return RElevated(
|
||||
text: 'ورود',
|
||||
isLoading: controller.isLoading.value,
|
||||
onPressed: controller.isDisabled.value
|
||||
? null
|
||||
: () async {
|
||||
await controller.submitLoginForm();
|
||||
},
|
||||
width: Get.width,
|
||||
height: 48,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget privacyPolicyWidget() {
|
||||
return BaseBottomSheet(
|
||||
child: Column(
|
||||
spacing: 5,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(8.w),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight, width: 1),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'بيانيه حريم خصوصی',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
'اطلاعات مربوط به هر شخص، حریم خصوصی وی محسوب میشود. حفاظت و حراست از اطلاعات شخصی در سامانه رصد یار، نه تنها موجب حفظ امنیت کاربران میشود، بلکه باعث اعتماد بیشتر و مشارکت آنها در فعالیتهای جاری میگردد. هدف از این بیانیه، آگاه ساختن شما درباره ی نوع و نحوه ی استفاده از اطلاعاتی است که در هنگام استفاده از سامانه رصد یار ، از جانب شما دریافت میگردد. شرکت هوشمند سازان خود را ملزم به رعایت حریم خصوصی همه شهروندان و کاربران سامانه دانسته و آن دسته از اطلاعات کاربران را که فقط به منظور ارائه خدمات کفایت میکند، دریافت کرده و از انتشار آن یا در اختیار قرار دادن آن به دیگران خودداری مینماید.',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark, height: 1.8),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(8.w),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight, width: 1),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 4,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'چگونگی جمع آوری و استفاده از اطلاعات کاربران',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
'''الف: اطلاعاتی که شما خود در اختيار این سامانه قرار میدهيد، شامل موارد زيرهستند:
|
||||
اقلام اطلاعاتی شامل شماره تلفن همراه، تاریخ تولد، کد پستی و کد ملی کاربران را دریافت مینماییم که از این اقلام، صرفا جهت احراز هویت کاربران استفاده خواهد شد.
|
||||
ب: برخی اطلاعات ديگر که به صورت خودکار از شما دريافت میشود شامل موارد زير میباشد:
|
||||
⦁ دستگاهی که از طریق آن سامانه رصد یار را مشاهده مینمایید( تلفن همراه، تبلت، رایانه).
|
||||
⦁ نام و نسخه سیستم عامل و browser کامپیوتر شما.
|
||||
⦁ اطلاعات صفحات بازدید شده.
|
||||
⦁ تعداد بازدیدهای روزانه در درگاه.
|
||||
⦁ هدف ما از دریافت این اطلاعات استفاده از آنها در تحلیل عملکرد کاربران درگاه می باشد تا بتوانیم در خدمت رسانی بهتر عمل کنیم.
|
||||
''',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark, height: 1.8),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(8.w),
|
||||
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight, width: 1),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 4,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'امنیت اطلاعات',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
'متعهدیم که امنیت اطلاعات شما را تضمین نماییم و برای جلوگیری از هر نوع دسترسی غیرمجاز و افشای اطلاعات شما از همه شیوههای لازم استفاده میکنیم تا امنیت اطلاعاتی را که به صورت آنلاین گردآوری میکنیم، حفظ شود. لازم به ذکر است در سامانه ما، ممکن است به سایت های دیگری لینک شوید، وقتی که شما از طریق این لینکها از سامانه ما خارج میشوید، توجه داشته باشید که ما بر دیگر سایت ها کنترل نداریم و سازمان تعهدی بر حفظ حریم شخصی آنان در سایت مقصد نخواهد داشت و مراجعه کنندگان میبایست به بیانیه حریم شخصی آن سایت ها مراجعه نمایند.',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark, height: 1.8),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/change_password/change_password_request_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/user_profile/user_profile.dart';
|
||||
import 'package:rasadyar_chicken/data/repositories/chicken/chicken_repository.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProfileLogic extends GetxController {
|
||||
ChickenRepository chickenRepository = diChicken.get<ChickenRepository>();
|
||||
GService gService = Get.find<GService>();
|
||||
TokenStorageService tokenService = Get.find<TokenStorageService>();
|
||||
RxInt selectedInformationType = 0.obs;
|
||||
Rxn<Jalali> birthDate = Rxn<Jalali>();
|
||||
|
||||
Rx<Resource<UserProfile>> userProfile = Rx<Resource<UserProfile>>(
|
||||
Resource.loading(),
|
||||
);
|
||||
Rx<Resource<UserLocalModel>> userLocal = Rx<Resource<UserLocalModel>>(
|
||||
Resource.loading(),
|
||||
);
|
||||
|
||||
TextEditingController nameController = TextEditingController();
|
||||
TextEditingController lastNameController = TextEditingController();
|
||||
TextEditingController nationalCodeController = TextEditingController();
|
||||
TextEditingController nationalIdController = TextEditingController();
|
||||
TextEditingController birthdayController = TextEditingController();
|
||||
|
||||
TextEditingController oldPasswordController = TextEditingController();
|
||||
TextEditingController newPasswordController = TextEditingController();
|
||||
TextEditingController retryNewPasswordController = TextEditingController();
|
||||
|
||||
RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
|
||||
Rxn<IranProvinceCityModel> selectedProvince = Rxn();
|
||||
Rxn<IranProvinceCityModel> selectedCity = Rxn();
|
||||
|
||||
GlobalKey<FormState> formKey = GlobalKey();
|
||||
ImagePicker imagePicker = ImagePicker();
|
||||
Rxn<XFile> selectedImage = Rxn<XFile>();
|
||||
final RxnString _base64Image = RxnString();
|
||||
RxBool isOnLoading = false.obs;
|
||||
|
||||
RxBool isUserInformationOpen = true.obs;
|
||||
RxBool isUnitInformationOpen = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
ever(selectedImage, (data) async {
|
||||
if (data?.path != null) {
|
||||
_base64Image.value = await convertImageToBase64(data!.path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getUserProfile();
|
||||
getUserRole();
|
||||
selectedProvince.listen((p0) => getCites());
|
||||
userProfile.listen((data) {
|
||||
nameController.text = data.data?.firstName ?? '';
|
||||
lastNameController.text = data.data?.lastName ?? '';
|
||||
nationalCodeController.text = data.data?.nationalCode ?? '';
|
||||
nationalIdController.text = data.data?.nationalId ?? '';
|
||||
birthdayController.text =
|
||||
data.data?.birthday?.toJalali.formatCompactDate() ?? '';
|
||||
birthDate.value = data.data?.birthday?.toJalali;
|
||||
selectedProvince.value = IranProvinceCityModel(
|
||||
name: data.data?.province ?? '',
|
||||
id: data.data?.provinceNumber ?? 0,
|
||||
);
|
||||
|
||||
selectedCity.value = IranProvinceCityModel(
|
||||
name: data.data?.city ?? '',
|
||||
id: data.data?.cityNumber ?? 0,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Future<void> getUserProfile() async {
|
||||
userProfile.value = Resource.loading();
|
||||
await safeCall<UserProfile?>(
|
||||
call: () async => await chickenRepository.getUserProfile(
|
||||
token: tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
userProfile.value = Resource.success(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getCites() async {
|
||||
await safeCall(
|
||||
call: () => chickenRepository.getCity(
|
||||
provinceName: selectedProvince.value?.name ?? '',
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null && result.isNotEmpty) {
|
||||
cites.value = result;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updateUserProfile() async {
|
||||
UserProfile userProfile = UserProfile(
|
||||
firstName: nameController.text,
|
||||
lastName: lastNameController.text,
|
||||
nationalCode: nationalCodeController.text,
|
||||
nationalId: nationalIdController.text,
|
||||
birthday: birthDate.value
|
||||
?.toDateTime()
|
||||
.formattedDashedGregorian
|
||||
.toString(),
|
||||
image: _base64Image.value,
|
||||
personType: 'self',
|
||||
type: 'self_profile',
|
||||
);
|
||||
isOnLoading.value = true;
|
||||
await safeCall(
|
||||
call: () async => await chickenRepository.updateUserProfile(
|
||||
token: tokenService.accessToken.value!,
|
||||
userProfile: userProfile,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
isOnLoading.value = false;
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
isOnLoading.value = false;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updatePassword() async {
|
||||
if (formKey.currentState?.validate() ?? false) {
|
||||
ChangePasswordRequestModel model = ChangePasswordRequestModel(
|
||||
username: userProfile.value.data?.mobile,
|
||||
password: newPasswordController.text,
|
||||
);
|
||||
|
||||
await safeCall(
|
||||
call: () async => await chickenRepository.updatePassword(
|
||||
token: tokenService.accessToken.value!,
|
||||
model: model,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getUserRole() async {
|
||||
userLocal.value = Resource.loading();
|
||||
await safeCall<UserLocalModel?>(
|
||||
call: () async => tokenService.getUserLocal(Module.chicken),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
userLocal.value = Resource.success(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void clearPasswordForm() {
|
||||
oldPasswordController.clear();
|
||||
newPasswordController.clear();
|
||||
retryNewPasswordController.clear();
|
||||
}
|
||||
|
||||
Future<void> changeUserRole(String newRole) async {
|
||||
dLog(newRole);
|
||||
await gService.saveRoute(Module.chicken, newRole);
|
||||
|
||||
Get.offAllNamed(newRole);
|
||||
}
|
||||
}
|
||||
@@ -1,901 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart' hide Image;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/common/fa_user_role.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/user_profile/user_profile.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class ProfilePage extends GetView<ProfileLogic> {
|
||||
const ProfilePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
spacing: 30,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: AppColor.blueNormal,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(),
|
||||
ObxValue((data) {
|
||||
final status = data.value.status;
|
||||
|
||||
if (status == ResourceStatus.loading) {
|
||||
return Container(
|
||||
width: 128.w,
|
||||
height: 128.h,
|
||||
child: Center(child: CupertinoActivityIndicator(color: AppColor.greenNormal)),
|
||||
);
|
||||
}
|
||||
|
||||
if (status == ResourceStatus.error) {
|
||||
return Container(
|
||||
width: 128.w,
|
||||
height: 128.h,
|
||||
child: Center(child: Text('خطا در دریافت اطلاعات')),
|
||||
);
|
||||
}
|
||||
|
||||
// Default UI
|
||||
|
||||
return Container(
|
||||
width: 128.w,
|
||||
height: 128.h,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppColor.blueLightActive,
|
||||
),
|
||||
child: Center(
|
||||
child: data.value.data?.image != null
|
||||
? CircleAvatar(
|
||||
radius: 64.w,
|
||||
backgroundImage: NetworkImage(data.value.data!.image!),
|
||||
)
|
||||
: Icon(Icons.person, size: 64.w),
|
||||
),
|
||||
);
|
||||
}, controller.userProfile),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: SingleChildScrollView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
rolesWidget(),
|
||||
SizedBox(height: 12.h),
|
||||
|
||||
ObxValue((data) {
|
||||
if (data.value.status == ResourceStatus.loading) {
|
||||
return LoadingWidget();
|
||||
} else if (data.value.status == ResourceStatus.error) {
|
||||
return ErrorWidget('خطا در دریافت اطلاعات کاربر');
|
||||
} else if (data.value.status == ResourceStatus.success) {
|
||||
return Column(
|
||||
spacing: 6,
|
||||
children: [
|
||||
ObxValue((isOpen) {
|
||||
return GestureDetector(
|
||||
onTap: () => isOpen.toggle(),
|
||||
child: AnimatedContainer(
|
||||
height: isOpen.value ? 320.h : 47.h,
|
||||
duration: Duration(milliseconds: 500),
|
||||
curve: Curves.linear,
|
||||
child: userProfileInformation(data.value),
|
||||
),
|
||||
);
|
||||
}, controller.isUserInformationOpen),
|
||||
|
||||
Visibility(
|
||||
visible:
|
||||
data.value.data?.unitName != null ||
|
||||
data.value.data?.unitAddress != null ||
|
||||
data.value.data?.unitPostalCode != null ||
|
||||
data.value.data?.unitRegistrationNumber != null ||
|
||||
data.value.data?.unitEconomicalNumber != null ||
|
||||
data.value.data?.unitCity != null ||
|
||||
data.value.data?.unitProvince != null ||
|
||||
data.value.data?.unitNationalId != null,
|
||||
|
||||
child: ObxValue((isOpen) {
|
||||
return GestureDetector(
|
||||
onTap: () => isOpen.toggle(),
|
||||
child: AnimatedContainer(
|
||||
height: isOpen.value ? 320.h : 47.h,
|
||||
duration: Duration(milliseconds: 500),
|
||||
curve: Curves.linear,
|
||||
child: unitInformation(data.value),
|
||||
),
|
||||
);
|
||||
}, controller.isUnitInformationOpen),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
}, controller.userProfile),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.bottomSheet(changePasswordBottomSheet(), isScrollControlled: true);
|
||||
},
|
||||
child: Container(
|
||||
height: 47.h,
|
||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 8.h),
|
||||
padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: const Color(0xFFD6D6D6)),
|
||||
),
|
||||
child: Row(
|
||||
spacing: 6,
|
||||
children: [
|
||||
Assets.vec.lockSvg.svg(
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
Text(
|
||||
'تغییر رمز عبور',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.bottomSheet(exitBottomSheet(), isScrollControlled: true);
|
||||
},
|
||||
child: Container(
|
||||
height: 47.h,
|
||||
margin: EdgeInsets.symmetric(horizontal: 8),
|
||||
padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: const Color(0xFFD6D6D6)),
|
||||
),
|
||||
child: Row(
|
||||
spacing: 6,
|
||||
children: [
|
||||
Assets.vec.logoutSvg.svg(
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.redNormal, BlendMode.srcIn),
|
||||
),
|
||||
Text(
|
||||
'خروج',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.redNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 100),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container invoiceIssuanceInformation() => Container();
|
||||
|
||||
Widget bankInformationWidget() => Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
itemList(title: 'نام بانک', content: 'سامان'),
|
||||
itemList(title: 'نام صاحب حساب', content: 'رضا رضایی'),
|
||||
itemList(title: 'شماره کارت ', content: '54154545415'),
|
||||
itemList(title: 'شماره حساب', content: '62565263263652'),
|
||||
itemList(title: 'شماره شبا', content: '62565263263652'),
|
||||
],
|
||||
);
|
||||
|
||||
Widget userProfileInformation(Resource<UserProfile> value) {
|
||||
UserProfile item = value.data!;
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: ObxValue(
|
||||
(val) => Container(
|
||||
height: val.value ? 320.h : 47.h,
|
||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: val.value ? 8 : 0),
|
||||
padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.5, color: AppColor.darkGreyLight),
|
||||
),
|
||||
child: val.value
|
||||
? Column(
|
||||
spacing: 6,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
userInformationBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
);
|
||||
},
|
||||
child: Assets.vec.editSvg.svg(
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
itemList(
|
||||
title: 'نام و نام خانوادگی',
|
||||
content: item.fullname ?? 'نامشخص',
|
||||
icon: Assets.vec.userSvg.path,
|
||||
hasColoredBox: true,
|
||||
),
|
||||
itemList(
|
||||
title: 'کدملی',
|
||||
content: item.nationalId ?? 'نامشخص',
|
||||
icon: Assets.vec.tagUserSvg.path,
|
||||
),
|
||||
itemList(
|
||||
title: 'موبایل',
|
||||
content: item.mobile ?? 'نامشخص',
|
||||
icon: Assets.vec.callSvg.path,
|
||||
),
|
||||
|
||||
itemList(
|
||||
title: 'شماره شناسنامه',
|
||||
content: item.nationalCode ?? 'نامشخص',
|
||||
icon: Assets.vec.userSquareSvg.path,
|
||||
),
|
||||
itemList(
|
||||
title: 'تاریخ تولد',
|
||||
content: item.birthday?.toJalali.formatCompactDate() ?? 'نامشخص',
|
||||
icon: Assets.vec.calendarSvg.path,
|
||||
),
|
||||
//todo
|
||||
itemList(
|
||||
title: 'استان',
|
||||
content: item.province ?? 'نامشخص',
|
||||
icon: Assets.vec.pictureFrameSvg.path,
|
||||
),
|
||||
itemList(
|
||||
title: 'شهر',
|
||||
content: item.city ?? 'نامشخص',
|
||||
icon: Assets.vec.mapSvg.path,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [Icon(CupertinoIcons.chevron_down, color: AppColor.iconColor)],
|
||||
),
|
||||
),
|
||||
controller.isUserInformationOpen,
|
||||
),
|
||||
),
|
||||
ObxValue(
|
||||
(isOpen) => AnimatedPositioned(
|
||||
right: 16,
|
||||
top: isOpen.value ? -7 : 11,
|
||||
duration: Duration(milliseconds: 500),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: isOpen.value
|
||||
? BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.5, color: Color(0xFFA9A9A9)),
|
||||
)
|
||||
: null,
|
||||
child: Text(
|
||||
'اطلاعات هویتی',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
controller.isUserInformationOpen,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget unitInformation(Resource<UserProfile> value) {
|
||||
UserProfile item = value.data!;
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: ObxValue(
|
||||
(val) => Container(
|
||||
height: val.value ? 320.h : 47.h,
|
||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: val.value ? 12 : 0),
|
||||
padding: EdgeInsets.symmetric(horizontal: 11.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.5, color: AppColor.darkGreyLight),
|
||||
),
|
||||
child: val.value
|
||||
? Column(
|
||||
children: [
|
||||
SizedBox(height: 5.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
userInformationBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
);
|
||||
},
|
||||
child: Assets.vec.editSvg.svg(
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
|
||||
child: Column(
|
||||
spacing: 2,
|
||||
children: [
|
||||
itemList(
|
||||
title: 'نام صنفی',
|
||||
content: item.unitName ?? 'نامشخص',
|
||||
hasColoredBox: true,
|
||||
visible: item.unitName != null,
|
||||
),
|
||||
itemList(
|
||||
title: 'شناسنامه ملی',
|
||||
content: item.unitNationalId ?? 'نامشخص',
|
||||
visible: item.unitName != null,
|
||||
),
|
||||
itemList(
|
||||
title: 'شماره ثبت',
|
||||
content: item.unitRegistrationNumber ?? 'نامشخص',
|
||||
visible: item.unitName != null,
|
||||
),
|
||||
|
||||
itemList(
|
||||
title: 'کد اقتصادی',
|
||||
content: item.unitEconomicalNumber ?? 'نامشخص',
|
||||
visible: item.unitName != null,
|
||||
),
|
||||
itemList(
|
||||
title: 'کد پستی',
|
||||
content: item.unitPostalCode ?? 'نامشخص',
|
||||
visible: item.unitName != null,
|
||||
),
|
||||
|
||||
itemList(
|
||||
title: 'استان',
|
||||
content: item.province ?? 'نامشخص',
|
||||
visible: item.unitName != null,
|
||||
),
|
||||
itemList(
|
||||
title: 'شهر',
|
||||
content: item.city ?? 'نامشخص',
|
||||
visible: item.unitName != null,
|
||||
),
|
||||
itemList(title: 'آدرس', content: item.unitAddress ?? 'نامشخص'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [Icon(CupertinoIcons.chevron_down, color: AppColor.iconColor)],
|
||||
),
|
||||
),
|
||||
controller.isUnitInformationOpen,
|
||||
),
|
||||
),
|
||||
ObxValue(
|
||||
(isOpen) => AnimatedPositioned(
|
||||
right: 16,
|
||||
top: isOpen.value ? -2 : 11,
|
||||
duration: Duration(milliseconds: 500),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: isOpen.value
|
||||
? BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.5, color: Color(0xFFA9A9A9)),
|
||||
)
|
||||
: null,
|
||||
child: Text(
|
||||
'اطلاعات صنفی',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
controller.isUnitInformationOpen,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemList({
|
||||
required String title,
|
||||
required String content,
|
||||
String? icon,
|
||||
bool hasColoredBox = false,
|
||||
bool? visible,
|
||||
}) => Visibility(
|
||||
visible: visible ?? true,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 6.h),
|
||||
decoration: BoxDecoration(
|
||||
color: hasColoredBox ? AppColor.greenLight : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: hasColoredBox
|
||||
? Border.all(width: 0.25, color: AppColor.bgDark)
|
||||
: Border.all(width: 0, color: Colors.transparent),
|
||||
),
|
||||
child: Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
if (icon != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: SvgGenImage.vec(icon).svg(
|
||||
width: 20.w,
|
||||
height: 20.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.textColor, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
Text(title, style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
|
||||
Spacer(),
|
||||
Text(content, style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Widget cardActionWidget({
|
||||
required String title,
|
||||
required VoidCallback onPressed,
|
||||
required String icon,
|
||||
bool selected = false,
|
||||
ColorFilter? color,
|
||||
Color? cardColor,
|
||||
Color? cardIconColor,
|
||||
Color? textColor,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: onPressed,
|
||||
child: Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Container(
|
||||
width: 52.w,
|
||||
height: 52.h,
|
||||
padding: EdgeInsets.all(6),
|
||||
decoration: ShapeDecoration(
|
||||
color: cardColor ?? AppColor.blueLight,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: cardIconColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: SvgGenImage.vec(icon).svg(
|
||||
width: 40.w,
|
||||
height: 40.h,
|
||||
colorFilter: color ?? ColorFilter.mode(Colors.white, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
title,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.textColor),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget userInformationBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 750.h,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
'ویرایش اطلاعات هویتی',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover),
|
||||
),
|
||||
|
||||
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: [
|
||||
RTextField(
|
||||
controller: controller.nameController,
|
||||
label: 'نام',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.lastNameController,
|
||||
label: 'نام خانوادگی',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.nationalCodeController,
|
||||
label: 'شماره شناسنامه',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.nationalIdController,
|
||||
label: 'کد ملی',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return RTextField(
|
||||
controller: controller.birthdayController,
|
||||
label: 'تاریخ تولد',
|
||||
initText: data.value?.formatCompactDate() ?? '',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
onTap: () {},
|
||||
);
|
||||
}, controller.birthDate),
|
||||
|
||||
SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(),
|
||||
|
||||
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: 8,
|
||||
children: [
|
||||
Text(
|
||||
'عکس پروفایل',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
ObxValue((data) {
|
||||
return Container(
|
||||
width: Get.width,
|
||||
height: 270,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.lightGreyNormal,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: AppColor.blackLight),
|
||||
),
|
||||
child: Center(
|
||||
child: data.value == null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.fromLTRB(30, 10, 10, 30),
|
||||
child: Image.network(
|
||||
controller.userProfile.value.data?.image ?? '',
|
||||
),
|
||||
)
|
||||
: Image.file(File(data.value!.path), fit: BoxFit.cover),
|
||||
),
|
||||
);
|
||||
}, controller.selectedImage),
|
||||
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'گالری',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
onPressed: () async {
|
||||
controller.selectedImage.value = await controller.imagePicker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
imageQuality: 60,
|
||||
maxWidth: 1080,
|
||||
maxHeight: 720,
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
ROutlinedElevated(
|
||||
text: 'دوربین',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
textStyle: AppFonts.yekan20.copyWith(color: AppColor.blueNormal),
|
||||
onPressed: () async {
|
||||
controller.selectedImage.value = await controller.imagePicker.pickImage(
|
||||
source: ImageSource.camera,
|
||||
imageQuality: 60,
|
||||
maxWidth: 1080,
|
||||
maxHeight: 720,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 16,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
height: 40.h,
|
||||
text: 'ویرایش',
|
||||
isLoading: data.value,
|
||||
onPressed: () async {
|
||||
await controller.updateUserProfile();
|
||||
controller.getUserProfile();
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}, controller.isOnLoading),
|
||||
ROutlinedElevated(
|
||||
height: 40.h,
|
||||
text: 'انصراف',
|
||||
borderColor: AppColor.blueNormal,
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget changePasswordBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 400.h,
|
||||
child: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
'تغییر رمز عبور',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover),
|
||||
),
|
||||
SizedBox(),
|
||||
RTextField(
|
||||
controller: controller.oldPasswordController,
|
||||
hintText: 'رمز عبور قبلی',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'رمز عبور را وارد کنید';
|
||||
} else if (controller.userProfile.value.data?.password != value) {
|
||||
return 'رمز عبور صحیح نیست';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.newPasswordController,
|
||||
hintText: 'رمز عبور جدید',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'رمز عبور را وارد کنید';
|
||||
} else if (value.length < 6) {
|
||||
return 'رمز عبور باید بیش از 6 کارکتر باشد.';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.retryNewPasswordController,
|
||||
hintText: 'تکرار رمز عبور جدید',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'رمز عبور را وارد کنید';
|
||||
} else if (value.length < 6) {
|
||||
return 'رمز عبور باید بیش از 6 کارکتر باشد.';
|
||||
} else if (controller.newPasswordController.text != value) {
|
||||
return 'رمز عبور جدید یکسان نیست';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
|
||||
SizedBox(),
|
||||
|
||||
Row(
|
||||
spacing: 16,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
RElevated(
|
||||
height: 40.h,
|
||||
text: 'ویرایش',
|
||||
onPressed: () async {
|
||||
if (controller.formKey.currentState?.validate() != true) {
|
||||
return;
|
||||
}
|
||||
await controller.updatePassword();
|
||||
controller.getUserProfile();
|
||||
controller.clearPasswordForm();
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
ROutlinedElevated(
|
||||
height: 40.h,
|
||||
text: 'انصراف',
|
||||
borderColor: AppColor.blueNormal,
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget exitBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 220.h,
|
||||
child: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text('خروج', style: AppFonts.yekan16Bold.copyWith(color: AppColor.error)),
|
||||
SizedBox(),
|
||||
Text(
|
||||
'آیا مطمئن هستید که میخواهید از حساب کاربری خود خارج شوید؟',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
SizedBox(),
|
||||
|
||||
Row(
|
||||
spacing: 16,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
RElevated(
|
||||
height: 40.h,
|
||||
text: 'خروج',
|
||||
backgroundColor: AppColor.error,
|
||||
onPressed: () async {
|
||||
await Future.wait([
|
||||
controller.tokenService.deleteModuleTokens(Module.chicken),
|
||||
controller.gService.clearSelectedModule(),
|
||||
]).then((value) async {
|
||||
await removeChickenDI();
|
||||
Get.offAllNamed("/moduleList");
|
||||
});
|
||||
},
|
||||
),
|
||||
ROutlinedElevated(
|
||||
height: 40.h,
|
||||
text: 'انصراف',
|
||||
borderColor: AppColor.blueNormal,
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget rolesWidget() {
|
||||
return ObxValue((data) {
|
||||
if (data.value.status == ResourceStatus.loading) {
|
||||
return CupertinoActivityIndicator();
|
||||
} else if (data.value.status == ResourceStatus.error) {
|
||||
return ErrorWidget('خطا در دریافت اطلاعات کاربر');
|
||||
} else if (data.value.status == ResourceStatus.success) {
|
||||
List<String>? item = data.value.data?.roles;
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w),
|
||||
physics: BouncingScrollPhysics(),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 8.w,
|
||||
children: List.generate(item?.length ?? 0, (index) {
|
||||
Map tmpRole = getFaUserRoleWithOnTap(item?[index]);
|
||||
return CustomChip(
|
||||
isSelected: controller.gService.getRoute(Module.chicken) == tmpRole.values.first,
|
||||
title: tmpRole.keys.first,
|
||||
index: index,
|
||||
onTap: (int p1) {
|
||||
controller.changeUserRole(tmpRole.values.first);
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
}, controller.userLocal);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class RoleLogic extends GetxController {
|
||||
TokenStorageService tokenService = Get.find<TokenStorageService>();
|
||||
GService gService = Get.find<GService>();
|
||||
RxList<String> roles = <String>[].obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
List<String> items = tokenService.getUserLocal(Module.chicken)!.roles ?? [];
|
||||
if (items.isNotEmpty) {
|
||||
roles.assignAll(items);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/common/fa_user_role.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class RolePage extends GetView<RoleLogic> {
|
||||
const RolePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
child: Column(
|
||||
children: [
|
||||
Assets.images.selectRole.image(height: 212.h, width: Get.width.w, fit: BoxFit.cover),
|
||||
ObxValue((data) {
|
||||
return Expanded(
|
||||
child: GridView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3,
|
||||
mainAxisSpacing: 12.h,
|
||||
crossAxisSpacing: 12.w,
|
||||
childAspectRatio: 2,
|
||||
),
|
||||
itemCount: data.length,
|
||||
hitTestBehavior: HitTestBehavior.opaque,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
Map role = getFaUserRoleWithOnTap(data[index]);
|
||||
return roleCard(
|
||||
title: role.keys.first,
|
||||
onTap: () async {
|
||||
try {
|
||||
String route = role.values.first;
|
||||
await controller.gService.saveRoute(Module.chicken, route);
|
||||
|
||||
await controller.gService.saveRole(Module.chicken, data[index]);
|
||||
Get.offAllNamed(route);
|
||||
} catch (e) {
|
||||
eLog(
|
||||
"احتمالا در\n ``getFaUserRoleWithOnTap`` \nروت اش را تعریف نکردی 👻👻 ==>$e ",
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}, controller.roles),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget roleCard({required String title, Function()? onTap, int? width, int? height}) {
|
||||
return Container(
|
||||
width: width?.w ?? 128.w,
|
||||
height: height?.h ?? 48.h,
|
||||
margin: EdgeInsets.all(8.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
border: Border.all(color: AppColor.blueNormal, width: 1.w),
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
child: Center(
|
||||
child: Text(
|
||||
title,
|
||||
style: AppFonts.yekan12Bold.copyWith(color: AppColor.blueNormal),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class KillHouseActionLogic extends GetxController {
|
||||
List<GlassMorphismCardItem> items = [
|
||||
GlassMorphismCardItem(
|
||||
title: "ثبت درخواست",
|
||||
icon: Assets.vec.submitRequestSvg.path,
|
||||
route: ChickenRoutes.submitRequestKillHouse,
|
||||
navId: killHouseActionKey,
|
||||
),
|
||||
GlassMorphismCardItem(
|
||||
title: "انبار و توزیع",
|
||||
icon: Assets.vec.warehouseDistributionSvg.path,
|
||||
route: ChickenRoutes.initWarehouseAndDistribution,
|
||||
),
|
||||
GlassMorphismCardItem(
|
||||
title: "سفارشات دریافتی",
|
||||
icon: Assets.vec.ordersReceivedSvg.path,
|
||||
route: '',
|
||||
),
|
||||
GlassMorphismCardItem(
|
||||
title: "خرید مستقیم",
|
||||
icon: Assets.vec.directPurchaseSvg.path,
|
||||
route: '',
|
||||
),
|
||||
GlassMorphismCardItem(
|
||||
title: "تخصیص خودرو",
|
||||
icon: Assets.vec.carAllocationSvg.path,
|
||||
route: '',
|
||||
),
|
||||
GlassMorphismCardItem(
|
||||
title: "ورود اطلاعات بار",
|
||||
icon: Assets.vec.enterCargoInformationSvg.path,
|
||||
route: '',
|
||||
),
|
||||
GlassMorphismCardItem(
|
||||
title: "مدیریت بارها",
|
||||
icon: Assets.vec.managementBarsSvg.path,
|
||||
route: '',
|
||||
),
|
||||
];
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
// TODO: implement onReady
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class KillHouseActionPage extends GetView<KillHouseActionLogic> {
|
||||
const KillHouseActionPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
child: GlassMorphismGrid(
|
||||
items: controller.items,
|
||||
onTap: (item) {
|
||||
Get.toNamed(item.route, id: item.navId);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/broadcast_price/broadcast_price.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/data/repositories/kill_house/kill_house_repository.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/pages.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class KillHouseRootLogic extends GetxController {
|
||||
RxInt currentPage = 1.obs;
|
||||
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
late KillHouseRepository killHouseRepository;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
killHouseRepository = diChicken.get<KillHouseRepository>();
|
||||
}
|
||||
|
||||
final pages = [
|
||||
Navigator(
|
||||
key: Get.nestedKey(killHouseActionKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == ChickenRoutes.actionKillHouse,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
Container(color: Colors.deepPurpleAccent.withAlpha(50)),
|
||||
ProfilePage(),
|
||||
];
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
// TODO: implement onReady
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void changePage(int i) {
|
||||
currentPage.value = i;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class KillHouseRootPage extends GetView<KillHouseRootLogic> {
|
||||
const KillHouseRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ObxValue((data) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
isFullScreen: true,
|
||||
scrollable: true,
|
||||
child: Stack(
|
||||
children: [
|
||||
IndexedStack(children: controller.pages, index: data.value),
|
||||
Positioned(
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
child: RBottomNavigation(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
items: [
|
||||
RBottomNavigationItem(
|
||||
label: 'عملیات',
|
||||
icon: Assets.vec.settingSvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
/* Get.nestedKey(
|
||||
poultrySecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
poultryFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);*/
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
/* Get.nestedKey(
|
||||
poultryFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
poultryThirdKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);*/
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 2,
|
||||
onTap: () {
|
||||
/* Get.nestedKey(
|
||||
poultryFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
poultrySecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);*/
|
||||
controller.changePage(2);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.currentPage);
|
||||
}
|
||||
}
|
||||
@@ -1,378 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
Widget addKillRequestBottomSheet(SubmitRequestKillHouseLogic controller) {
|
||||
return ObxValue(
|
||||
(data) => AnimatedContainer(
|
||||
duration: Duration(milliseconds: 300),
|
||||
height: data.value ? 680.h : 580.h,
|
||||
child: BaseBottomSheet(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(width: 12),
|
||||
Text(
|
||||
"ثبت درخواست کشتار",
|
||||
style: AppFonts.yekan18Bold.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
Divider(),
|
||||
SizedBox(height: 8),
|
||||
|
||||
InformationTag(
|
||||
data: InformationTagData(
|
||||
labelTitle: 'قیمت روز مرغ (${Jalali.now().formatCompactDate()})',
|
||||
labelTitleStyle: AppFonts.yekan14,
|
||||
isLoading: false,
|
||||
height: 40.h,
|
||||
value: controller.commissionPrices.chickenAveragePrice.separatedByComma.addReal,
|
||||
valueStyle: AppFonts.yekan14,
|
||||
borderColor: AppColor.greenNormal,
|
||||
radiusWidth: 1,
|
||||
valueBgColor: Colors.white,
|
||||
labelGradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [AppColor.greenLightActive, Colors.white],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
ResourceOverlayDropdown(
|
||||
height: 40.h,
|
||||
items: controller.killHouseList,
|
||||
itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
|
||||
labelBuilder: (selected) => Text(selected?.name ?? 'محل کشتار'),
|
||||
onChanged: controller.setKillHouse,
|
||||
),
|
||||
|
||||
SizedBox(height: 8),
|
||||
|
||||
UnitTextField(
|
||||
controller: controller.breedCountController,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLines: 1,
|
||||
minLines: 1,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
unit: 'قطعه',
|
||||
hint: 'حجم کشتار',
|
||||
initialValue: 0.separatedByComma,
|
||||
),
|
||||
|
||||
SizedBox(height: 8),
|
||||
ResourceOverlayDropdown(
|
||||
items: controller.timeFrameOfKilling,
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'زمان دریافت'),
|
||||
onChanged: (selected) => controller.setTimeFrameOfKilling(selected),
|
||||
),
|
||||
|
||||
SizedBox(height: 8),
|
||||
RTextField(
|
||||
controller: controller.dateOfSlaughterTextEditor,
|
||||
hintText: 'تاریخ کشتار',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Assets.vec.calendarSvg.svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.bgIcon, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
readonly: true,
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
modalDatePicker(
|
||||
onDateSelected: (value) {
|
||||
controller.dateOfSlaughterTextEditor.text = value.formatCompactDate();
|
||||
controller.dateOfSlaughter = value;
|
||||
},
|
||||
),
|
||||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
ignoreSafeArea: false,
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
buildAnimatedLabelContainer(controller),
|
||||
SizedBox(height: 8),
|
||||
Container(
|
||||
height: 40.h,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.blueDark, width: 0.5),
|
||||
),
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {
|
||||
if (controller.isAgreedUndertaking.value == false) {
|
||||
undertakingDialog(controller);
|
||||
}
|
||||
else{
|
||||
controller.toggleAgreeUndertaking(false);
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
spacing: 2,
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return Checkbox(
|
||||
value: data.value,
|
||||
onChanged: (value) {
|
||||
if (controller.isAgreedUndertaking.value == false) {
|
||||
undertakingDialog(controller);
|
||||
}
|
||||
else {
|
||||
controller.toggleAgreeUndertaking(false);
|
||||
}
|
||||
},
|
||||
);
|
||||
}, controller.isAgreedUndertaking),
|
||||
|
||||
Text(
|
||||
"با تعهدنامه موافق هستم !",
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.blueDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Container(
|
||||
height: 40.h,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.mediumGrey, width: 1),
|
||||
),
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => controller.toggleAgreeSmsNotification(),
|
||||
child: Row(
|
||||
spacing: 2,
|
||||
children: [
|
||||
ObxValue((selected) {
|
||||
return Checkbox(
|
||||
value: selected.value,
|
||||
onChanged: (value) => controller.toggleAgreeSmsNotification(),
|
||||
);
|
||||
}, controller.isAgreedSmsNotification),
|
||||
Text(
|
||||
"دریافت پیامک اطلاع رسانی",
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Row(
|
||||
spacing: 16,
|
||||
mainAxisAlignment: .center,
|
||||
children: [
|
||||
RElevated(
|
||||
width: 160.w,
|
||||
height: 40.h,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
text: 'ثبت',
|
||||
onPressed: () async {
|
||||
await controller.submitKillRequest();
|
||||
},
|
||||
),
|
||||
|
||||
ROutlinedElevated(
|
||||
height: 40,
|
||||
text: 'انصراف',
|
||||
borderColor: AppColor.redNormal,
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
controller.isBreedWeightSelected,
|
||||
);
|
||||
}
|
||||
|
||||
void undertakingDialog(SubmitRequestKillHouseLogic controller) {
|
||||
Get.dialog(
|
||||
AlertDialog(
|
||||
title: Text("تعهد نامه", textAlign: TextAlign.center),
|
||||
titleTextStyle: AppFonts.yekan20.copyWith(color: AppColor.textColor3),
|
||||
content: Column(
|
||||
mainAxisSize: .min,
|
||||
spacing: 10,
|
||||
children: [
|
||||
Text(
|
||||
"اینجانب ${controller.baseLogic.userProfile.value.data?.fullname} موافقت خود را نسبت به موارد ذکر شده اعلام می نمایم.",
|
||||
style: AppFonts.yekan13.copyWith(color: AppColor.textColor3),
|
||||
),
|
||||
Text(
|
||||
"✅ بر اساس این توافق نامه در صورت لغو کشتار جریمه خواهم شد.",
|
||||
style: AppFonts.yekan13.copyWith(color: AppColor.textColor3),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: RElevated(
|
||||
text: 'موافقم',
|
||||
height: 32.h,
|
||||
onPressed: () {
|
||||
controller.toggleAgreeUndertaking(true);
|
||||
Get.back();
|
||||
},
|
||||
textStyle: AppFonts.yekan20Bold.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ROutlinedElevated(
|
||||
text: 'رد',
|
||||
textStyle: AppFonts.yekan20.copyWith(color: AppColor.redNormal),
|
||||
height: 32.h,
|
||||
onPressed: () {
|
||||
controller.toggleAgreeUndertaking(false);
|
||||
Get.back();
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildAnimatedLabelContainer(SubmitRequestKillHouseLogic controller) {
|
||||
return ObxValue((data) {
|
||||
return AnimatedCrossFade(
|
||||
firstChild: GestureDetector(
|
||||
onTap: () {
|
||||
controller.toggleBreedWeightSelection();
|
||||
},
|
||||
child: Container(
|
||||
height: 40.h,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.mediumGrey, width: 0.5),
|
||||
),
|
||||
child: Row(
|
||||
spacing: 7,
|
||||
children: [
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Switch(
|
||||
value: data.value,
|
||||
onChanged: (data) => controller.toggleBreedWeightSelection(),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"تعیین نژاد / وزن مرغ",
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
secondChild: SizedBox(
|
||||
height: 140.h,
|
||||
child: Stack(
|
||||
fit: StackFit.passthrough,
|
||||
children: [
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 121.h,
|
||||
padding: EdgeInsets.fromLTRB(8.r, 18.r, 8.r, 8.r),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.mediumGrey, width: (0.5).w),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
ResourceOverlayDropdown(
|
||||
items: controller.chickenBreedList,
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'نژاد مرغ'),
|
||||
onChanged: (selected) => controller.setChickenBreed(selected),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.chickenWeight,
|
||||
label: ' وزن مرغ (کیلوگرم) ',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: 7,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.toggleBreedWeightSelection();
|
||||
},
|
||||
child: Container(
|
||||
height: 30.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.w, vertical: 4.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.mediumGrey, width: 0.5),
|
||||
),
|
||||
child: Row(
|
||||
spacing: 7,
|
||||
children: [
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Switch(
|
||||
value: data.value,
|
||||
onChanged: (_) => controller.toggleBreedWeightSelection(),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"تعیین نژاد / وزن مرغ",
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
crossFadeState: data.value ? CrossFadeState.showSecond : CrossFadeState.showFirst,
|
||||
duration: Duration(milliseconds: 500),
|
||||
);
|
||||
}, controller.isBreedWeightSelected);
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/kill_house_module/register_request/request/kill_request_response.dart';
|
||||
import 'package:rasadyar_chicken/data/models/kill_house_module/register_request/response/chicken_commission_prices/chicken_commission_prices.dart';
|
||||
import 'package:rasadyar_chicken/data/models/kill_house_module/register_request/response/kill_house/kill_house_response.dart';
|
||||
import 'package:rasadyar_chicken/data/models/kill_house_module/register_request/response/kill_request_list/kill_request_list.dart'
|
||||
as listModel;
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SubmitRequestKillHouseLogic extends GetxController {
|
||||
ChickenBaseLogic baseLogic = Get.find<ChickenBaseLogic>();
|
||||
RxList<String> routesName = ["عملیات", "ثبت درخواست کشتار"].obs;
|
||||
late KillHouseRootLogic rootLogic;
|
||||
|
||||
RxInt expandedItemIndex = RxInt(-1);
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
RxBool isBreedWeightSelected = false.obs;
|
||||
|
||||
TextEditingController breedCountController = TextEditingController();
|
||||
TextEditingController dateOfSlaughterTextEditor = TextEditingController();
|
||||
Jalali dateOfSlaughter = Jalali.now();
|
||||
TextEditingController chickenWeight = TextEditingController();
|
||||
|
||||
Resource<List<String>> timeFrameOfKilling = Resource.success([
|
||||
'12 - 14',
|
||||
'14 - 16',
|
||||
'16 - 18',
|
||||
'18 - 20',
|
||||
'20 - 22',
|
||||
'22 - 24',
|
||||
]);
|
||||
|
||||
RxString timeFrameOfKillingSelected = ''.obs;
|
||||
|
||||
Resource<List<String>> chickenBreedList = Resource.success([
|
||||
'آرین',
|
||||
'راس',
|
||||
'آربراکوز (آیلاس)',
|
||||
'کاب',
|
||||
'هوبارد',
|
||||
'ترکیبی',
|
||||
'وارداتی',
|
||||
]);
|
||||
|
||||
RxString chickenBreedSelected = ''.obs;
|
||||
RxBool isAgreedUndertaking = false.obs;
|
||||
RxBool isAgreedSmsNotification = false.obs;
|
||||
|
||||
KillHouseResponse? selectedKillHouse;
|
||||
late Resource<List<KillHouseResponse>> killHouseList;
|
||||
late ChickenCommissionPrices commissionPrices;
|
||||
|
||||
Rx<Resource<List<listModel.KillRequestList>>> killRequestList = Rx(
|
||||
Resource.initial(),
|
||||
);
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
rootLogic = Get.find<KillHouseRootLogic>();
|
||||
|
||||
getCommissionPrice();
|
||||
getKillHouseList();
|
||||
getListOfKillRequests();
|
||||
dateOfSlaughterTextEditor.text = Jalali.now().formatCompactDate();
|
||||
dateOfSlaughter = Jalali.now();
|
||||
chickenWeight.text = '2.7';
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void onRefresh() {
|
||||
getCommissionPrice();
|
||||
getKillHouseList();
|
||||
getListOfKillRequests();
|
||||
}
|
||||
|
||||
void toggleExpandedItem(int index) {
|
||||
if (expandedItemIndex.value == index) {
|
||||
expandedItemIndex.value = -1;
|
||||
} else {
|
||||
expandedItemIndex.value = index;
|
||||
}
|
||||
}
|
||||
|
||||
void toggleBreedWeightSelection() {
|
||||
isBreedWeightSelected.value = !isBreedWeightSelected.value;
|
||||
}
|
||||
|
||||
void clearPage() {
|
||||
expandedItemIndex.value = -1;
|
||||
isBreedWeightSelected.value = false;
|
||||
isAgreedUndertaking.value = false;
|
||||
isAgreedSmsNotification.value = false;
|
||||
breedCountController.clear();
|
||||
dateOfSlaughter = Jalali.now();
|
||||
dateOfSlaughterTextEditor.text = Jalali.now().formatCompactDate();
|
||||
chickenWeight.text = '2.7';
|
||||
timeFrameOfKillingSelected.value = '';
|
||||
chickenBreedSelected.value = '';
|
||||
}
|
||||
|
||||
void setKillHouse(KillHouseResponse killHouse) {
|
||||
selectedKillHouse = killHouse;
|
||||
iLog(selectedKillHouse?.key);
|
||||
}
|
||||
|
||||
void setTimeFrameOfKilling(String timeFrame) {
|
||||
timeFrameOfKillingSelected.value = timeFrame;
|
||||
}
|
||||
|
||||
void setChickenBreed(String breed) {
|
||||
chickenBreedSelected.value = breed;
|
||||
}
|
||||
|
||||
void toggleAgreeUndertaking(bool item) {
|
||||
isAgreedUndertaking.value = item;
|
||||
}
|
||||
|
||||
void toggleAgreeSmsNotification() {
|
||||
isAgreedSmsNotification.value = !isAgreedSmsNotification.value;
|
||||
}
|
||||
|
||||
Future<void> getKillHouseList() async {
|
||||
await safeCall(
|
||||
call: () => rootLogic.killHouseRepository.getKillHouseList(
|
||||
token: rootLogic.tokenService.accessToken.value ?? '',
|
||||
),
|
||||
onSuccess: (result) => killHouseList = Resource.success(result ?? []),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getCommissionPrice() async {
|
||||
await safeCall(
|
||||
call: () => rootLogic.killHouseRepository.getCommissionPrice(
|
||||
token: rootLogic.tokenService.accessToken.value ?? '',
|
||||
),
|
||||
onSuccess: (result) => commissionPrices =
|
||||
result ?? ChickenCommissionPrices(chickenAveragePrice: 0),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> submitKillRequest() async {
|
||||
KillRequestResponse request = KillRequestResponse(
|
||||
killCapacity: int.parse(breedCountController.text),
|
||||
reciveTime: timeFrameOfKillingSelected.value,
|
||||
reciveDate: dateOfSlaughter
|
||||
.toDateTime()
|
||||
.formattedGregorianDateWithoutMillisecond,
|
||||
lowWeight: false,
|
||||
highWeight: false,
|
||||
indexWeight: double.parse(chickenWeight.text),
|
||||
chickenBreed: chickenBreedSelected.value,
|
||||
cash: true,
|
||||
credit: false,
|
||||
smsPayment: isAgreedSmsNotification.value,
|
||||
killHouseKey: selectedKillHouse?.key,
|
||||
killerKillHouseKey: null,
|
||||
role: 'KillHouse',
|
||||
);
|
||||
await safeCall(
|
||||
showError: true,
|
||||
|
||||
call: () => rootLogic.killHouseRepository.submitKillHouseRequest(
|
||||
token: rootLogic.tokenService.accessToken.value ?? '',
|
||||
data: request,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
onRefresh();
|
||||
Get.back();
|
||||
Future.delayed(
|
||||
Duration(seconds: 3),
|
||||
() => defaultShowSuccessMessage("عملیات با موفقیت انجام شد"),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getListOfKillRequests() async {
|
||||
await safeCall(
|
||||
showError: true,
|
||||
call: () => rootLogic.killHouseRepository.getListKillRequest(
|
||||
token: rootLogic.tokenService.accessToken.value ?? '',
|
||||
queryParameters: buildRawQueryParams(
|
||||
role: 'KillHouse',
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result == null || result.isEmpty) {
|
||||
killRequestList.value = Resource.empty();
|
||||
return;
|
||||
}
|
||||
killRequestList.value = Resource.success(result);
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
killRequestList.value = Resource.error(error);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteRequest(int id) async {
|
||||
await safeCall(
|
||||
showError: true,
|
||||
|
||||
call: () => rootLogic.killHouseRepository.deleteKillRequest(
|
||||
token: rootLogic.tokenService.accessToken.value ?? '',
|
||||
requestId: id,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
onRefresh();
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/kill_house_module/register_request/response/kill_request_list/kill_request_list.dart'
|
||||
as listModel
|
||||
show KillRequestList;
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'add_request_bottom_sheet.dart';
|
||||
import 'logic.dart';
|
||||
|
||||
class SubmitRequestKillHousePage extends GetView<SubmitRequestKillHouseLogic> {
|
||||
const SubmitRequestKillHousePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasBack: true,
|
||||
hasFilter: true,
|
||||
hasSearch: true,
|
||||
onBackTap: () => Get.back(id: killHouseActionKey),
|
||||
onSearchChanged: (data) {
|
||||
//Todo
|
||||
},
|
||||
onRefresh: () async => controller.onRefresh(),
|
||||
routesWidget: ContainerBreadcrumb(rxRoutes: controller.routesName),
|
||||
child: Stack(
|
||||
fit: .expand,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
right: 13,
|
||||
left: 14,
|
||||
child: Obx(() {
|
||||
return RListView.separated(
|
||||
itemCount: controller.killRequestList.value.data?.length ?? 0,
|
||||
itemBuilder: (context, index) {
|
||||
var item = controller.killRequestList.value.data![index];
|
||||
return ObxValue((data) {
|
||||
return ExpandableListItem2(
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
onTap: () => controller.toggleExpandedItem(index),
|
||||
selected: data.value == index,
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.virtualSvg.path,
|
||||
);
|
||||
}, controller.expandedItemIndex);
|
||||
},
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8),
|
||||
resource: controller.killRequestList.value,
|
||||
);
|
||||
}),
|
||||
),
|
||||
|
||||
Positioned(
|
||||
right: 8,
|
||||
bottom: 92,
|
||||
child: RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
isScrollControlled: true,
|
||||
addKillRequestBottomSheet(controller),
|
||||
).then((value) {
|
||||
controller.clearPage();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(listModel.KillRequestList item) {
|
||||
return Row(
|
||||
children: [
|
||||
SizedBox(width: 30),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.killHouse?.name ?? 'بدون نام',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
item.createDate?.toJalali.formatCompactDate() ?? "-",
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'درخواست ${item.killCapacity}'.addCountEXT,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
'تعداد مورد تایید 150 قطعه',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Spacer(),
|
||||
Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(listModel.KillRequestList item) {
|
||||
Jalali date = item.createDate.toJalali;
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.killHouse?.name ?? 'بدون نام',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
//todo
|
||||
Text(
|
||||
'در انتظار تایید استان',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
SizedBox(width: 7),
|
||||
Assets.vec.clockSvg.svg(width: 16.w, height: 16.h),
|
||||
],
|
||||
),
|
||||
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(
|
||||
date.formatter.wN,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.textColor,
|
||||
),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${date.formatter.d} ${date.formatter.mN ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
date.formatter.y,
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${date.formatter.tHH}:${date.formatter.tMM ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'تعداد درخواست اولیه',
|
||||
value: item.killCapacity.separatedByComma.addCountEXT,
|
||||
),
|
||||
//todo
|
||||
buildRow(
|
||||
title: 'تعداد مورد تایید',
|
||||
value: item.numberOfAllocated.separatedByComma.addCountEXT,
|
||||
),
|
||||
buildRow(title: 'زمان دریافت', value: item.reciveTime ?? '-'),
|
||||
buildRow(
|
||||
title: 'تاریخ درخواستی کشتار',
|
||||
value: item.reciveDate.toJalali.formatCompactDate(),
|
||||
),
|
||||
ROutlinedElevated(
|
||||
text: 'حذف',
|
||||
height: 40.h,
|
||||
textStyle: AppFonts.yekan20.copyWith(color: AppColor.redNormal),
|
||||
isFullWidth: true,
|
||||
onPressed: () {
|
||||
buildWarningDialog(
|
||||
title: 'اخطار',
|
||||
middleText: 'آیا از حذف شدن این مورد اطمینان دارید؟',
|
||||
onConfirm: () async {
|
||||
controller.deleteRequest(item.id!);
|
||||
},
|
||||
onRefresh: () async {
|
||||
controller.onRefresh();
|
||||
},
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyLogic extends GetxController {
|
||||
List<String> routesName = ['خرید'];
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
fLog('BuyLogic onReady');
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void onPopScopTaped() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null || now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyPage
|
||||
extends GetView<WarehouseAndDistributionBuyLogic> {
|
||||
const WarehouseAndDistributionBuyPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
isBase: true,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 21.w,
|
||||
children: [
|
||||
GlassMorphismCardIcon(
|
||||
title: 'خرید داخل استان',
|
||||
vecIcon: Assets.vec.map1Svg.path,
|
||||
gradient: LinearGradient(
|
||||
colors: [Color(0xFF00E096), Color(0xFF007D5E)],
|
||||
stops: [0.0, 0.95],
|
||||
begin: AlignmentGeometry.topLeft,
|
||||
end: AlignmentGeometry.bottomRight,
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
ChickenRoutes.buysInProvinceWarehouseAndDistribution,
|
||||
id: killHouseWarehouseAndDistributionBuyKey,
|
||||
);
|
||||
},
|
||||
),
|
||||
GlassMorphismCardIcon(
|
||||
title: 'خرید خارج استان',
|
||||
vecIcon: Assets.vec.buyOutProvinceSvg.path,
|
||||
gradient: LinearGradient(
|
||||
colors: [Color(0xFF00E096), Color(0xFF007D5E)],
|
||||
stops: [0.0, 0.95],
|
||||
begin: AlignmentGeometry.topLeft,
|
||||
end: AlignmentGeometry.bottomRight,
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
ChickenRoutes.buysOutOfProvinceWarehouseAndDistribution,
|
||||
id: killHouseWarehouseAndDistributionBuyKey,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/buy/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/buy_in_province_all/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/buy_in_province_waiting/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyInProvinceLogic extends GetxController {
|
||||
RxList<String> routesName = RxList();
|
||||
RxList<int> isExpandedList = <int>[].obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
|
||||
WarehouseAndDistributionRootLogic rootLogic = Get.find<WarehouseAndDistributionRootLogic>();
|
||||
|
||||
WarehouseAndDistributionBuyLogic get buyLogic => Get.find<WarehouseAndDistributionBuyLogic>();
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
|
||||
WarehouseAndDistributionBuyInProvinceAllLogic buyAllLogic = Get.find<WarehouseAndDistributionBuyInProvinceAllLogic>();
|
||||
WarehouseAndDistributionBuyInProvinceWaitingLogic buyWaitingLogic = Get.find<WarehouseAndDistributionBuyInProvinceWaitingLogic>();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName.value = [...buyLogic.routesName, 'داخل استان'].toList();
|
||||
routesName.add(selectedSegmentIndex.value == 0 ? 'در انتظار' : 'کل خریدها');
|
||||
ever(selectedSegmentIndex, (callback) {
|
||||
routesName.removeLast();
|
||||
routesName.add(callback == 0 ? 'در انتظار' : 'کل خریدها');
|
||||
});
|
||||
|
||||
ever(fromDateFilter, (callback) => _setFromDateFilter(callback));
|
||||
ever(toDateFilter, (callback) => _setToDateFilter(callback));
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
fLog('BuyInProvinceLogic onReady');
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void _setFromDateFilter(Jalali jalali) {
|
||||
final isWaiting = selectedSegmentIndex.value == 0;
|
||||
if (isWaiting) {
|
||||
buyWaitingLogic.fromDateFilter.value = fromDateFilter.value;
|
||||
} else {
|
||||
buyAllLogic.fromDateFilter.value = fromDateFilter.value;
|
||||
}
|
||||
}
|
||||
|
||||
void _setToDateFilter(Jalali jalali) {
|
||||
final isWaiting = selectedSegmentIndex.value == 0;
|
||||
if (isWaiting) {
|
||||
buyWaitingLogic.toDateFilter.value = fromDateFilter.value;
|
||||
} else {
|
||||
buyAllLogic.toDateFilter.value = fromDateFilter.value;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> submitFilter() async {
|
||||
final isWaiting = selectedSegmentIndex.value == 0;
|
||||
if (isWaiting) {
|
||||
buyWaitingLogic.getWaitingArrivals();
|
||||
} else {
|
||||
buyAllLogic.getAllArrivals();
|
||||
}
|
||||
}
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
searchedValue.value = data?.trim();
|
||||
final isWaiting = selectedSegmentIndex.value == 0;
|
||||
if (isWaiting) {
|
||||
buyWaitingLogic.searchedValue.value = searchedValue.value;
|
||||
} else {
|
||||
buyAllLogic.searchedValue.value = searchedValue.value;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
await rootLogic.onRefresh();
|
||||
await Future.wait([buyWaitingLogic.getWaitingArrivals(), buyAllLogic.getAllArrivals()]);
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/buy_in_province_all/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/buy_in_province_waiting/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/inventory/inventory_widget.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyInProvincePage
|
||||
extends GetView<WarehouseAndDistributionBuyInProvinceLogic> {
|
||||
const WarehouseAndDistributionBuyInProvincePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routesWidget: ContainerBreadcrumb(rxRoutes: controller.routesName),
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
hasBack: true,
|
||||
backId: killHouseWarehouseAndDistributionBuyKey,
|
||||
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(filterBottomSheet());
|
||||
},
|
||||
onRefresh: controller.onRefresh,
|
||||
child: Column(
|
||||
spacing: 4.h,
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return InventoryWidget(inventoryModel: data.value);
|
||||
}, controller.rootLogic.inventoryModel),
|
||||
|
||||
segmentWidget(),
|
||||
ObxValue((index) {
|
||||
return Expanded(
|
||||
child: index.value == 0
|
||||
? WarehouseAndDistributionBuyInProvinceWaitingPage()
|
||||
: WarehouseAndDistributionBuyInProvinceAllPage(),
|
||||
);
|
||||
}, controller.selectedSegmentIndex),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Padding segmentWidget() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RSegment(
|
||||
children: ['وارد شده به انبار', 'کل خریدها'],
|
||||
selectedIndex: 0,
|
||||
borderColor: const Color(0xFFB4B4B4),
|
||||
selectedBorderColor: AppColor.blueNormal,
|
||||
selectedBackgroundColor: AppColor.blueLight,
|
||||
onSegmentSelected: (index) =>
|
||||
controller.selectedSegmentIndex.value = index,
|
||||
backgroundColor: AppColor.whiteGreyNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 200,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
'فیلترها',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
date: controller.fromDateFilter,
|
||||
onChanged: (jalali) =>
|
||||
controller.fromDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
isFrom: false,
|
||||
date: controller.toDateFilter,
|
||||
onChanged: (jalali) => controller.toDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
RElevated(
|
||||
text: 'اعمال فیلتر',
|
||||
|
||||
isFullWidth: true,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
onPressed: () {
|
||||
controller.submitFilter();
|
||||
Get.back();
|
||||
},
|
||||
height: 40,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/steward_allocation/steward_allocation_request.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyInProvinceAllLogic extends GetxController {
|
||||
RxInt isExpandedListIndex = (-1).obs;
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
RxMap<String, bool> isLoadingConfirmMap = RxMap();
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
|
||||
WarehouseAndDistributionRootLogic rootLogic =
|
||||
Get.find<WarehouseAndDistributionRootLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<WaitingArrivalModel>>> allProduct =
|
||||
Resource<PaginationModel<WaitingArrivalModel>>.loading().obs;
|
||||
|
||||
TextEditingController weightController = TextEditingController();
|
||||
TextEditingController countController = TextEditingController();
|
||||
TextEditingController lossController = TextEditingController();
|
||||
TextEditingController approvedWithOtpController = TextEditingController();
|
||||
|
||||
RxBool approvedWithOtpCode = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
getAllArrivals();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getAllArrivals(),
|
||||
time: Duration(milliseconds: 2000),
|
||||
);
|
||||
super.onReady();
|
||||
ever(approvedWithOtpCode, (callback) {
|
||||
if (callback == false) {
|
||||
approvedWithOtpController.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> getAllArrivals([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
allProduct.value =
|
||||
Resource<PaginationModel<WaitingArrivalModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
safeCall(
|
||||
// call: () async => await rootLogic.chickenRepository.getWaitingArrivals(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// queryParameters: buildQueryParams(
|
||||
// queryParams: {'type': 'all'},
|
||||
// pageSize: 20,
|
||||
// page: currentPage.value,
|
||||
// search: 'filter',
|
||||
// role: 'Steward',
|
||||
// value: searchedValue.value,
|
||||
// fromDate: fromDateFilter.value.toDateTime(),
|
||||
// toDate: toDateFilter.value.toDateTime(),
|
||||
// ),
|
||||
// ),
|
||||
call: () async => null as PaginationModel<WaitingArrivalModel>?,
|
||||
onSuccess: (res) async {
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
// TODO: Fix - res type issues
|
||||
// if ((res?.count ?? 0) == 0) {
|
||||
// allProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.empty();
|
||||
// } else {
|
||||
// allProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.success(
|
||||
// PaginationModel<WaitingArrivalModel>(
|
||||
// count: res?.count ?? 0,
|
||||
// next: res?.next,
|
||||
// previous: res?.previous,
|
||||
// results: [...(allProduct.value.data?.results ?? []), ...(res?.results ?? [])],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
allProduct.value =
|
||||
Resource<PaginationModel<WaitingArrivalModel>>.empty();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> acceptEntries(WaitingArrivalModel model) async {
|
||||
var request = StewardAllocationRequest(
|
||||
allocationKey: model.key,
|
||||
checkAllocation: true,
|
||||
state: 'accepted',
|
||||
receiverRealNumberOfCarcasses: model.realNumberOfCarcasses ?? 0,
|
||||
receiverRealWeightOfCarcasses: model.realWeightOfCarcasses?.toInt() ?? 0,
|
||||
registrationCode: approvedWithOtpCode.value
|
||||
? int.parse(approvedWithOtpController.text)
|
||||
: null,
|
||||
weightLossOfCarcasses: model.weightLossOfCarcasses?.toInt() ?? 0,
|
||||
).toJson();
|
||||
request.removeWhere((key, value) => value == null);
|
||||
|
||||
safeCall(
|
||||
showError: true,
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
// call: () async => await rootLogic.chickenRepository.setSateForArrivals(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// request: request,
|
||||
// ),
|
||||
call: () async {},
|
||||
onSuccess: (result) {
|
||||
getAllArrivals();
|
||||
rootLogic.onRefresh();
|
||||
clearApprovedController();
|
||||
toggleExpansion();
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> denyEntries(WaitingArrivalModel model) async {
|
||||
var request = StewardAllocationRequest(
|
||||
allocationKey: model.key,
|
||||
checkAllocation: true,
|
||||
state: 'rejected',
|
||||
).toJson();
|
||||
request.removeWhere((key, value) => value == null);
|
||||
|
||||
safeCall(
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
// call: () async => await rootLogic.chickenRepository.setSateForArrivals(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// request: request,
|
||||
// ),
|
||||
call: () async {},
|
||||
onError: (error, stackTrace) {
|
||||
eLog(error);
|
||||
},
|
||||
onSuccess: (result) {
|
||||
getAllArrivals();
|
||||
rootLogic.onRefresh();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
String getVecPathItem(String? item) {
|
||||
switch (item) {
|
||||
case 'pending':
|
||||
return Assets.vec.timerSvg.path;
|
||||
case 'accepted':
|
||||
return Assets.vec.checkSquareSvg.path;
|
||||
case 'rejected':
|
||||
return Assets.vec.closeCircleSvg.path;
|
||||
default:
|
||||
return Assets.vec.timerSvg.path;
|
||||
}
|
||||
}
|
||||
|
||||
void clearApprovedController() {
|
||||
weightController.clear();
|
||||
countController.clear();
|
||||
lossController.clear();
|
||||
approvedWithOtpController.clear();
|
||||
approvedWithOtpCode.value = false;
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (isExpandedListIndex.value == index || index == null) {
|
||||
isExpandedListIndex.value = -1;
|
||||
} else {
|
||||
isExpandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
|
||||
Color getLabelColor(String? receiverState) {
|
||||
if (receiverState == 'pending') {
|
||||
return AppColor.yellowNormal2;
|
||||
}
|
||||
return AppColor.mediumGreyDarkHover;
|
||||
}
|
||||
}
|
||||
@@ -1,381 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/string_utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyInProvinceAllPage extends GetView<WarehouseAndDistributionBuyInProvinceAllLogic> {
|
||||
const WarehouseAndDistributionBuyInProvinceAllPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
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),
|
||||
labelColor: getLabelColor(item.receiverState),
|
||||
labelIcon: controller.getVecPathItem(item.receiverState),
|
||||
labelIconColor: controller.getLabelColor(item.receiverState),
|
||||
);
|
||||
}, controller.isExpandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getAllArrivals(true),
|
||||
);
|
||||
}, controller.allProduct),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(WaitingArrivalModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.toSteward?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.date?.formattedJalaliDate ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 6,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: item.product?.name?.contains('مرغ گرم') ?? false,
|
||||
child: Assets.vec.hotChickenSvg.svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item.weightOfCarcasses?.separatedByCommaFa.addKg ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
textDirection: TextDirection.ltr,
|
||||
style: AppFonts.yekan12Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
item.toSteward?.guildsName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(WaitingArrivalModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.toSteward?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
item.receiverState?.faItem ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
SizedBox(width: 7),
|
||||
SvgGenImage.vec(controller.getVecPathItem(item.receiverState)).svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.darkGreyDark, BlendMode.srcIn),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'N/A',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(title: 'مشخصات فروشنده', value: item.toSteward?.user?.fullname ?? 'N/A'),
|
||||
buildRow(
|
||||
title: 'تلفن فروشنده',
|
||||
value: item.toSteward?.user?.mobile ?? 'N/A',
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
buildRow(title: 'نوع تخصیص', value: item.allocationType?.faAllocationType ?? 'N/A'),
|
||||
buildRow(title: ' سهمیه', value: item.quota?.faTitle ?? 'N/A'),
|
||||
buildRow(title: 'محصول', value: item.product?.name ?? 'N/A'),
|
||||
buildRow(
|
||||
title: 'وزن خریداری شده',
|
||||
value: item.weightOfCarcasses?.separatedByCommaFa ?? 'N/A',
|
||||
valueLabel: 'کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلوگرم',
|
||||
titleLabel: (item.approvedPriceStatus ?? false) ? 'مصوب' : 'آزاد',
|
||||
titleLabelStyle: AppFonts.yekan14Bold.copyWith(color: AppColor.greenNormal),
|
||||
value: item.amount?.separatedByCommaFa ?? 'N/A',
|
||||
valueLabel: 'ریال',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت کل',
|
||||
value: item.totalAmount?.separatedByCommaFa ?? 'N/A',
|
||||
valueLabel: 'ریال',
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: item.receiverState == 'pending',
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
text: 'تایید',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
isLoading: data[item.key!] ?? false,
|
||||
onPressed: () async {
|
||||
await Get.bottomSheet(
|
||||
conformationBottomSheet(item),
|
||||
isScrollControlled: true,
|
||||
).then((value) {
|
||||
Get.back();
|
||||
controller.clearApprovedController();
|
||||
});
|
||||
},
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
);
|
||||
}, controller.isLoadingConfirmMap),
|
||||
ROutlinedElevated(
|
||||
text: 'رد',
|
||||
textStyle: AppFonts.yekan20.copyWith(color: AppColor.redNormal),
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
buildWarningDialog(
|
||||
title: 'اخطار',
|
||||
middleText: 'آیا از رد شدن این مورد اطمینان دارید؟',
|
||||
onConfirm: () => controller.denyEntries(item),
|
||||
onRefresh: () => controller.getAllArrivals(),
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Color getLabelColor(String? item) {
|
||||
switch (item) {
|
||||
case 'pending':
|
||||
return AppColor.blueLight;
|
||||
case 'accepted':
|
||||
return AppColor.greenLightHover;
|
||||
case 'rejected':
|
||||
return AppColor.redLightHover;
|
||||
default:
|
||||
return AppColor.blueLight;
|
||||
}
|
||||
}
|
||||
|
||||
Widget conformationBottomSheet(WaitingArrivalModel item) {
|
||||
controller.weightController.text = item.weightOfCarcasses.separatedByComma;
|
||||
return BaseBottomSheet(
|
||||
height: 430.h,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
RTextField(
|
||||
label: 'وزن(کیلوگرم)',
|
||||
controller: controller.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
RTextField(
|
||||
label: 'حجم(قطعه)',
|
||||
controller: controller.countController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
RTextField(
|
||||
label: 'افت وزن(کیلوگرم)',
|
||||
controller: controller.lossController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
|
||||
Text('تایید ', style: AppFonts.yekan16Bold.copyWith(color: AppColor.textColor)),
|
||||
ObxValue((data) {
|
||||
return Column(
|
||||
children: [
|
||||
RadioGroup(
|
||||
groupValue: data.value,
|
||||
onChanged: (value) {
|
||||
controller.approvedWithOtpCode.value = value ?? false;
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
radioRow(
|
||||
value: true,
|
||||
label: ' با کد احراز',
|
||||
onTap: () {
|
||||
controller.approvedWithOtpCode.value = true;
|
||||
},
|
||||
),
|
||||
radioRow(
|
||||
value: false,
|
||||
label: 'بدون کد احراز',
|
||||
onTap: () {
|
||||
controller.approvedWithOtpCode.value = false;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
child: RTextField(
|
||||
controller: controller.approvedWithOtpController,
|
||||
label: 'کد احراز',
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
visible: data.value,
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.approvedWithOtpCode),
|
||||
SizedBox(height: 30.h),
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
enabled: controller.approvedWithOtpCode.value
|
||||
? controller.approvedWithOtpController.text.isNotEmpty
|
||||
: true,
|
||||
text: 'تایید',
|
||||
onPressed: () async {
|
||||
await controller.acceptEntries(item);
|
||||
},
|
||||
isFullWidth: true,
|
||||
);
|
||||
}, controller.approvedWithOtpCode),
|
||||
SizedBox(height: 20.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget radioRow({
|
||||
required bool value,
|
||||
required String label,
|
||||
TextStyle? textStyle,
|
||||
GestureTapCallback? onTap,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: value),
|
||||
Text(label, style: textStyle ?? AppFonts.yekan16.copyWith(color: AppColor.textColor)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/steward_allocation/steward_allocation_request.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyInProvinceWaitingLogic extends GetxController {
|
||||
RxInt isExpandedListIndex = (-1).obs;
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
RxMap<String, bool> isLoadingConfirmMap = RxMap();
|
||||
Rx<Color> bgConfirmAllColor = AppColor.blueNormal.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
WarehouseAndDistributionRootLogic rootLogic =
|
||||
Get.find<WarehouseAndDistributionRootLogic>();
|
||||
RxBool isButtonConfirm = false.obs;
|
||||
|
||||
Rx<Resource<PaginationModel<WaitingArrivalModel>>> waitingProduct =
|
||||
Resource<PaginationModel<WaitingArrivalModel>>.loading().obs;
|
||||
|
||||
TextEditingController weightController = TextEditingController();
|
||||
TextEditingController countController = TextEditingController();
|
||||
TextEditingController lossController = TextEditingController();
|
||||
TextEditingController approvedWithOtpController = TextEditingController();
|
||||
|
||||
RxBool approvedWithOtpCode = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getWaitingArrivals(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getWaitingArrivals();
|
||||
approvedWithOtpController.addListener(() {
|
||||
isButtonConfirm.value = approvedWithOtpController.text.trim().length > 4;
|
||||
});
|
||||
}
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
searchedValue.value = data?.trim();
|
||||
}
|
||||
|
||||
Future<void> getWaitingArrivals([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
waitingProduct.value =
|
||||
Resource<PaginationModel<WaitingArrivalModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
safeCall(
|
||||
// call: () async => await rootLogic.chickenRepository.getWaitingArrivals(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// queryParameters: buildQueryParams(
|
||||
// queryParams: {'type': 'not_entered'},
|
||||
// pageSize: 20,
|
||||
// page: currentPage.value,
|
||||
// search: 'filter',
|
||||
// role: 'Steward',
|
||||
// value: searchedValue.value,
|
||||
// fromDate: fromDateFilter.value.toDateTime(),
|
||||
// toDate: toDateFilter.value.toDateTime(),
|
||||
// ),
|
||||
// ),
|
||||
call: () async => null as PaginationModel<WaitingArrivalModel>?,
|
||||
onSuccess: (res) async {
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
// TODO: Fix - res type issues
|
||||
// if ((res?.count ?? 0) == 0) {
|
||||
// waitingProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.empty();
|
||||
// } else {
|
||||
// waitingProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.success(
|
||||
// PaginationModel<WaitingArrivalModel>(
|
||||
// count: res?.count ?? 0,
|
||||
// next: res?.next,
|
||||
// previous: res?.previous,
|
||||
// results: [...(waitingProduct.value.data?.results ?? []), ...(res?.results ?? [])],
|
||||
// ),
|
||||
// );
|
||||
// flashingFabBgColor();
|
||||
// }
|
||||
waitingProduct.value =
|
||||
Resource<PaginationModel<WaitingArrivalModel>>.empty();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> acceptEntries(WaitingArrivalModel model) async {
|
||||
var request = StewardAllocationRequest(
|
||||
allocationKey: model.key,
|
||||
checkAllocation: true,
|
||||
state: 'accepted',
|
||||
receiverRealNumberOfCarcasses: model.realNumberOfCarcasses ?? 0,
|
||||
receiverRealWeightOfCarcasses: model.realWeightOfCarcasses?.toInt() ?? 0,
|
||||
registrationCode: approvedWithOtpCode.value
|
||||
? int.parse(approvedWithOtpController.text.trim())
|
||||
: null,
|
||||
weightLossOfCarcasses: model.weightLossOfCarcasses?.toInt() ?? 0,
|
||||
stewardCheckAllocation: true,
|
||||
).toJson();
|
||||
request.removeWhere((key, value) => value == null);
|
||||
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
safeCall(
|
||||
showError: true,
|
||||
showSuccess: true,
|
||||
// call: () async => await rootLogic.chickenRepository.setSateForArrivals(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// request: request,
|
||||
// ),
|
||||
call: () async {},
|
||||
onError: (error, stackTrace) {
|
||||
eLog(error);
|
||||
},
|
||||
onSuccess: (result) {
|
||||
getWaitingArrivals();
|
||||
rootLogic.onRefresh();
|
||||
clearApprovedController();
|
||||
toggleExpansion();
|
||||
Future.delayed(Duration(seconds: 3), () {
|
||||
Get.back();
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> denyEntries(WaitingArrivalModel model) async {
|
||||
var request = StewardAllocationRequest(
|
||||
allocationKey: model.key,
|
||||
checkAllocation: true,
|
||||
state: 'rejected',
|
||||
).toJson();
|
||||
request.removeWhere((key, value) => value == null);
|
||||
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
safeCall(
|
||||
// call: () async => await rootLogic.chickenRepository.setSateForArrivals(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// request: request,
|
||||
// ),
|
||||
call: () async {},
|
||||
onError: (error, stackTrace) {
|
||||
eLog(error);
|
||||
},
|
||||
onSuccess: (result) {
|
||||
getWaitingArrivals();
|
||||
rootLogic.onRefresh();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void flashingFabBgColor() {
|
||||
Timer.periodic(Duration(seconds: 2), (timer) {
|
||||
if (bgConfirmAllColor.value == AppColor.blueNormal) {
|
||||
bgConfirmAllColor.value = AppColor.blueLightHover;
|
||||
} else {
|
||||
bgConfirmAllColor.value = AppColor.blueNormal;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void clearApprovedController() {
|
||||
weightController.clear();
|
||||
countController.clear();
|
||||
lossController.clear();
|
||||
approvedWithOtpController.clear();
|
||||
approvedWithOtpCode.value = false;
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (isExpandedListIndex.value == index || index == null) {
|
||||
isExpandedListIndex.value = -1;
|
||||
} else {
|
||||
isExpandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,373 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/string_utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyInProvinceWaitingPage extends GetView<WarehouseAndDistributionBuyInProvinceWaitingLogic> {
|
||||
const WarehouseAndDistributionBuyInProvinceWaitingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
var item = data.value.data!.results![index];
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: controller.isExpandedListIndex.value == index,
|
||||
onTap: () => controller.toggleExpansion(index: index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.timerSvg.path,
|
||||
labelIconColor: AppColor.yellowNormal2,
|
||||
);
|
||||
}, controller.isExpandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getWaitingArrivals(true),
|
||||
);
|
||||
}, controller.waitingProduct),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(WaitingArrivalModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
'${controller.rootLogic.isKillHouse(item) ? 'کشتارگاه' : 'مباشر'} ${controller.rootLogic.isKillHouse(item) ? item.killHouse?.name : item.steward?.user?.fullname} ',
|
||||
textAlign: TextAlign.start,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.date?.formattedJalaliDate ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 6,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: item.product?.name?.contains('مرغ گرم') ?? false,
|
||||
child: Assets.vec.hotChickenSvg.svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item.weightOfCarcasses?.separatedByCommaFa.addKg ?? 'ندارد',
|
||||
textAlign: TextAlign.left,
|
||||
textDirection: TextDirection.ltr,
|
||||
style: AppFonts.yekan12Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
'${item.amount?.separatedByCommaFa} ریال',
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
(item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
style: AppFonts.yekan12Bold.copyWith(
|
||||
color: (item.approvedPriceStatus ?? false)
|
||||
? AppColor.blueNormal
|
||||
: AppColor.greenNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(WaitingArrivalModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${controller.rootLogic.isKillHouse(item) ? item.killHouse?.name : item.steward?.user?.fullname} ',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'در انتظار',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
SizedBox(width: 7),
|
||||
Assets.vec.clockSvg.svg(width: 16.w, height: 16.h),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'ندارد',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'مشخصات فروشنده',
|
||||
value:
|
||||
'${controller.rootLogic.isKillHouse(item) ? item.killHouse?.killHouseOperator?.user?.fullname : item.steward?.user?.fullname} ',
|
||||
),
|
||||
buildRow(
|
||||
title: 'تلفن فروشنده',
|
||||
value:
|
||||
'${controller.rootLogic.isKillHouse(item) ? item.killHouse?.killHouseOperator?.user?.mobile : item.steward?.user?.mobile} ',
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
buildRow(title: 'نوع تخصیص', value: item.allocationType?.faAllocationType ?? 'ندارد'),
|
||||
buildRow(title: ' سهمیه', value: item.quota?.faTitle ?? 'ندارد'),
|
||||
buildRow(title: 'نوع فروش', value: item.saleType == "governmental" ? 'دولتی' : 'آزاد'),
|
||||
buildRow(title: 'محصول', value: item.product?.name ?? 'ندارد'),
|
||||
buildRow(
|
||||
title: 'تاریخ تولید گوشت',
|
||||
value: item.productionDate?.toJalali.toJalaliDateTime() ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'وزن خریداری شده',
|
||||
value: '${item.weightOfCarcasses?.separatedByCommaFa} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلوگرم',
|
||||
titleLabel: (item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
titleLabelStyle: AppFonts.yekan14Bold.copyWith(color: AppColor.greenNormal),
|
||||
value: '${item.amount?.separatedByCommaFa} ریال',
|
||||
),
|
||||
|
||||
buildRow(title: 'قیمت کل', value: '${item.totalAmount?.separatedByCommaFa} ریال'),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
text: 'تایید',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
isLoading: data[item.key!] ?? false,
|
||||
onPressed: () async {
|
||||
await Get.bottomSheet(conformationBottomSheet(item), isScrollControlled: true);
|
||||
},
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
);
|
||||
}, controller.isLoadingConfirmMap),
|
||||
ROutlinedElevated(
|
||||
text: 'رد',
|
||||
textStyle: AppFonts.yekan20.copyWith(color: AppColor.redNormal),
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
buildWarningDialog(
|
||||
title: 'اخطار',
|
||||
middleText: 'آیا از رد شدن این مورد اطمینان دارید؟',
|
||||
onConfirm: () => controller.denyEntries(item),
|
||||
onRefresh: () => controller.getWaitingArrivals(),
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget conformationBottomSheet(WaitingArrivalModel item) {
|
||||
controller.weightController.text = item.weightOfCarcasses.separatedByComma;
|
||||
return BaseBottomSheet(
|
||||
height: 450.h,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
RTextField(
|
||||
label: 'وزن(کیلوگرم)',
|
||||
controller: controller.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
RTextField(
|
||||
label: 'حجم(قطعه)',
|
||||
controller: controller.countController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
RTextField(
|
||||
label: 'افت وزن(کیلوگرم)',
|
||||
controller: controller.lossController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
|
||||
Text('تایید ', style: AppFonts.yekan16Bold.copyWith(color: AppColor.textColor)),
|
||||
ObxValue((data) {
|
||||
return Column(
|
||||
children: [
|
||||
RadioGroup(
|
||||
groupValue: data.value,
|
||||
onChanged: (value) {
|
||||
controller.approvedWithOtpCode.value = value ?? false;
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
radioRow(
|
||||
value: true,
|
||||
label: ' با کد احراز',
|
||||
onTap: () {
|
||||
controller.approvedWithOtpCode.value = true;
|
||||
},
|
||||
),
|
||||
radioRow(
|
||||
value: false,
|
||||
label: 'بدون کد احراز',
|
||||
onTap: () {
|
||||
controller.approvedWithOtpCode.value = false;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
child: RTextField(
|
||||
controller: controller.approvedWithOtpController,
|
||||
label: 'کد احراز',
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 5,
|
||||
),
|
||||
visible: data.value,
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.approvedWithOtpCode),
|
||||
SizedBox(height: 30.h),
|
||||
Obx(() {
|
||||
return RElevated(
|
||||
enabled: controller.approvedWithOtpCode.value
|
||||
? controller.isButtonConfirm.value
|
||||
: true,
|
||||
text: 'تایید',
|
||||
onPressed: () async {
|
||||
await controller.acceptEntries(item);
|
||||
},
|
||||
isFullWidth: true,
|
||||
);
|
||||
}),
|
||||
SizedBox(height: 20.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget radioRow({
|
||||
required bool value,
|
||||
required String label,
|
||||
TextStyle? textStyle,
|
||||
GestureTapCallback? onTap,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: value),
|
||||
Text(label, style: textStyle ?? AppFonts.yekan16.copyWith(color: AppColor.textColor)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,328 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/create_steward_free_bar/create_steward_free_bar.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_free_bar.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/buy/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyOutOfProvinceLogic extends GetxController {
|
||||
late List<String> routesName;
|
||||
RxBool isSubmitButtonEnabled = false.obs;
|
||||
RxInt expandedListIndex = (-1).obs;
|
||||
|
||||
final RxInt currentPage = 1.obs;
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
final RxBool isOnLoadingSubmitOrEdit = false.obs;
|
||||
|
||||
//TODO add this to Di
|
||||
ImagePicker imagePicker = ImagePicker();
|
||||
|
||||
Rx<Resource<PaginationModel<StewardFreeBar>>> purchaseOutOfProvinceList =
|
||||
Resource<PaginationModel<StewardFreeBar>>.loading().obs;
|
||||
Rxn<ProductModel> selectedProduct = Rxn();
|
||||
|
||||
RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
|
||||
Rxn<IranProvinceCityModel> selectedProvince = Rxn();
|
||||
Rxn<IranProvinceCityModel> selectedCity = Rxn();
|
||||
Rxn<XFile> selectedImage = Rxn<XFile>();
|
||||
final RxnString _base64Image = RxnString();
|
||||
RxnString editImageUrl = RxnString();
|
||||
RxnString editFreeBarKey = RxnString();
|
||||
|
||||
WarehouseAndDistributionRootLogic rootLogic =
|
||||
Get.find<WarehouseAndDistributionRootLogic>();
|
||||
|
||||
WarehouseAndDistributionBuyLogic buyLogic =
|
||||
Get.find<WarehouseAndDistributionBuyLogic>();
|
||||
|
||||
WarehouseAndDistributionSaleLogic outOfTheProvinceLogic =
|
||||
Get.find<WarehouseAndDistributionSaleLogic>();
|
||||
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
TextEditingController sellerNameController = TextEditingController();
|
||||
TextEditingController sellerPhoneController = TextEditingController();
|
||||
TextEditingController carcassWeightController = TextEditingController();
|
||||
TextEditingController carcassCountController = TextEditingController();
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName = [...buyLogic.routesName, 'خارج استان'].toList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getStewardPurchaseOutOfProvince();
|
||||
selectedProvince.listen((p0) => getCites());
|
||||
|
||||
// TODO: Fix - rolesProductsModel doesn't exist, use rolesProduct instead
|
||||
// selectedProduct.value = rootLogic.rolesProductsModel.first;
|
||||
selectedProduct.value = rootLogic.rolesProduct.value;
|
||||
setupListeners();
|
||||
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getStewardPurchaseOutOfProvince(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
sellerNameController.dispose();
|
||||
sellerPhoneController.dispose();
|
||||
carcassWeightController.dispose();
|
||||
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
searchedValue.value = data?.trim();
|
||||
}
|
||||
|
||||
Future<void> getStewardPurchaseOutOfProvince([
|
||||
bool isLoadingMore = false,
|
||||
]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
purchaseOutOfProvinceList.value =
|
||||
Resource<PaginationModel<StewardFreeBar>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1; // Reset to first page if search value is set
|
||||
}
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic, need to use killHouseRepository or inject chickenRepository
|
||||
await safeCall(
|
||||
// call: () => rootLogic.chickenRepository.getStewardPurchasesOutSideOfTheProvince(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// queryParameters: buildQueryParams(
|
||||
// pageSize: 20,
|
||||
// page: currentPage.value,
|
||||
// search: 'filter',
|
||||
// role: 'Steward',
|
||||
// value: searchedValue.value,
|
||||
// fromDate: fromDateFilter.value.toDateTime(),
|
||||
// toDate: toDateFilter.value.toDateTime(),
|
||||
// ),
|
||||
// ),
|
||||
call: () async => null as PaginationModel<StewardFreeBar>?,
|
||||
onSuccess: (res) async {
|
||||
await Future.delayed(Duration(milliseconds: 500));
|
||||
// TODO: Fix - res type issues
|
||||
// if ((res?.count ?? 0) == 0) {
|
||||
// purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.empty();
|
||||
// } else {
|
||||
// purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.success(
|
||||
// PaginationModel<StewardFreeBar>(
|
||||
// count: res?.count ?? 0,
|
||||
// next: res?.next,
|
||||
// previous: res?.previous,
|
||||
// results: [
|
||||
// ...(purchaseOutOfProvinceList.value.data?.results ?? []),
|
||||
// ...(res?.results ?? []),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
purchaseOutOfProvinceList.value =
|
||||
Resource<PaginationModel<StewardFreeBar>>.empty();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getCites() async {
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
await safeCall(
|
||||
// call: () =>
|
||||
// rootLogic.chickenRepository.getCity(provinceName: selectedProvince.value?.name ?? ''),
|
||||
call: () async => null as List<IranProvinceCityModel>?,
|
||||
onSuccess: (result) {
|
||||
// TODO: Fix - result type issues
|
||||
// if (result != null && result.isNotEmpty) {
|
||||
// cites.value = result;
|
||||
// }
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void setupListeners() {
|
||||
sellerNameController.addListener(() {
|
||||
checkFormValid();
|
||||
if (!isSubmitButtonEnabled.value) {
|
||||
isSubmitButtonEnabled.value = !isSubmitButtonEnabled.value;
|
||||
}
|
||||
});
|
||||
sellerPhoneController.addListener(checkFormValid);
|
||||
carcassWeightController.addListener(checkFormValid);
|
||||
carcassCountController.addListener(checkFormValid);
|
||||
|
||||
ever(selectedProvince, (_) => checkFormValid());
|
||||
ever(selectedCity, (_) => checkFormValid());
|
||||
ever(selectedProduct, (_) => checkFormValid());
|
||||
ever(selectedImage, (data) async {
|
||||
checkFormValid();
|
||||
if (data?.path != null) {
|
||||
_base64Image.value = await convertImageToBase64(data!.path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void checkFormValid() {
|
||||
isSubmitButtonEnabled.value =
|
||||
sellerNameController.text.isNotEmpty &&
|
||||
sellerPhoneController.text.isNotEmpty &&
|
||||
carcassWeightController.text.isNotEmpty &&
|
||||
carcassCountController.text.isNotEmpty &&
|
||||
selectedProvince.value != null &&
|
||||
selectedCity.value != null &&
|
||||
selectedProduct.value != null &&
|
||||
(selectedImage.value != null || editImageUrl.value != null);
|
||||
|
||||
if (isSubmitButtonEnabled.value) {
|
||||
isOnLoadingSubmitOrEdit.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> createStewardPurchaseOutOfProvince() async {
|
||||
bool res = false;
|
||||
isOnLoadingSubmitOrEdit.value = true;
|
||||
if (!(formKey.currentState?.validate() ?? false)) {
|
||||
isOnLoadingSubmitOrEdit.value = false;
|
||||
return res;
|
||||
}
|
||||
await safeCall(
|
||||
showError: true,
|
||||
call: () async {
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
// 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),
|
||||
// numberOfCarcasses: int.parse(carcassCountController.text.clearComma),
|
||||
// barImage: _base64Image.value,
|
||||
// date: DateTime.now().formattedYHMS,
|
||||
// );
|
||||
// await rootLogic.chickenRepository.createStewardPurchasesOutSideOfTheProvince(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// body: createStewardFreeBar,
|
||||
// );
|
||||
},
|
||||
onSuccess: (result) {
|
||||
getStewardPurchaseOutOfProvince();
|
||||
resetSubmitForm();
|
||||
toggleExpansion();
|
||||
res = true;
|
||||
},
|
||||
);
|
||||
isOnLoadingSubmitOrEdit.value = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
void resetSubmitForm() {
|
||||
sellerNameController.clear();
|
||||
sellerPhoneController.clear();
|
||||
carcassWeightController.clear();
|
||||
carcassCountController.clear();
|
||||
selectedProvince.value = null;
|
||||
selectedCity.value = null;
|
||||
selectedImage.value = null;
|
||||
_base64Image.value = null;
|
||||
editImageUrl.value = null;
|
||||
|
||||
isSubmitButtonEnabled.value = false;
|
||||
}
|
||||
|
||||
void setEditData(StewardFreeBar item) async {
|
||||
editImageUrl.value = item.barImage;
|
||||
sellerNameController.text = item.killHouseName ?? '';
|
||||
sellerPhoneController.text = item.killHouseMobile ?? '';
|
||||
carcassWeightController.text = item.weightOfCarcasses.separatedByComma;
|
||||
carcassCountController.text = item.numberOfCarcasses.separatedByComma;
|
||||
editFreeBarKey.value = item.key;
|
||||
selectedProvince.value = IranProvinceCityModel(name: item.province);
|
||||
selectedCity.value = IranProvinceCityModel(name: item.city);
|
||||
// TODO: Fix - rolesProductsModel doesn't exist, use rolesProduct instead
|
||||
// selectedProduct.value = rootLogic.rolesProductsModel.firstWhere(
|
||||
// (element) => element.key == item.product!.key,
|
||||
// );
|
||||
if (rootLogic.rolesProduct.value?.key == item.product!.key) {
|
||||
selectedProduct.value = rootLogic.rolesProduct.value;
|
||||
}
|
||||
|
||||
isSubmitButtonEnabled.value = true;
|
||||
}
|
||||
|
||||
Future<void> editStewardPurchaseOutOfProvince() async {
|
||||
CreateStewardFreeBar edit = CreateStewardFreeBar(
|
||||
productKey: selectedProduct.value!.key,
|
||||
key: editFreeBarKey.value,
|
||||
killHouseName: sellerNameController.text,
|
||||
killHouseMobile: sellerPhoneController.text,
|
||||
province: selectedProvince.value!.name,
|
||||
city: selectedCity.value!.name,
|
||||
weightOfCarcasses: int.parse(carcassWeightController.text.clearComma),
|
||||
numberOfCarcasses: int.parse(carcassCountController.text.clearComma),
|
||||
date: DateTime.now().formattedYHMS,
|
||||
);
|
||||
|
||||
if (_base64Image.value != null) {
|
||||
edit = edit.copyWith(barImage: _base64Image.value);
|
||||
}
|
||||
|
||||
await safeCall(
|
||||
showError: true,
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
// call: () => rootLogic.chickenRepository.editStewardPurchasesOutSideOfTheProvince(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// body: edit,
|
||||
// ),
|
||||
call: () async {},
|
||||
onSuccess: (result) {
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
toggleExpansion();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteStewardPurchaseOutOfProvince(String key) async {
|
||||
await safeCall(
|
||||
// TODO: Fix - chickenRepository doesn't exist in rootLogic
|
||||
// call: () => rootLogic.chickenRepository.deleteStewardPurchasesOutSideOfTheProvince(
|
||||
// token: rootLogic.tokenService.accessToken.value!,
|
||||
// queryParameters: buildRawQueryParams(queryParams: {'key': key}),
|
||||
// ),
|
||||
call: () async {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await rootLogic.onRefresh();
|
||||
await getStewardPurchaseOutOfProvince();
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,698 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart' hide Image;
|
||||
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';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class WarehouseAndDistributionBuyOutOfProvincePage
|
||||
extends GetView<WarehouseAndDistributionBuyOutOfProvinceLogic> {
|
||||
const WarehouseAndDistributionBuyOutOfProvincePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
backId: killHouseWarehouseAndDistributionBuyKey,
|
||||
onRefresh: controller.onRefresh,
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(filterBottomSheet());
|
||||
},
|
||||
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Column(
|
||||
children: [
|
||||
//inventoryWidget(controller.rootLogic),
|
||||
ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
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),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.truckFastOutlinedSvg.path,
|
||||
);
|
||||
}, controller.expandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async =>
|
||||
controller.getStewardPurchaseOutOfProvince(true),
|
||||
);
|
||||
}, controller.purchaseOutOfProvinceList),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 5,
|
||||
bottom: 95,
|
||||
child: RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
addPurchasedInformationBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).whenComplete(() {
|
||||
controller.resetSubmitForm();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(StewardFreeBar item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${item.province}-${item.city}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'ندارد',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.textColor,
|
||||
),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'مشخصات فروشنده',
|
||||
value: item.killHouseName ?? 'ندارد',
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'تلفن فروشنده',
|
||||
value: item.killHouseMobile ?? 'ندارد',
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
buildRow(title: 'محصول', value: item.product?.name ?? 'ندارد'),
|
||||
buildRow(
|
||||
title: 'وزن خریداری شده',
|
||||
value: '${item.weightOfCarcasses?.separatedByCommaFa} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'حجم خریداری شده',
|
||||
value: '${item.numberOfCarcasses?.separatedByCommaFa} قطعه',
|
||||
),
|
||||
buildRowOnTapped(
|
||||
title: 'مشاهده بارنامه',
|
||||
titleStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
valueWidget: Assets.vec.clipboardEyeSvg.svg(
|
||||
width: 20,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColor.blueNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
BaseBottomSheet(
|
||||
height: 400,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
'بارنامه',
|
||||
style: AppFonts.yekan16Bold.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
|
||||
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;
|
||||
return CupertinoActivityIndicator();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'ویرایش',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
controller.setEditData(item);
|
||||
Get.bottomSheet(
|
||||
addPurchasedInformationBottomSheet(true),
|
||||
isScrollControlled: true,
|
||||
).whenComplete(() {
|
||||
controller.resetSubmitForm();
|
||||
});
|
||||
},
|
||||
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: () => controller
|
||||
.deleteStewardPurchaseOutOfProvince(item.key!),
|
||||
onRefresh: () async {
|
||||
controller.rootLogic.onRefresh();
|
||||
controller.onRefresh();
|
||||
controller.toggleExpansion();
|
||||
},
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(StewardFreeBar item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.killHouseName ?? 'ندارد',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.date?.formattedJalaliDate ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: item.product?.name?.contains('مرغ گرم') ?? false,
|
||||
child: Assets.vec.hotChickenSvg.svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColor.blueNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${item.weightOfCarcasses?.separatedByCommaFa}kg',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
'${item.numberOfCarcasses.separatedByComma} ${'قطعه'}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
'${item.province}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
'${item.city}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget addPurchasedInformationBottomSheet([bool isOnEdit = false]) {
|
||||
return BaseBottomSheet(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
isOnEdit ? 'ویرایش اطلاعات خرید' : 'ثبت اطلاعات خرید',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
//_productDropDown(),
|
||||
|
||||
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: [_provinceWidget(), _cityWidget()],
|
||||
),
|
||||
),
|
||||
|
||||
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: [
|
||||
RTextField(
|
||||
controller: controller.sellerNameController,
|
||||
label: 'نام فروشنده',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.sellerPhoneController,
|
||||
label: 'تلفن فروشنده',
|
||||
keyboardType: TextInputType.phone,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
maxLength: 11,
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
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;
|
||||
},
|
||||
),
|
||||
|
||||
UnitTextField(
|
||||
controller: controller.carcassWeightController,
|
||||
hint: 'وزن',
|
||||
unit: 'کیلوگرم',
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
),
|
||||
|
||||
UnitTextField(
|
||||
controller: controller.carcassCountController,
|
||||
hint: 'حجم',
|
||||
unit: 'قطعه',
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_imageCarcasesWidget(isOnEdit),
|
||||
submitButtonWidget(isOnEdit),
|
||||
SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget submitButtonWidget(bool isOnEdit) {
|
||||
return Obx(() {
|
||||
return RElevated(
|
||||
text: isOnEdit ? 'ویرایش' : 'ثبت',
|
||||
width: Get.width,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
isLoading: controller.isOnLoadingSubmitOrEdit.value,
|
||||
enabled: controller.isSubmitButtonEnabled.value,
|
||||
onPressed: isOnEdit
|
||||
? () async {
|
||||
await controller.editStewardPurchaseOutOfProvince();
|
||||
Get.back();
|
||||
}
|
||||
: () async {
|
||||
var res = await controller.createStewardPurchaseOutOfProvince();
|
||||
if (res) {
|
||||
Get.back();
|
||||
}
|
||||
},
|
||||
height: 40,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/* Widget _productDropDown() {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<ProductModel>(
|
||||
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 _provinceWidget() {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<IranProvinceCityModel>(
|
||||
items: controller.rootLogic.provinces,
|
||||
onChanged: (value) {
|
||||
controller.selectedProvince.value = value;
|
||||
},
|
||||
selectedItem: controller.selectedProvince.value,
|
||||
itemBuilder: (item) => Text(
|
||||
item.name ?? 'بدون نام',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.lightGreyDarker),
|
||||
),
|
||||
labelBuilder: (item) => item?.name != null
|
||||
? Text(
|
||||
item!.name!,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
)
|
||||
: Text(
|
||||
'انتخاب استان',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.textColorLight,
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _cityWidget() {
|
||||
return ObxValue((data) {
|
||||
return OverlayDropdownWidget<IranProvinceCityModel>(
|
||||
items: data,
|
||||
onChanged: (value) {
|
||||
controller.selectedCity.value = value;
|
||||
},
|
||||
selectedItem: controller.selectedCity.value,
|
||||
itemBuilder: (item) => Text(
|
||||
item.name ?? 'بدون نام',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.lightGreyDarker),
|
||||
),
|
||||
labelBuilder: (item) => item?.name != null
|
||||
? Text(
|
||||
item!.name!,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
)
|
||||
: Text(
|
||||
'انتخاب شهر',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.textColorLight,
|
||||
),
|
||||
),
|
||||
);
|
||||
}, controller.cites);
|
||||
}
|
||||
|
||||
SizedBox _imageCarcasesWidget(bool isOnEdit) {
|
||||
return SizedBox(
|
||||
width: Get.width,
|
||||
height: 370,
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
'بارنامه',
|
||||
style: AppFonts.yekan16Bold.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return Container(
|
||||
width: Get.width,
|
||||
height: 270,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.lightGreyNormal,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: AppColor.blackLight),
|
||||
),
|
||||
child: Center(
|
||||
child: isOnEdit
|
||||
? Image.network(controller.editImageUrl.value ?? '')
|
||||
: data.value == null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
30,
|
||||
10,
|
||||
10,
|
||||
30,
|
||||
),
|
||||
child: Assets.vec.placeHolderSvg.svg(
|
||||
width: 200.w,
|
||||
height: 150.h,
|
||||
),
|
||||
)
|
||||
: Image.file(
|
||||
File(data.value!.path),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
);
|
||||
}, controller.selectedImage),
|
||||
),
|
||||
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'گالری',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
onPressed: () async {
|
||||
controller.selectedImage.value = await controller
|
||||
.imagePicker
|
||||
.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
imageQuality: 60,
|
||||
maxWidth: 1080,
|
||||
maxHeight: 720,
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
ROutlinedElevated(
|
||||
text: 'دوربین',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
textStyle: AppFonts.yekan20.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
onPressed: () async {
|
||||
controller.selectedImage.value = await controller
|
||||
.imagePicker
|
||||
.pickImage(
|
||||
source: ImageSource.camera,
|
||||
imageQuality: 60,
|
||||
maxWidth: 1080,
|
||||
maxHeight: 720,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 200,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
'فیلترها',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
date: controller.fromDateFilter,
|
||||
onChanged: (jalali) =>
|
||||
controller.fromDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
isFrom: false,
|
||||
date: controller.toDateFilter,
|
||||
onChanged: (jalali) => controller.toDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RElevated(
|
||||
text: 'اعمال فیلتر',
|
||||
isFullWidth: true,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
onPressed: () {
|
||||
controller.getStewardPurchaseOutOfProvince();
|
||||
Get.back();
|
||||
},
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import 'package:rasadyar_chicken/data/models/response/bar_information/bar_information.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionHomeLogic extends GetxController {
|
||||
WarehouseAndDistributionRootLogic rootLogic =
|
||||
Get.find<WarehouseAndDistributionRootLogic>();
|
||||
|
||||
RxList<Map<String, String?>> inventoryItems = [
|
||||
{'خریدهای دولتی داخل استان': null},
|
||||
{'خریدهای آزاد داخل استان': null},
|
||||
{'وزن خریدهای خارج استان': null},
|
||||
{'کل ورودی به انبار': null},
|
||||
{'کل فروش': null},
|
||||
{'مانده انبار': null},
|
||||
].obs;
|
||||
|
||||
RxList<Map<String, String>> broadcastItems = [
|
||||
{'وزن دولتی': '2،225،256'},
|
||||
{'وزن آزاد': '2،225،256'},
|
||||
{'فروش دولتی': '2،225،256'},
|
||||
{'فروش آزاد': '2،225،256'},
|
||||
{'توزیع داخل استان': '2،225،256'},
|
||||
{'توزیع خارج استان': '2،225،256'},
|
||||
{'قطعه بندی': '2،225،256'},
|
||||
].obs;
|
||||
|
||||
RxBool isExpanded = false.obs;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
Future<void> refreshData() async {
|
||||
await Future.wait([
|
||||
rootLogic.getRolesProducts(),
|
||||
rootLogic.getInfoSaleDashboard(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,245 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/data/models/kill_house_module/warehouse_and_distribution/response/kill_house_sales_info_dashboard.dart';
|
||||
import 'package:rasadyar_chicken/data/models/local/widely_used_local_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/broadcast_price/broadcast_price.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_remain_weight/steward_remain_weight.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart'
|
||||
hide ProductModel;
|
||||
import 'package:rasadyar_chicken/data/repositories/kill_house/kill_house_repository.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/buy/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/home/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sale/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/segmentation/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||
|
||||
class WarehouseAndDistributionRootLogic extends GetxController {
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
late DioRemote dioRemote;
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
RxInt currentPage = 2.obs;
|
||||
List<Widget> pages = [
|
||||
WarehouseAndDistributionBuyPage(),
|
||||
WarehouseAndDistributionSalePage(),
|
||||
WarehouseAndDistributionHomePage(),
|
||||
WarehouseAndDistributionSegmentationPage(),
|
||||
ProfilePage(),
|
||||
];
|
||||
|
||||
late KillHouseRepository killHouseRepository;
|
||||
|
||||
final defaultRoutes = <int, String>{
|
||||
0: ChickenRoutes.buyWarehouseAndDistribution,
|
||||
1: ChickenRoutes.saleWarehouseAndDistribution,
|
||||
};
|
||||
|
||||
Rxn<ProductModel> rolesProduct = Rxn<ProductModel>();
|
||||
Rxn<WidelyUsedLocalModel> widelyUsedList = Rxn<WidelyUsedLocalModel>();
|
||||
|
||||
Rxn<BroadcastPrice> broadcastPrice = Rxn<BroadcastPrice>();
|
||||
Rxn<KillHouseSalesInfoDashboard> salesInfoDashboard =
|
||||
Rxn<KillHouseSalesInfoDashboard>();
|
||||
Rxn<StewardRemainWeight> remainWeight = Rxn<StewardRemainWeight>();
|
||||
|
||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||
RxMap<int, dynamic> inventoryExpandedList = RxMap();
|
||||
Rxn<ProductModel> inventoryModel = Rxn<ProductModel>();
|
||||
RxList<IranProvinceCityModel> provinces = <IranProvinceCityModel>[].obs;
|
||||
|
||||
// Cancel tokens for API calls
|
||||
CancelToken? _inventoryCancelToken;
|
||||
CancelToken? _provincesCancelToken;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
|
||||
killHouseRepository = diChicken.get<KillHouseRepository>();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
|
||||
if (provinces.isEmpty) {
|
||||
getProvinces();
|
||||
}
|
||||
if (salesInfoDashboard.value == null) {
|
||||
getInfoSaleDashboard();
|
||||
}
|
||||
if (rolesProduct.value == null) {
|
||||
getRolesProducts();
|
||||
}
|
||||
if (broadcastPrice.value == null) {
|
||||
getBroadcastPrice();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// Cancel any ongoing requests when controller is disposed
|
||||
_inventoryCancelToken?.cancel();
|
||||
_provincesCancelToken?.cancel();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
await Future.wait([
|
||||
getInfoSaleDashboard(),
|
||||
getRolesProducts(),
|
||||
getProvinces(),
|
||||
getBroadcastPrice(),
|
||||
]);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
if (inventoryExpandedList.keys.contains(index)) {
|
||||
inventoryExpandedList.remove(index);
|
||||
} else {
|
||||
inventoryExpandedList[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getInfoSaleDashboard() async {
|
||||
// Cancel previous request if still running
|
||||
_inventoryCancelToken?.cancel();
|
||||
_inventoryCancelToken = CancelToken();
|
||||
|
||||
await safeCall<KillHouseSalesInfoDashboard?>(
|
||||
call: () async => await killHouseRepository.getInfoDashboard(
|
||||
token: tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
salesInfoDashboard.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
if (error is DioException && error.type == DioExceptionType.cancel) {
|
||||
// Request was cancelled, ignore the error
|
||||
return;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void rootErrorHandler(DioException error) {
|
||||
handleGeneric(error, () {
|
||||
tokenService.deleteModuleTokens(Module.chicken);
|
||||
});
|
||||
}
|
||||
|
||||
void changePage(int index) {
|
||||
currentPage.value = index;
|
||||
}
|
||||
|
||||
Future<void> getProvinces() async {
|
||||
// Cancel previous request if still running
|
||||
_provincesCancelToken?.cancel();
|
||||
_provincesCancelToken = CancelToken();
|
||||
|
||||
try {
|
||||
final res = await killHouseRepository.getProvince(
|
||||
cancelToken: _provincesCancelToken,
|
||||
);
|
||||
if (res != null) {
|
||||
provinces.clear();
|
||||
provinces.value = res;
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is DioException && e.type == DioExceptionType.cancel) {
|
||||
// Request was cancelled, ignore the error
|
||||
return;
|
||||
}
|
||||
provinces.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getBroadcastPrice() async {
|
||||
safeCall(
|
||||
call: () async => await killHouseRepository.getBroadcastPrice(
|
||||
token: tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
broadcastPrice.value = result;
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getRolesProducts() async {
|
||||
await safeCall(
|
||||
call: () async => await killHouseRepository.getRolesProducts(
|
||||
token: tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
rolesProduct.value = result.first;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
int getNestedKey() {
|
||||
switch (currentPage.value) {
|
||||
case 0:
|
||||
return stewardFirstKey;
|
||||
case 1:
|
||||
return stewardSecondKey;
|
||||
case 2:
|
||||
return stewardThirdKey;
|
||||
|
||||
case 3:
|
||||
return stewardFourthKey;
|
||||
|
||||
case 4:
|
||||
return stewardFourthKey;
|
||||
|
||||
default:
|
||||
return stewardThirdKey;
|
||||
}
|
||||
}
|
||||
|
||||
void onPopScopTaped() async {
|
||||
final nestedKeyId = getNestedKey();
|
||||
GlobalKey<NavigatorState>? currentNestedKey = Get.nestedKey(nestedKeyId);
|
||||
|
||||
if (currentNestedKey?.currentState?.canPop() == true) {
|
||||
iLog(currentNestedKey?.currentState?.canPop());
|
||||
iLog(currentNestedKey?.currentContext);
|
||||
currentNestedKey?.currentState?.popUntil((route) => route.isFirst);
|
||||
} else {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isKillHouse(WaitingArrivalModel model) =>
|
||||
model.allocationType?.split("_")[0].toLowerCase() == "killhouse";
|
||||
}
|
||||
@@ -1,565 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/chicken.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionRootPage
|
||||
extends GetView<WarehouseAndDistributionRootLogic> {
|
||||
WarehouseAndDistributionRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ObxValue((data) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
isBase: true,
|
||||
onPopScopTaped: controller.onPopScopTaped,
|
||||
child: Stack(
|
||||
children: [
|
||||
IndexedStack(
|
||||
children: [
|
||||
Navigator(
|
||||
key: Get.nestedKey(killHouseWarehouseAndDistributionBuyKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => ChickenPages.pages.firstWhere(
|
||||
(e) =>
|
||||
e.name == ChickenRoutes.buyWarehouseAndDistribution,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
Navigator(
|
||||
key: Get.nestedKey(killHouseWarehouseAndDistributionSaleKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => ChickenPages.pages.firstWhere(
|
||||
(e) =>
|
||||
e.name ==
|
||||
ChickenRoutes.saleWarehouseAndDistribution,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
Navigator(
|
||||
key: Get.nestedKey(stewardThirdKey),
|
||||
onGenerateRoute: (settings) =>
|
||||
GetPageRoute(page: () => controller.pages[2]),
|
||||
),
|
||||
Navigator(
|
||||
key: Get.nestedKey(stewardFourthKey),
|
||||
onGenerateRoute: (settings) =>
|
||||
GetPageRoute(page: () => controller.pages[3]),
|
||||
),
|
||||
Navigator(
|
||||
key: Get.nestedKey(stewardFifthKey),
|
||||
onGenerateRoute: (settings) =>
|
||||
GetPageRoute(page: () => controller.pages[4]),
|
||||
),
|
||||
],
|
||||
index: data.value,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
child: RBottomNavigation(
|
||||
items: [
|
||||
RBottomNavigationItem(
|
||||
label: 'خرید',
|
||||
icon: Assets.vec.buySvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'فروش',
|
||||
icon: Assets.vec.saleSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 2,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(2);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'قطعه بندی',
|
||||
icon: Assets.vec.convertCubeSvg.path,
|
||||
isSelected: controller.currentPage.value == 3,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(3);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 4,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
|
||||
controller.changePage(4);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.currentPage);
|
||||
}
|
||||
|
||||
Container _todayShipmentWidget() {
|
||||
return Container(
|
||||
height: 70,
|
||||
width: Get.width / 2,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [const Color(0xFFEAEFFF), Colors.white],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Assets.icons.cubeScan.svg(width: 30.w, height: 30),
|
||||
Text(
|
||||
'بارهای امروز',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
'2،225،256',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
'کیلوگرم',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container _informationLabelCard({
|
||||
required String title,
|
||||
required String description,
|
||||
String unit = 'کیلوگرم',
|
||||
required String iconPath,
|
||||
required Color iconColor,
|
||||
required Color bgDescriptionColor,
|
||||
required Color bgLabelColor,
|
||||
}) {
|
||||
return Container(
|
||||
height: 82,
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Row(
|
||||
children: [
|
||||
// Left side with icon and title
|
||||
Expanded(
|
||||
child: Container(
|
||||
height: 82,
|
||||
decoration: BoxDecoration(
|
||||
color: bgLabelColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(8),
|
||||
bottomRight: Radius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
SvgGenImage.vec(iconPath).svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
|
||||
),
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.mediumGreyDarkActive,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Right side with description and unit
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: bgDescriptionColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(8),
|
||||
bottomLeft: Radius.circular(8),
|
||||
),
|
||||
),
|
||||
child: 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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container _informationIconCard({
|
||||
required String title,
|
||||
required String description,
|
||||
String unit = 'کیلوگرم',
|
||||
required String iconPath,
|
||||
required Color iconColor,
|
||||
required Color bgDescriptionColor,
|
||||
required Color bgLabelColor,
|
||||
}) {
|
||||
return Container(
|
||||
height: 110,
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
child: Container(
|
||||
height: 91,
|
||||
decoration: BoxDecoration(
|
||||
color: bgDescriptionColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.25, color: const Color(0xFFB4B4B4)),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.mediumGreyDarkActive,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
description,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan16.copyWith(
|
||||
color: AppColor.mediumGreyDarkActive,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
unit,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(
|
||||
color: AppColor.mediumGreyDarkActive,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 0,
|
||||
child: Container(
|
||||
width: 32,
|
||||
height: 32,
|
||||
decoration: ShapeDecoration(
|
||||
color: bgLabelColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
side: BorderSide(width: 0.25, color: const Color(0xFFD5D5D5)),
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: SvgGenImage.vec(iconPath).svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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),
|
||||
),
|
||||
),
|
||||
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),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget addWidelyUsed({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(0xFFD9F7F0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Assets.vec.messageAddSvg.svg(
|
||||
width: 40,
|
||||
height: 40,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColor.greenNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'افزودن',
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.greenDarkHover),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
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: 1,
|
||||
child: Text(
|
||||
value,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.darkGreyDarkHover,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget broadcastInformationWidget(KillHouseDistributionInfo? model) {
|
||||
return Container(
|
||||
height: 140,
|
||||
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: 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(),
|
||||
),
|
||||
],
|
||||
)
|
||||
: const Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
|
||||
Widget cardWidget({
|
||||
required String title,
|
||||
required String iconPath,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return Container(
|
||||
width: Get.width / 4,
|
||||
height: 130,
|
||||
child: GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Card(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(width: 1, color: AppColor.blueNormal),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SvgGenImage(iconPath).svg(width: 50, height: 50),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/conform_allocation/conform_allocation.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/guild/guild_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/steward_free_bar_dashboard/steward_free_bar_dashboard.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionSaleLogic extends GetxController {
|
||||
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel =
|
||||
Rxn<List<AllocatedMadeModel>?>();
|
||||
|
||||
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
|
||||
|
||||
Rxn<StewardFreeBarDashboard> stewardFreeDashboard =
|
||||
Rxn<StewardFreeBarDashboard>();
|
||||
|
||||
WarehouseAndDistributionRootLogic rootLogic =
|
||||
Get.find<WarehouseAndDistributionRootLogic>();
|
||||
|
||||
List<String> routesName = ['فروش'];
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getStewardDashBord();
|
||||
}
|
||||
|
||||
Future<void> getAllocatedMade() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getAllocatedMade(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(page: 1, pageSize: 20, search: 'filter', role: 'Steward'),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
allocatedMadeModel.value = result.results;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
void checkVerfication() {}
|
||||
|
||||
void confirmAllocation(ConformAllocation allocation) {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocation: allocation.toJson(),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
void denyAllocation(String token) {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.denyAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationToken: token,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> confirmAllAllocations() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationTokens: allocatedMadeModel.value?.map((e) => e.key!).toList() ?? [],
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> getGuilds() async {}
|
||||
|
||||
Future<void> addSale() async {}
|
||||
|
||||
void setSelectedGuild(GuildModel value) {}
|
||||
|
||||
void setSelectedProduct(ProductModel value) {}
|
||||
|
||||
Future<void> getStewardDashBord() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getStewardDashboard(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
stratDate: DateTime.now().formattedDashedGregorian,
|
||||
endDate: DateTime.now().formattedDashedGregorian,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
stewardFreeDashboard.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> submitAllocation() async {}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
rootLogic.inventoryExpandedList.clear();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void onPopScopTaped() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/chicken.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/steward_free_bar_dashboard/steward_free_bar_dashboard.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class WarehouseAndDistributionSalePage extends GetView<WarehouseAndDistributionSaleLogic> {
|
||||
WarehouseAndDistributionSalePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
isBase: true,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 21,
|
||||
children: [
|
||||
GlassMorphismCardIcon(
|
||||
title: 'فروش داخل استان',
|
||||
vecIcon: Assets.vec.map2Svg.path,
|
||||
onTap: () {
|
||||
Get.toNamed(ChickenRoutes.salesInProvinceSteward, id: stewardSecondKey);
|
||||
},
|
||||
),
|
||||
GlassMorphismCardIcon(
|
||||
title: 'فروش خارج استان',
|
||||
vecIcon: Assets.vec.saleOutProvinceSvg.path,
|
||||
onTap: () {
|
||||
Get.toNamed(ChickenRoutes.salesOutOfProvinceSteward, id: stewardSecondKey);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget addSaleOutOfTheProvinceBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text(
|
||||
'ثبت فروش خارج استان',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
RElevated(text: 'ثبت توزیع/ فروش', onPressed: () {}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _typeOuterInfoCard({
|
||||
required String title,
|
||||
required String iconPath,
|
||||
required Color foregroundColor,
|
||||
VoidCallback? onTap,
|
||||
}) {
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
height: 180,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: foregroundColor),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned(
|
||||
top: -41,
|
||||
child: SvgGenImage.vec(iconPath).svg(
|
||||
width: 45,
|
||||
height: 45,
|
||||
colorFilter: ColorFilter.mode(foregroundColor, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
|
||||
Assets.vec.shoppingBasketSvg.svg(
|
||||
width: 55,
|
||||
height: 60,
|
||||
colorFilter: ColorFilter.mode(foregroundColor, BlendMode.srcIn),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan16Bold.copyWith(color: foregroundColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget summaryOfInformation(StewardFreeBarDashboard? model) {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'خلاصه اطلاعات',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 140,
|
||||
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: model == null
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 10,
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
buildRow('تعداد کل بارها', model.totalQuantity?.toString() ?? '0'),
|
||||
buildRow('تعداد کل', model.totalBars?.toString() ?? '0'),
|
||||
buildRow('وزن کل (کیلوگرم)', model.totalWeight?.toString() ?? '0'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,507 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/conform_allocation/conform_allocation.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/submit_steward_allocation/submit_steward_allocation.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/broadcast_price/broadcast_price.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/guild/guild_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/guild_profile/guild_profile.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/steward_remain_weight/steward_remain_weight.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/string_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionSalesInProvinceLogic extends GetxController {
|
||||
WarehouseAndDistributionRootLogic rootLogic = Get.find<WarehouseAndDistributionRootLogic>();
|
||||
WarehouseAndDistributionSaleLogic saleLogic = Get.find<WarehouseAndDistributionSaleLogic>();
|
||||
RxnString searchedValue = RxnString();
|
||||
RxInt expandedListIndex = (-1).obs;
|
||||
RxList<String> routesName = RxList();
|
||||
Rx<Color> bgConfirmAllColor = AppColor.blueNormal.obs;
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
Timer? _flashingTimer;
|
||||
|
||||
Rx<Resource<PaginationModel<AllocatedMadeModel>>> allocatedList =
|
||||
Resource<PaginationModel<AllocatedMadeModel>>.loading().obs;
|
||||
|
||||
RxList<ProductModel> rolesProductsModel = RxList<ProductModel>();
|
||||
|
||||
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
|
||||
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
Rxn<ProductModel> selectedProductModel = Rxn<ProductModel>();
|
||||
Rxn<GuildModel> selectedGuildModel = Rxn<GuildModel>();
|
||||
Rxn<GuildProfile> guildProfile = Rxn<GuildProfile>();
|
||||
RxInt saleType = 1.obs;
|
||||
RxInt priceType = 2.obs;
|
||||
RxInt quotaType = 1.obs;
|
||||
RxInt weight = 0.obs;
|
||||
RxInt pricePerKilo = 0.obs;
|
||||
RxInt totalCost = 0.obs;
|
||||
RxBool isValid = false.obs;
|
||||
final weightController = TextEditingController();
|
||||
final pricePerKiloController = TextEditingController();
|
||||
final totalCostController = TextEditingController();
|
||||
|
||||
final ScrollController scrollControllerAllocationsMade = ScrollController();
|
||||
final RxInt currentPage = 1.obs;
|
||||
final RxBool addPageAllocationsMade = false.obs;
|
||||
final RxBool hasMoreDataAllocationsMade = true.obs;
|
||||
|
||||
Rxn<BroadcastPrice> broadcastPrice = Rxn<BroadcastPrice>();
|
||||
Rxn<AllocatedMadeModel> selectedAllocationModelForUpdate = Rxn<AllocatedMadeModel>();
|
||||
SubmitStewardAllocation? tmpStewardAllocation;
|
||||
|
||||
Rxn<Jalali> productionDate = Rxn(null);
|
||||
Rxn<int> remainingStock = Rxn(null);
|
||||
Map<String, DayData> freeProductionDateData = {};
|
||||
Map<String, DayData> governmentalProductionDateData = {};
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName.value = [...saleLogic.routesName, 'داخل استان'].toList();
|
||||
getAllocatedMade();
|
||||
getRolesProducts();
|
||||
getGuilds();
|
||||
getGuildProfile();
|
||||
getBroadcastPrice();
|
||||
ever(saleType, (callback) {
|
||||
getGuilds();
|
||||
});
|
||||
|
||||
ever(quotaType, (_) {
|
||||
remainingStock.value = null;
|
||||
productionDate.value = null;
|
||||
});
|
||||
|
||||
debounce(weight, time: Duration(milliseconds: 110), (callback) {
|
||||
totalCost.value = callback * pricePerKilo.value;
|
||||
});
|
||||
|
||||
debounce(pricePerKilo, time: Duration(milliseconds: 100), (callback) {
|
||||
totalCost.value = callback * weight.value;
|
||||
});
|
||||
|
||||
totalCost.listen((data) {
|
||||
totalCostController.text = data.toString().separatedByComma;
|
||||
|
||||
isValid.value =
|
||||
weight.value > 0 &&
|
||||
pricePerKilo.value > 0 &&
|
||||
totalCost.value > 0 &&
|
||||
selectedProductModel.value != null &&
|
||||
selectedGuildModel.value != null;
|
||||
});
|
||||
everAll([
|
||||
totalCost,
|
||||
weight,
|
||||
pricePerKilo,
|
||||
totalCost,
|
||||
selectedProductModel,
|
||||
selectedGuildModel,
|
||||
productionDate,
|
||||
], (callback) => checkVerification());
|
||||
|
||||
scrollControllerAllocationsMade.addListener(() {
|
||||
if (scrollControllerAllocationsMade.position.pixels >=
|
||||
scrollControllerAllocationsMade.position.maxScrollExtent - 100) {
|
||||
addPageAllocationsMade.value = true;
|
||||
getAllocatedMade();
|
||||
}
|
||||
});
|
||||
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getAllocatedMade(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
/* ever(rootLogic.stewardRemainWeight, (callback) {
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
}); */
|
||||
}
|
||||
|
||||
void _updateGovernmentalProductionDateData() {
|
||||
/* List<RemainWeightDay> dates = rootLogic.stewardRemainWeight.value?.governmental ?? [];
|
||||
governmentalProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
}; */
|
||||
}
|
||||
|
||||
void _updateFreeProductionDateData() {
|
||||
/* var dates = rootLogic.stewardRemainWeight.value?.free ?? [];
|
||||
freeProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
}; */
|
||||
}
|
||||
|
||||
Future<void> getAllocatedMade([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
allocatedList.value = Resource<PaginationModel<AllocatedMadeModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1; // Reset to first page if search value is set
|
||||
}
|
||||
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getAllocatedMade(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
page: currentPage.value,
|
||||
pageSize: 20,
|
||||
search: 'filter',
|
||||
role: 'Steward',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
),
|
||||
),
|
||||
onSuccess: (res) async {
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
allocatedList.value = Resource<PaginationModel<AllocatedMadeModel>>.empty();
|
||||
} else {
|
||||
allocatedList.value = Resource<PaginationModel<AllocatedMadeModel>>.success(
|
||||
PaginationModel<AllocatedMadeModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: isLoadingMore
|
||||
? [...(allocatedList.value.data?.results ?? []), ...(res?.results ?? [])]
|
||||
: res?.results ?? [],
|
||||
),
|
||||
);
|
||||
isLoadingMoreAllocationsMade.value = false;
|
||||
if ((allocatedList.value.data?.results?.length ?? 0) > 1) {
|
||||
flashingFabBgColor();
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {
|
||||
isLoadingMoreAllocationsMade.value = false;
|
||||
},
|
||||
); */
|
||||
|
||||
}
|
||||
|
||||
void checkVerification() {
|
||||
var hasWeight = quotaType.value == 1
|
||||
? weight.value <=
|
||||
(governmentalProductionDateData[productionDate.value?.formatCompactDate()]?.value ??
|
||||
0)
|
||||
: weight.value <=
|
||||
(freeProductionDateData[productionDate.value?.formatCompactDate()]?.value ?? 0);
|
||||
|
||||
isValid.value =
|
||||
weight.value > 0 &&
|
||||
pricePerKilo.value > 0 &&
|
||||
totalCost.value > 0 &&
|
||||
hasWeight &&
|
||||
selectedProductModel.value != null &&
|
||||
selectedGuildModel.value != null;
|
||||
}
|
||||
|
||||
void confirmAllocation(ConformAllocation allocation) {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocation: allocation.toJson(),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
void denyAllocation(String token) {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.denyAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationToken: token,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> confirmAllAllocations() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationTokens: allocatedList.value.data?.results?.map((e) => e.key!).toList() ?? [],
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> getRolesProducts() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getRolesProducts(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
role: 'Steward',
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
rolesProductsModel.value = result;
|
||||
selectedProductModel.value = result.first;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> getGuilds() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getGuilds(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
//queryParams: {'free': saleType.value == 2 ? true : false},
|
||||
queryParams: {'all': true},
|
||||
role: 'Steward',
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
guildsModel.clear();
|
||||
guildsModel.addAll(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> addSale() async {}
|
||||
|
||||
void setSelectedGuild(GuildModel value) {
|
||||
selectedGuildModel.value = value;
|
||||
update();
|
||||
}
|
||||
|
||||
void setSelectedProduct(ProductModel value) {
|
||||
selectedProductModel.value = value;
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> getGuildProfile() async {
|
||||
/* await safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getProfile(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onError: (error, stackTrace) {},
|
||||
onSuccess: (result) {
|
||||
guildProfile.value = result;
|
||||
},
|
||||
); */
|
||||
}
|
||||
|
||||
void setSubmitData() {
|
||||
tmpStewardAllocation = SubmitStewardAllocation(
|
||||
approvedPriceStatus: priceType.value == 1,
|
||||
allocationType:
|
||||
'${guildProfile.value?.steward == true ? "steward" : "guild"}_${selectedGuildModel.value?.steward == true ? "steward" : "guild"}',
|
||||
sellerType: guildProfile.value?.steward == true ? "Steward" : "Guild",
|
||||
buyerType: selectedGuildModel.value?.steward == true ? "Steward" : "Guild",
|
||||
amount: pricePerKilo.value,
|
||||
totalAmount: totalCost.value,
|
||||
weightOfCarcasses: weight.value,
|
||||
sellType: saleType.value == 2 ? "free" : 'exclusive',
|
||||
numberOfCarcasses: 0,
|
||||
productionDate: productionDate.value?.toDateTime().formattedDashedGregorian,
|
||||
quota: quotaType.value == 1 ? 'governmental' : 'free',
|
||||
guildKey: selectedGuildModel.value?.key,
|
||||
productKey: selectedProductModel.value?.key,
|
||||
date: DateTime.now().formattedDashedGregorian,
|
||||
type: "manual",
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> submitAllocation() async {
|
||||
setSubmitData();
|
||||
|
||||
/* safeCall(
|
||||
showError: true,
|
||||
call: () async => await rootLogic.chickenRepository.postSubmitStewardAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: tmpStewardAllocation!,
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
clearForm();
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
Future.delayed(Duration(seconds: 1), () => defaultShowSuccessMessage("ثبت موفق بود"));
|
||||
Get.back();
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> deleteAllocation(AllocatedMadeModel model) async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.deleteStewardAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: {'steward_allocation_key': model.key},
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
rootLogic.inventoryExpandedList.clear();
|
||||
stopFlashing();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void setEditData(AllocatedMadeModel item) {
|
||||
selectedAllocationModelForUpdate.value = item;
|
||||
selectedProductModel.value = rolesProductsModel.first;
|
||||
selectedGuildModel.value = GuildModel(guildsName: 'tst');
|
||||
weight.value = item.weightOfCarcasses ?? 0;
|
||||
pricePerKilo.value = item.amount ?? 0;
|
||||
totalCost.value = item.totalAmount ?? 0;
|
||||
weightController.text = weight.value.toString().separatedByComma;
|
||||
pricePerKiloController.text = pricePerKilo.value.toString().separatedByComma;
|
||||
totalCostController.text = totalCost.value.toString().separatedByComma;
|
||||
isValid.value = true;
|
||||
productionDate.value = item.productionDate.toJalali;
|
||||
}
|
||||
|
||||
void clearForm() {
|
||||
selectedGuildModel.value = null;
|
||||
weight.value = 0;
|
||||
totalCost.value = 0;
|
||||
weightController.clear();
|
||||
if (broadcastPrice.value?.active == false) {
|
||||
pricePerKilo.value = 0;
|
||||
pricePerKiloController.clear();
|
||||
}
|
||||
totalCostController.clear();
|
||||
isValid.value = false;
|
||||
productionDate.value = null;
|
||||
quotaType.value = 1;
|
||||
priceType.value = 2;
|
||||
saleType.value = 2;
|
||||
}
|
||||
|
||||
Future<void> updateAllocation() async {
|
||||
ConformAllocation updatedAllocationModel = ConformAllocation(
|
||||
allocation_key: selectedAllocationModelForUpdate.value?.key,
|
||||
amount: pricePerKilo.value,
|
||||
total_amount: totalCost.value,
|
||||
number_of_carcasses: 0,
|
||||
weight_of_carcasses: weight.value,
|
||||
);
|
||||
|
||||
/* safeCall(
|
||||
showError: true,
|
||||
call: () async => await rootLogic.chickenRepository.updateStewardAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: updatedAllocationModel,
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
clearForm();
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
Future.delayed(Duration(seconds: 1), () => defaultShowSuccessMessage("ویرایش موفق بود"));
|
||||
Get.back();
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
searchedValue.value = data?.trim();
|
||||
}
|
||||
|
||||
void flashingFabBgColor() {
|
||||
_flashingTimer?.cancel();
|
||||
|
||||
_flashingTimer = Timer.periodic(Duration(seconds: 2), (timer) {
|
||||
if (bgConfirmAllColor.value == AppColor.blueNormal) {
|
||||
bgConfirmAllColor.value = AppColor.blueLightHover;
|
||||
} else {
|
||||
bgConfirmAllColor.value = AppColor.blueNormal;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void stopFlashing() {
|
||||
_flashingTimer?.cancel();
|
||||
_flashingTimer = null;
|
||||
bgConfirmAllColor.value = AppColor.blueNormal; // بازگرداندن به رنگ پیشفرض
|
||||
}
|
||||
|
||||
Steward? getBuyerInformation(AllocatedMadeModel model) {
|
||||
if (model.allocationType?.buyerIsGuild ?? false) {
|
||||
return model.toGuilds;
|
||||
} else {
|
||||
return model.steward;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getBroadcastPrice() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getBroadcastPrice(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
broadcastPrice.value = result;
|
||||
if (broadcastPrice.value?.active == true) {
|
||||
pricePerKilo.value = broadcastPrice.value?.stewardPrice ?? 0;
|
||||
pricePerKiloController.text = pricePerKilo.value.toString().separatedByComma;
|
||||
priceType.value = 2;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
toggleExpansion();
|
||||
currentPage.value = 1;
|
||||
hasMoreDataAllocationsMade.value = true;
|
||||
await Future.wait([getAllocatedMade(), getRolesProducts(), rootLogic.onRefresh()]);
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,543 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sales_in_province/widgets/cu_sale_in_provience.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/string_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/inventory/inventory_widget.dart';
|
||||
import 'package:rasadyar_core/core.dart' hide modalDatePicker;
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class WarehouseAndDistributionSalesInProvincePage
|
||||
extends GetView<WarehouseAndDistributionSalesInProvinceLogic> {
|
||||
const WarehouseAndDistributionSalesInProvincePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
backId: stewardSecondKey,
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
onRefresh: controller.onRefresh,
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(filterBottomSheet());
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Column(
|
||||
children: [
|
||||
// inventoryWidget(controller.rootLogic),
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
isPaginating:
|
||||
controller.isLoadingMoreAllocationsMade.value,
|
||||
onLoadMore: () async {
|
||||
controller.currentPage.value++;
|
||||
await controller.getAllocatedMade(true);
|
||||
},
|
||||
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,
|
||||
labelIcon: Assets.vec.timerSvg.path,
|
||||
labelIconColor: item.registrationCode == null
|
||||
? AppColor.darkGreyDark
|
||||
: AppColor.error,
|
||||
);
|
||||
}, controller.expandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) =>
|
||||
SizedBox(height: 8.h),
|
||||
);
|
||||
}, controller.allocatedList),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 5,
|
||||
bottom: 95,
|
||||
child: SizedBox(
|
||||
width: Get.width - 30,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
RFab.add(
|
||||
onPressed: () {
|
||||
/* Get.bottomSheet(
|
||||
addOrEditBottomSheet(controller),
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
).whenComplete(() {
|
||||
controller.clearForm();
|
||||
}); */
|
||||
},
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: (data.value.data?.results?.length ?? 0) > 1,
|
||||
child: AnimatedFab(
|
||||
onPressed: () async {
|
||||
Get.defaultDialog(
|
||||
title: 'تایید یکجا',
|
||||
middleText:
|
||||
'آیا از تایید تمامی تخصیص ها اطمینان دارید؟',
|
||||
confirm: ElevatedButton(
|
||||
onPressed: () async {
|
||||
await controller.confirmAllAllocations();
|
||||
controller.getAllocatedMade();
|
||||
// controller.rootLogic.getKillHouseSalesInfoDashboard();
|
||||
Get.back();
|
||||
},
|
||||
child: Text('تایید'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
),
|
||||
cancel: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: AppColor.error,
|
||||
enableFeedback: true,
|
||||
side: BorderSide(
|
||||
color: AppColor.error,
|
||||
width: 1,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Text('لغو'),
|
||||
),
|
||||
);
|
||||
},
|
||||
message: 'تایید یکجا',
|
||||
icon: Assets.vec.clipboardTaskSvg.svg(
|
||||
width: 40.w,
|
||||
height: 40.h,
|
||||
),
|
||||
backgroundColor: controller.bgConfirmAllColor.value,
|
||||
),
|
||||
);
|
||||
}, controller.allocatedList),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(AllocatedMadeModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
controller.getBuyerInformation(item)?.user?.fullname ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
item.createDate?.formattedJalaliDate ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 6,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: item.product?.name?.contains('مرغ گرم') ?? false,
|
||||
child: Assets.vec.hotChickenSvg.svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColor.blueNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item.weightOfCarcasses!.separatedByCommaFa.addKg,
|
||||
textAlign: TextAlign.left,
|
||||
textDirection: TextDirection.ltr,
|
||||
style: AppFonts.yekan12Bold.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
item.amount.separatedByCommaFa.addReal,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(width: 8),
|
||||
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.approvedPriceStatus == true
|
||||
? 'دولتی'
|
||||
: item.approvedPriceStatus == false
|
||||
? 'آزاد'
|
||||
: '-',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(
|
||||
color: item.approvedPriceStatus == true
|
||||
? AppColor.blueNormal
|
||||
: AppColor.greenNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(width: 8),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(AllocatedMadeModel item, int index) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.getBuyerInformation(item)?.user?.fullname ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
item.registrationCode == null
|
||||
? 'در انتظار'
|
||||
: 'در انتظار تایید خریدار',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(
|
||||
color: item.registrationCode == null
|
||||
? AppColor.darkGreyDark
|
||||
: AppColor.error,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 7),
|
||||
Assets.vec.clockSvg.svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(
|
||||
item.registrationCode == null
|
||||
? AppColor.darkGreyDark
|
||||
: AppColor.error,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'ندارد',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.textColor,
|
||||
),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
buildRow(
|
||||
title: 'تلفن خریدار',
|
||||
value:
|
||||
controller.getBuyerInformation(item)?.user?.mobile ?? 'ندارد',
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
buildRow(title: 'محصول', value: item.product?.name ?? 'ندارد'),
|
||||
|
||||
buildRow(
|
||||
title: 'تاریخ تولید گوشت',
|
||||
value: item.productionDate?.toJalali.formatCompactDate() ?? 'ندارد',
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'نوع تخصیص',
|
||||
value: item.allocationType?.faAllocationType ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'نوع فروش',
|
||||
value: (item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'نوع انبار',
|
||||
value: (item.quota == 'governmental') ? 'دولتی' : 'آزاد',
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'وزن خریداری شده',
|
||||
value: '${item.weightOfCarcasses?.separatedByCommaFa} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'افت وزن(کیلوگرم)',
|
||||
value: item.weightLossOfCarcasses?.toInt().toString() ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلوگرم',
|
||||
titleLabel: (item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
titleLabelStyle: AppFonts.yekan14Bold.copyWith(
|
||||
color: (item.approvedPriceStatus ?? false)
|
||||
? AppColor.blueNormal
|
||||
: AppColor.greenNormal,
|
||||
),
|
||||
value: '${item.amount?.separatedByCommaFa} ریال',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت کل',
|
||||
value: '${item.totalAmount?.separatedByCommaFa} ریال',
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'کداحراز',
|
||||
value: item.registrationCode?.toString() ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'وضعیت کد احراز',
|
||||
value: item.systemRegistrationCode == true
|
||||
? "ارسال شده"
|
||||
: "ارسال نشده",
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: item.registrationCode == null,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'ویرایش',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
controller.setEditData(item);
|
||||
/* Get.bottomSheet(
|
||||
addOrEditBottomSheet(controller, isEditMode: true),
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
).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(index: index);
|
||||
|
||||
await controller.deleteAllocation(item);
|
||||
},
|
||||
onRefresh: controller.onRefresh,
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 200,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
'فیلترها',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: timeFilterWidget(
|
||||
controller: controller,
|
||||
date: controller.fromDateFilter,
|
||||
onChanged: (jalali) =>
|
||||
controller.fromDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: timeFilterWidget(
|
||||
controller: controller,
|
||||
isFrom: false,
|
||||
date: controller.toDateFilter,
|
||||
onChanged: (jalali) => controller.toDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RElevated(
|
||||
text: 'اعمال فیلتر',
|
||||
isFullWidth: true,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
onPressed: () {
|
||||
controller.getAllocatedMade();
|
||||
Get.back();
|
||||
},
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
GestureDetector timeFilterWidget({
|
||||
required WarehouseAndDistributionSalesInProvinceLogic controller,
|
||||
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.blueNormal),
|
||||
),
|
||||
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.blueNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
isFrom ? 'از' : 'تا',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return Text(
|
||||
date.value.formatCompactDate(),
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(
|
||||
color: AppColor.lightGreyNormalActive,
|
||||
),
|
||||
);
|
||||
}, date),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,515 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sales_in_province/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
Widget addOrEditBottomSheet(WarehouseAndDistributionSalesInProvinceLogic controller, {bool isEditMode = false}) {
|
||||
return BaseBottomSheet(
|
||||
height: Get.height * (isEditMode ? 0.60 : 0.75),
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'${isEditMode ? 'ویرایش' : 'ثبت'} توزیع/ فروش',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
productDropDown(controller),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
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: [
|
||||
const SizedBox(height: 8),
|
||||
ObxValue((data) {
|
||||
return RTextField(
|
||||
controller: TextEditingController(),
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
label: 'تاریخ',
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
modalDatePicker((value) {
|
||||
controller.fromDateFilter.value = value;
|
||||
controller.fromDateFilter.refresh();
|
||||
}),
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
initText: (data.value).formatCompactDate(),
|
||||
);
|
||||
}, controller.fromDateFilter),
|
||||
Visibility(
|
||||
visible: isEditMode == false,
|
||||
child: 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.quotaType.value = 1;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 1),
|
||||
Text('دولتی', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.quotaType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Obx(() {
|
||||
return MonthlyDataCalendar(
|
||||
label: 'تاریخ تولید گوشت',
|
||||
selectedDate: controller.productionDate.value?.formatCompactDate(),
|
||||
onDateSelect: (value) {
|
||||
controller.productionDate.value = value.date;
|
||||
controller.remainingStock.value = value.remainingStock;
|
||||
},
|
||||
dayData: controller.quotaType.value == 1
|
||||
? controller.governmentalProductionDateData
|
||||
: controller.freeProductionDateData,
|
||||
);
|
||||
}),
|
||||
|
||||
Visibility(visible: isEditMode == false, child: guildsDropDown(controller)),
|
||||
|
||||
RTextField(
|
||||
controller: controller.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
autoValidateMode: AutovalidateMode.onUserInteraction,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
validator: (value) {
|
||||
if ((int.tryParse(value?.clearComma ?? '0') ?? 0) >
|
||||
(controller.remainingStock.value ?? 0)) {
|
||||
return 'وزن تخصیصی بیشتر از موجودی انبار است';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (p0) {
|
||||
controller.weight.value = int.tryParse(p0.clearComma) ?? 0;
|
||||
},
|
||||
label: 'وزن لاشه (کیلوگرم)',
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: isEditMode == false,
|
||||
child: Container(
|
||||
height: 58.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.priceType.value,
|
||||
onChanged: (value) {
|
||||
controller.priceType.value = value!;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: (controller.broadcastPrice.value?.active ?? false)
|
||||
? () {
|
||||
controller.priceType.value = 1;
|
||||
}
|
||||
: null,
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(
|
||||
value: 1,
|
||||
enabled: controller.broadcastPrice.value?.active ?? false,
|
||||
),
|
||||
Text(
|
||||
'قیمت مصوب',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color:
|
||||
(controller.broadcastPrice.value?.active ?? false)
|
||||
? AppColor.textColor
|
||||
: AppColor.labelTextColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.priceType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('قیمت آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return RTextField(
|
||||
variant: RTextFieldVariant.noBorder,
|
||||
controller: controller.pricePerKiloController,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
readonly: data.value == 1,
|
||||
onChanged: (p0) {
|
||||
controller.pricePerKilo.value = int.tryParse(p0.clearComma) ?? 0;
|
||||
},
|
||||
keyboardType: TextInputType.number,
|
||||
label: 'قیمت هر کیلو (ريال)',
|
||||
);
|
||||
}, controller.priceType),
|
||||
|
||||
RTextField(
|
||||
variant: RTextFieldVariant.noBorder,
|
||||
enabled: false,
|
||||
keyboardType: TextInputType.number,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
controller: controller.totalCostController,
|
||||
label: 'هزینه کل (ريال)',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 12.h),
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
text: isEditMode ? 'ویرایش' : 'ثبت',
|
||||
isFullWidth: true,
|
||||
textStyle: AppFonts.yekan16.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
height: 40,
|
||||
enabled: data.value,
|
||||
onPressed: isEditMode
|
||||
? () async {
|
||||
await controller.updateAllocation();
|
||||
Get.back();
|
||||
}
|
||||
: () async {
|
||||
await controller.submitAllocation();
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}, controller.isValid),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget guildsDropDown(WarehouseAndDistributionSalesInProvinceLogic controller) {
|
||||
return Obx(() {
|
||||
final item = controller.selectedGuildModel.value;
|
||||
|
||||
return SearchableDropdown(
|
||||
onChanged: (value) {
|
||||
controller.selectedGuildModel.value = value;
|
||||
},
|
||||
selectedItem: [?item],
|
||||
singleSelect: false,
|
||||
items: controller.guildsModel,
|
||||
hintText: 'انتخاب مباشر/صنف',
|
||||
itemBuilder: (item) => Text(
|
||||
item.user != null
|
||||
? '${item.steward == true ? 'مباشر' : 'صنف'} ${item.user!.fullname} (${item.user!.mobile})'
|
||||
: 'بدون نام',
|
||||
),
|
||||
multiLabelBuilder: (item) => Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight),
|
||||
),
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
item?.user != null
|
||||
? '${item?.steward == true ? 'مباشر' : 'صنف'} ${item?.user!.fullname}'
|
||||
: 'بدون نام',
|
||||
style: AppFonts.yekan14,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
Icon(Icons.close, size: 16, color: AppColor.labelTextColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
onSearch: (query) async {
|
||||
return Future.microtask(() {
|
||||
return RxList(
|
||||
controller.guildsModel
|
||||
.where((element) => element.user?.fullname?.contains(query) ?? false)
|
||||
.toList(),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget productDropDown(WarehouseAndDistributionSalesInProvinceLogic controller) {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<ProductModel>(
|
||||
items: controller.rolesProductsModel,
|
||||
height: 56,
|
||||
hasDropIcon: false,
|
||||
background: Colors.white,
|
||||
onChanged: (value) {
|
||||
controller.selectedProductModel.value = value;
|
||||
},
|
||||
selectedItem: controller.selectedProductModel.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(),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(visible: data.value != null, child: Text('موجودی: $data'));
|
||||
}, controller.remainingStock),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
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: Jalali.now(),
|
||||
minimumDate: Jalali.now().add(days: -1),
|
||||
maximumDate: Jalali.now(),
|
||||
mode: PersianCupertinoDatePickerMode.date,
|
||||
onDateTimeChanged: (dateTime) {
|
||||
tempPickedDate = dateTime;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget show2StepAddBottomSheet(WarehouseAndDistributionSalesInProvinceLogic controller) {
|
||||
return BaseBottomSheet(
|
||||
height: Get.height * .39,
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
buildRow(
|
||||
title: 'تاریخ ثبت',
|
||||
value: controller.tmpStewardAllocation?.date?.formattedJalaliDate ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'نام و نام خانوادگی خریدار',
|
||||
value:
|
||||
controller.guildsModel
|
||||
.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey)
|
||||
.user
|
||||
?.fullname ??
|
||||
'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شماره خریدار',
|
||||
value:
|
||||
controller.guildsModel
|
||||
.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey)
|
||||
.user
|
||||
?.mobile ??
|
||||
'ندارد',
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلو',
|
||||
value: '${controller.tmpStewardAllocation?.amount.separatedByCommaFa ?? 0} ریال ',
|
||||
),
|
||||
buildRow(
|
||||
title: 'وزن تخصیصی',
|
||||
value:
|
||||
'${controller.tmpStewardAllocation?.weightOfCarcasses?.toInt().separatedByCommaFa ?? 0} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت کل',
|
||||
value: '${controller.tmpStewardAllocation?.totalAmount.separatedByCommaFa ?? 0} ریال',
|
||||
),
|
||||
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: RElevated(
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
height: 40,
|
||||
text: 'ثبت',
|
||||
textStyle: AppFonts.yekan18.copyWith(color: Colors.white),
|
||||
onPressed: () async {
|
||||
await controller.submitAllocation();
|
||||
Get
|
||||
..back()
|
||||
..back();
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ROutlinedElevated(
|
||||
height: 40,
|
||||
borderColor: AppColor.error,
|
||||
text: ' بازگشت',
|
||||
textStyle: AppFonts.yekan18.copyWith(color: AppColor.error),
|
||||
onPressed: () {
|
||||
Get
|
||||
..back()
|
||||
..back();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1,382 +0,0 @@
|
||||
import 'package:flutter/material.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/broadcast_price/broadcast_price.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/data/models/response/steward_remain_weight/steward_remain_weight.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sales_out_of_province_buyers/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sales_out_of_province_sales_list/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionSalesOutOfProvinceLogic extends GetxController {
|
||||
WarehouseAndDistributionRootLogic rootLogic = Get.find<WarehouseAndDistributionRootLogic>();
|
||||
|
||||
WarehouseAndDistributionSaleLogic saleLogic = Get.find<WarehouseAndDistributionSaleLogic>();
|
||||
|
||||
WarehouseAndDistributionSalesOutOfProvinceSalesListLogic saleListLogic = Get.find<WarehouseAndDistributionSalesOutOfProvinceSalesListLogic>();
|
||||
|
||||
WarehouseAndDistributionSalesOutOfProvinceBuyersLogic buyerLogic = Get.find<WarehouseAndDistributionSalesOutOfProvinceBuyersLogic>();
|
||||
|
||||
RxBool isExpanded = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxBool isSaleSubmitButtonEnabled = false.obs;
|
||||
RxInt expandedListIndex = (-1).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();
|
||||
Rxn<BroadcastPrice> broadcastPrice = Rxn<BroadcastPrice>();
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
TextEditingController quarantineCodeController = TextEditingController();
|
||||
TextEditingController saleWeightController = TextEditingController();
|
||||
TextEditingController saleCountController = TextEditingController();
|
||||
TextEditingController pricePerKiloController = TextEditingController();
|
||||
TextEditingController totalCostController = TextEditingController();
|
||||
TextEditingController otpCodeSell = TextEditingController();
|
||||
Rx<Jalali> saleDate = Jalali.now().obs;
|
||||
String? key;
|
||||
RxInt pricePerKilo = 0.obs;
|
||||
RxInt totalCost = 0.obs;
|
||||
RxInt weight = 0.obs;
|
||||
RxString otpCode = ''.obs;
|
||||
|
||||
Rx<Resource<PaginationModel<StewardFreeSaleBar>>> salesList =
|
||||
Resource<PaginationModel<StewardFreeSaleBar>>.loading().obs;
|
||||
|
||||
Rxn<ProductModel> selectedProduct = Rxn();
|
||||
Rxn<OutProvinceCarcassesBuyer> selectedBuyer = Rxn();
|
||||
|
||||
RxInt saleType = 2.obs;
|
||||
RxInt quotaType = 1.obs;
|
||||
Rxn<Jalali> productionDate = Rxn();
|
||||
Rxn<int> remainingStock = Rxn(null);
|
||||
Map<String, DayData> freeProductionDateData = {};
|
||||
Map<String, DayData> governmentalProductionDateData = {};
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName.value = [...saleLogic.routesName, 'خارج استان'].toList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getOutProvinceSales();
|
||||
getBroadcastPrice();
|
||||
// selectedProduct.value = rootLogic.rolesProductsModel.first;
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getOutProvinceSales(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
setupListeners();
|
||||
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
/* ever(rootLogic.stewardRemainWeight, (callback) {
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
}); */
|
||||
ever(quotaType, (_) {
|
||||
remainingStock.value = null;
|
||||
productionDate.value = null;
|
||||
});
|
||||
debounce(pricePerKilo, time: Duration(milliseconds: 100), (callback) {
|
||||
totalCost.value = callback * (weight.value);
|
||||
});
|
||||
|
||||
ever(totalCost, (callback) {
|
||||
totalCostController.text = callback.separatedByComma;
|
||||
});
|
||||
}
|
||||
|
||||
void _updateGovernmentalProductionDateData() {
|
||||
/* List<RemainWeightDay> dates = rootLogic.stewardRemainWeight.value?.governmental ?? [];
|
||||
governmentalProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
}; */
|
||||
}
|
||||
|
||||
void _updateFreeProductionDateData() {
|
||||
/* var dates = rootLogic.stewardRemainWeight.value?.free ?? [];
|
||||
freeProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
}; */
|
||||
}
|
||||
|
||||
void setSearchValue(String? value) {
|
||||
searchedValue.value = value?.trim();
|
||||
}
|
||||
|
||||
void submitFilter() {
|
||||
fromDateFilter.value = fromDateFilter.value;
|
||||
toDateFilter.value = toDateFilter.value;
|
||||
getOutProvinceSales();
|
||||
}
|
||||
|
||||
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);
|
||||
saleWeightController.addListener(() {
|
||||
checkSalesFormValid();
|
||||
weight.value = int.parse(saleWeightController.text.clearComma);
|
||||
var res = (weight / selectedProduct.value!.weightAverage!.toInt()).round();
|
||||
saleCountController.text = res.separatedByComma;
|
||||
});
|
||||
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 = rootLogic.rolesProductsModel.first;
|
||||
key = item.key;
|
||||
saleType.value = item.saleType == 'free' ? 2 : 1;
|
||||
quotaType.value = item.quota == 'governmental' ? 1 : 2;
|
||||
isSaleSubmitButtonEnabled.value = true;
|
||||
productionDate.value = item.productionDate.toJalali;
|
||||
pricePerKiloController.text = pricePerKilo.value.toString().separatedByComma;
|
||||
totalCostController.text = totalCost.value.toString().separatedByComma;
|
||||
}
|
||||
|
||||
Future<void> deleteStewardPurchaseOutOfProvince(String key) async {
|
||||
/* await safeCall(
|
||||
call: () => rootLogic.chickenRepository.deleteOutProvinceStewardFreeBar(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
key: key,
|
||||
),
|
||||
); */
|
||||
}
|
||||
|
||||
Future<bool> createSale() async {
|
||||
bool res = false;
|
||||
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
|
||||
buyerKey: selectedBuyer.value?.key,
|
||||
numberOfCarcasses: int.tryParse(saleCountController.text.clearComma),
|
||||
weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma),
|
||||
date: saleDate.value.toDateTime().formattedDashedGregorian,
|
||||
clearanceCode: quarantineCodeController.text,
|
||||
productKey: selectedProduct.value?.key,
|
||||
saleType: saleType.value == 2 ? 'free' : 'exclusive',
|
||||
quota: quotaType.value == 1 ? 'governmental' : 'free',
|
||||
productionDate: productionDate.value?.toDateTime().formattedDashedGregorian,
|
||||
);
|
||||
/* await safeCall(
|
||||
showError: true,
|
||||
call: () => rootLogic.chickenRepository.createOutProvinceStewardFreeBar(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
body: requestBody,
|
||||
),
|
||||
onSuccess: (_) {
|
||||
res = true;
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("عملیات با موفقیت انجام شد"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
); */
|
||||
return res;
|
||||
}
|
||||
|
||||
void clearSaleForm() {
|
||||
quarantineCodeController.clear();
|
||||
saleWeightController.clear();
|
||||
saleDate.value = Jalali.now();
|
||||
productionDate.value = null;
|
||||
saleType.value = 2;
|
||||
quotaType.value = 2;
|
||||
selectedBuyer.value = null;
|
||||
}
|
||||
|
||||
Future<bool> editSale() async {
|
||||
bool res = false;
|
||||
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
|
||||
numberOfCarcasses: int.tryParse(saleCountController.text.clearComma),
|
||||
weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma),
|
||||
date: saleDate.value.toDateTime().formattedDashedGregorian,
|
||||
clearanceCode: quarantineCodeController.text,
|
||||
saleType: saleType.value == 2 ? 'free' : 'exclusive',
|
||||
quota: quotaType.value == 1 ? 'governmental' : 'free',
|
||||
key: key,
|
||||
);
|
||||
/* await safeCall(
|
||||
call: () => rootLogic.chickenRepository.updateOutProvinceStewardFreeBar(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
body: requestBody,
|
||||
),
|
||||
onSuccess: (_) {
|
||||
res = true;
|
||||
onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("عملیات با موفقیت انجام شد"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
); */
|
||||
return res;
|
||||
}
|
||||
|
||||
Future sendSaleOtpCode(StewardFreeSaleBar item) async {
|
||||
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
|
||||
buyerKey: item.buyer?.key,
|
||||
buyerName: item.buyer?.fullname,
|
||||
buyerMobile: item.buyer?.mobile,
|
||||
numberOfCarcasses: item.numberOfCarcasses,
|
||||
weightOfCarcasses: item.weightOfCarcasses?.toInt(),
|
||||
date: item.date,
|
||||
clearanceCode: item.clearanceCode,
|
||||
registerCode: otpCode.value,
|
||||
saleType: item.saleType,
|
||||
quota: item.quota,
|
||||
role: "Steward",
|
||||
key: item.key,
|
||||
city: item.city,
|
||||
province: item.province,
|
||||
);
|
||||
/* await safeCall(
|
||||
showError: true,
|
||||
call: () => rootLogic.chickenRepository.updateOutProvinceStewardFreeBar(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
body: requestBody,
|
||||
),
|
||||
onSuccess: (_) {
|
||||
onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("عملیات با موفقیت انجام شد"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
); */
|
||||
}
|
||||
|
||||
void resetSubmitForm() {
|
||||
selectedCity.value = null;
|
||||
|
||||
key = null;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
toggleExpansion();
|
||||
currentPage.value = 1;
|
||||
resetSubmitForm();
|
||||
clearSaleForm();
|
||||
await rootLogic.onRefresh();
|
||||
await getOutProvinceSales();
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getBroadcastPrice() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getBroadcastPrice(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
broadcastPrice.value = result;
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
void setSaleDate(Jalali value) {
|
||||
saleDate.value = value;
|
||||
saleDate.refresh();
|
||||
dateErrorDialog();
|
||||
}
|
||||
|
||||
void setProductionDate(DayInfo value) {
|
||||
productionDate.value = value.date;
|
||||
remainingStock.value = value.remainingStock;
|
||||
dateErrorDialog();
|
||||
}
|
||||
|
||||
void dateErrorDialog() {
|
||||
if ((productionDate.value?.distanceTo(saleDate.value) ?? 0) >= 1) {
|
||||
saleDate.value = Jalali.now();
|
||||
Future.delayed(
|
||||
Duration(milliseconds: 300),
|
||||
() => defaultShowErrorMessage("تاریخ تولید نمی تواند قبل از تاریخ فروش باشد"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,233 +0,0 @@
|
||||
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/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sales_out_of_province/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionSalesOutOfProvinceBuyersLogic
|
||||
extends GetxController {
|
||||
WarehouseAndDistributionRootLogic rootLogic =
|
||||
Get.find<WarehouseAndDistributionRootLogic>();
|
||||
|
||||
WarehouseAndDistributionSaleLogic get saleLogic =>
|
||||
Get.find<WarehouseAndDistributionSaleLogic>();
|
||||
|
||||
WarehouseAndDistributionSalesOutOfProvinceLogic get saleOutOfProvince =>
|
||||
Get.find<WarehouseAndDistributionSalesOutOfProvinceLogic>();
|
||||
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedListIndex = (-1).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;
|
||||
|
||||
RxList<String> routesName = RxList();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName.value = [...saleLogic.routesName, 'خریداران'].toList();
|
||||
getOutProvinceCarcassesBuyer();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
|
||||
selectedProvince.listen((p0) => getCites());
|
||||
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getOutProvinceCarcassesBuyer(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
|
||||
setupListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
buyerNameController.dispose();
|
||||
buyerLastNameController.dispose();
|
||||
buyerPhoneController.dispose();
|
||||
buyerUnitNameController.dispose();
|
||||
selectedCity.value = null;
|
||||
selectedProvince.value = null;
|
||||
|
||||
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',
|
||||
);
|
||||
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;
|
||||
}
|
||||
|
||||
void setSearchValue(String? value) {
|
||||
searchedValue.value = value?.trim();
|
||||
}
|
||||
|
||||
void submitFilter() {
|
||||
fromDateFilter.value = fromDateFilter.value;
|
||||
toDateFilter.value = toDateFilter.value;
|
||||
getOutProvinceCarcassesBuyer();
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await rootLogic.onRefresh();
|
||||
await getOutProvinceCarcassesBuyer();
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
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/utils/nested_keys_utils.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 WarehouseAndDistributionSalesOutOfProvinceBuyersPage extends GetView<WarehouseAndDistributionSalesOutOfProvinceBuyersLogic> {
|
||||
const WarehouseAndDistributionSalesOutOfProvinceBuyersPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
backId: stewardSecondKey,
|
||||
onRefresh: controller.onRefresh,
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
filteringWidget: filterBottomSheet(),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: Get.width,
|
||||
height: 39,
|
||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.greenLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.textColor, width: 0.5),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'لیست خریداران خارج از استان',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkHover),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
onLoadMore: () async => controller.getOutProvinceCarcassesBuyer(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),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.userRaduisSvg.path,
|
||||
);
|
||||
}, controller.expandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
);
|
||||
}, controller.buyerList),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 100,
|
||||
child: RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
addOrEditBuyerBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).whenComplete(() => controller.resetSubmitForm());
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget addOrEditBuyerBottomSheet([bool isOnEdit = false]) {
|
||||
return BaseBottomSheet(
|
||||
height: 600,
|
||||
child: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
isOnEdit ? 'ویرایش خریدار' : 'افزودن خریدار',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
|
||||
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: [_provinceWidget(), _cityWidget()]),
|
||||
),
|
||||
|
||||
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: [
|
||||
RTextField(
|
||||
controller: controller.buyerNameController,
|
||||
label: 'نام خریدار',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.buyerLastNameController,
|
||||
label: 'نام خانوادگی خریدار',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.buyerPhoneController,
|
||||
label: 'تلفن خریدار',
|
||||
keyboardType: TextInputType.phone,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
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.buyerUnitNameController,
|
||||
label: 'نام واحد',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
|
||||
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 = 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);
|
||||
}
|
||||
|
||||
Padding itemListWidget(OutProvinceCarcassesBuyer item) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 8),
|
||||
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(OutProvinceCarcassesBuyer item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
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.separatedByCommaFa}',
|
||||
),
|
||||
buildRow(
|
||||
title: 'حجم تقریبی',
|
||||
value: '${item.requestsInfo?.totalQuantity.separatedByCommaFa}',
|
||||
valueLabel: 'قطعه',
|
||||
),
|
||||
buildRow(
|
||||
title: 'وزن',
|
||||
value: '${item.requestsInfo?.totalWeight.separatedByCommaFa}',
|
||||
valueLabel: 'کیلوگرم',
|
||||
),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'ویرایش',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
controller.setEditDataBuyer(item);
|
||||
Get.bottomSheet(
|
||||
addOrEditBuyerBottomSheet(true),
|
||||
isScrollControlled: true,
|
||||
).whenComplete(() => controller.resetSubmitForm());
|
||||
},
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() => filterBottomSheetWidget(
|
||||
fromDate: controller.fromDateFilter,
|
||||
onChangedFromDate: (jalali) => controller.fromDateFilter.value = jalali,
|
||||
toDate: controller.toDateFilter,
|
||||
onChangedToDate: (jalali) => controller.toDateFilter.value = jalali,
|
||||
onSubmit: () => controller.submitFilter(),
|
||||
);
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
import 'package:flutter/material.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/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/sales_out_of_province_buyers/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionSalesOutOfProvinceSalesListLogic extends GetxController {
|
||||
WarehouseAndDistributionRootLogic rootLogic = Get.find<WarehouseAndDistributionRootLogic>();
|
||||
|
||||
WarehouseAndDistributionSaleLogic saleLogic = Get.find<WarehouseAndDistributionSaleLogic>();
|
||||
|
||||
WarehouseAndDistributionSalesOutOfProvinceBuyersLogic buyerLogic = Get.find<WarehouseAndDistributionSalesOutOfProvinceBuyersLogic>();
|
||||
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
RxBool isExpanded = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxBool isSaleSubmitButtonEnabled = false.obs;
|
||||
RxInt expandedListIndex = (-1).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();
|
||||
|
||||
|
||||
|
||||
RxInt saleType = 1.obs;
|
||||
RxInt quotaType = 1.obs;
|
||||
|
||||
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
TextEditingController quarantineCodeController = TextEditingController();
|
||||
TextEditingController saleWeightController = TextEditingController();
|
||||
TextEditingController saleCountController = 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();
|
||||
|
||||
//selectedProduct.value = rootLogic.rolesProductsModel.first;
|
||||
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() {
|
||||
|
||||
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 = rootLogic.rolesProductsModel.first;
|
||||
key = item.key;
|
||||
isSaleSubmitButtonEnabled.value = true;
|
||||
}
|
||||
|
||||
Future<void> deleteStewardPurchaseOutOfProvince(String key) async {
|
||||
//todo
|
||||
/* await safeCall(
|
||||
call: () => rootLogic.chickenRepository
|
||||
.editStewardPurchasesOutSideOfTheProvince(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
stewardFreeBarKey: key,
|
||||
),
|
||||
);*/
|
||||
}
|
||||
|
||||
Future<bool> createSale() async {
|
||||
bool res = false;
|
||||
var tmpWight = int.tryParse(saleWeightController.text.clearComma);
|
||||
var tmpCount = (tmpWight! / selectedProduct.value!.weightAverage!).round();
|
||||
|
||||
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
|
||||
buyerKey: selectedBuyer.value?.key,
|
||||
numberOfCarcasses: tmpCount,
|
||||
weightOfCarcasses: tmpWight,
|
||||
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;
|
||||
}
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,498 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
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/routes/routes.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class WarehouseAndDistributionSalesOutOfProvinceSalesListPage extends GetView<WarehouseAndDistributionSalesOutOfProvinceSalesListLogic> {
|
||||
const WarehouseAndDistributionSalesOutOfProvinceSalesListPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
onLoadMore: () async => controller.getOutProvinceSales(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,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item, index),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.timerSvg.path,
|
||||
labelIconColor: AppColor.yellowNormal2,
|
||||
);
|
||||
}, controller.expandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
);
|
||||
}, controller.salesList),
|
||||
floatingActionButton: Row(
|
||||
children: [
|
||||
RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
addOrEditSaleBottomSheet(),
|
||||
ignoreSafeArea: false,
|
||||
isScrollControlled: true,
|
||||
).whenComplete(() {
|
||||
controller.clearSaleForm();
|
||||
});
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
RFab(
|
||||
icon: Icon(CupertinoIcons.person_add_solid, color: Colors.white, size: 35.w),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
onPressed: () {
|
||||
Get.toNamed(ChickenRoutes.salesOutOfProvinceBuyerSteward, id: 1);
|
||||
},
|
||||
),
|
||||
SizedBox(width: 25),
|
||||
],
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(StewardFreeSaleBar item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text(
|
||||
item.date?.formattedJalaliDate ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.buyer?.fullname ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
item.buyer?.mobile ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
item.buyer?.unitName ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
Text(
|
||||
'${item.weightOfCarcasses?.separatedByCommaFa ?? 0}KG',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(StewardFreeSaleBar item, int index) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${item.province}-${item.city}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'ندارد',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
buildRow(title: 'مشخصات خریدار', value: item.buyer?.fullname ?? 'ندارد'),
|
||||
buildRow(title: 'تلفن خریدار', value: item.buyer?.mobile ?? 'ندارد'),
|
||||
buildRow(title: 'نام واحد', value: item.buyer?.unitName ?? 'ندارد'),
|
||||
buildRow(title: 'وزن لاشه', value: '${item.weightOfCarcasses?.separatedByCommaFa}'),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'ویرایش',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
controller.setEditDataSales(item);
|
||||
Get.bottomSheet(
|
||||
addOrEditSaleBottomSheet(true),
|
||||
isScrollControlled: true,
|
||||
).whenComplete(() {
|
||||
controller.resetSubmitForm();
|
||||
});
|
||||
},
|
||||
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.deleteStewardPurchaseOutOfProvince(item.key!);
|
||||
},
|
||||
onRefresh: () => controller.getOutProvinceSales(),
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget addOrEditSaleBottomSheet([bool isOnEdit = false]) {
|
||||
return BaseBottomSheet(
|
||||
height: 500.h,
|
||||
child: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
isOnEdit ? 'ویرایش فروش' : 'افزودن فروش',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
//_productDropDown(),
|
||||
|
||||
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: [
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: timeFilterWidget(
|
||||
date: controller.saleDate,
|
||||
onChanged: (jalali) => controller.saleDate.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
_buyerWidget(),
|
||||
RTextField(
|
||||
controller: controller.saleWeightController,
|
||||
label: 'وزن لاشه',
|
||||
keyboardType: TextInputType.number,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
|
||||
validator: (value) {
|
||||
if (value == null) {
|
||||
return 'لطفاً وزن لاشه را وارد کنید';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.saleCountController,
|
||||
label: 'حجم تقریبی(قطعه)',
|
||||
keyboardType: TextInputType.number,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
|
||||
validator: (value) {
|
||||
if (value == null) {
|
||||
return 'لطفاً وزن لاشه را وارد کنید';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.quarantineCodeController,
|
||||
label: 'کد قرنطینه',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
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.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 _productDropDown() {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<ProductModel>(
|
||||
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}',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
} */
|
||||
|
||||
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: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: AppColor.darkGreyLight),
|
||||
),
|
||||
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;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,308 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/broadcast_price/broadcast_price.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/pages/kill_house/warehouse_and_distribution/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class WarehouseAndDistributionSegmentationLogic extends GetxController {
|
||||
WarehouseAndDistributionRootLogic rootLogic = Get.find<WarehouseAndDistributionRootLogic>();
|
||||
|
||||
RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
|
||||
late List<String> routesName;
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
RxBool isExpanded = false.obs;
|
||||
|
||||
RxInt expandedListIndex = (-1).obs;
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
RxInt segmentType = 1.obs;
|
||||
RxInt priceType = 2.obs;
|
||||
RxInt quotaType = 2.obs;
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
TextEditingController weightController = TextEditingController(text: '0');
|
||||
RxBool isSubmitButtonEnabled = false.obs;
|
||||
Rxn<GuildModel> selectedGuildModel = Rxn<GuildModel>();
|
||||
Rxn<ProductModel> selectedProduct = Rxn<ProductModel>();
|
||||
Rxn<SegmentationModel> selectedSegment = Rxn<SegmentationModel>();
|
||||
Rxn<BroadcastPrice> broadcastPrice = Rxn<BroadcastPrice>();
|
||||
Rx<Resource<PaginationModel<SegmentationModel>>> segmentationList =
|
||||
Resource<PaginationModel<SegmentationModel>>.loading().obs;
|
||||
|
||||
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
|
||||
Rx<Jalali> saleDate = Jalali.now().obs;
|
||||
RxInt weight = 0.obs;
|
||||
Rxn<Jalali> productionDate = Rxn(null);
|
||||
Rxn<int> remainingStock = Rxn(null);
|
||||
Map<String, DayData> freeProductionDateData = {};
|
||||
Map<String, DayData> governmentalProductionDateData = {};
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName = ['قطعهبندی'].toList();
|
||||
//once(rootLogic.rolesProductsModel, (callback) => selectedProduct.value = callback.first);
|
||||
getAllSegmentation();
|
||||
getGuilds();
|
||||
|
||||
ever(quotaType, (_) {
|
||||
remainingStock.value = null;
|
||||
productionDate.value = null;
|
||||
});
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
/* ever(rootLogic.stewardRemainWeight, (callback) {
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
}); */
|
||||
}
|
||||
|
||||
void _updateGovernmentalProductionDateData() {
|
||||
/* List<RemainWeightDay> dates = rootLogic.stewardRemainWeight.value?.governmental ?? [];
|
||||
governmentalProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
}; */
|
||||
}
|
||||
|
||||
void _updateFreeProductionDateData() {
|
||||
/* var dates = rootLogic.stewardRemainWeight.value?.free ?? [];
|
||||
freeProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
}; */
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
setUpListener();
|
||||
}
|
||||
|
||||
|
||||
void setSearchValue(String? value) {
|
||||
searchedValue.value = value?.trim();
|
||||
}
|
||||
|
||||
void setUpListener() {
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getAllSegmentation(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
|
||||
everAll([selectedSegment, quotaType, priceType], (_) {
|
||||
validateForm();
|
||||
});
|
||||
|
||||
weightController.addListener(() => validateForm());
|
||||
}
|
||||
|
||||
void setEditData(SegmentationModel item) {
|
||||
selectedSegment.value = item;
|
||||
weightController.text = item.weight.toString();
|
||||
}
|
||||
|
||||
void clearForm() {
|
||||
weightController.text = '0';
|
||||
selectedSegment.value = null;
|
||||
selectedGuildModel.value = null;
|
||||
productionDate.value = null;
|
||||
segmentType.value = 1;
|
||||
priceType.value = 2;
|
||||
quotaType.value = 1;
|
||||
remainingStock.value = null;
|
||||
}
|
||||
|
||||
void validateForm() {
|
||||
var weight = int.tryParse(weightController.text.trim().clearComma) ?? 0;
|
||||
var hasWeight = (remainingStock.value ?? 0) > weight;
|
||||
isSubmitButtonEnabled.value =
|
||||
selectedProduct.value != null &&
|
||||
weightController.text.isNotEmpty &&
|
||||
hasWeight &&
|
||||
productionDate.value != null &&
|
||||
weight > 0 &&
|
||||
(segmentType.value == 1 || (segmentType.value == 2 && selectedGuildModel.value != null));
|
||||
}
|
||||
|
||||
Future<void> getAllSegmentation([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
segmentationList.value = Resource<PaginationModel<SegmentationModel>>.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(
|
||||
showError: true,
|
||||
call: () async => await rootLogic.chickenRepository.getSegmentation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
pageSize: 20,
|
||||
page: currentPage.value,
|
||||
search: 'filter',
|
||||
role: 'Steward',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
),
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
if ((result?.count ?? 0) == 0) {
|
||||
segmentationList.value = Resource<PaginationModel<SegmentationModel>>.empty();
|
||||
} else {
|
||||
segmentationList.value = Resource<PaginationModel<SegmentationModel>>.success(
|
||||
PaginationModel<SegmentationModel>(
|
||||
count: result?.count ?? 0,
|
||||
next: result?.next,
|
||||
previous: result?.previous,
|
||||
results: [
|
||||
...(segmentationList.value.data?.results ?? []),
|
||||
...(result?.results ?? []),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
isLoadingMoreAllocationsMade.value = false;
|
||||
}
|
||||
},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> deleteSegmentation(String key) async {
|
||||
/* await safeCall(
|
||||
showError: true,
|
||||
showSuccess: true,
|
||||
call: () => rootLogic.chickenRepository.deleteSegmentation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
key: key,
|
||||
),
|
||||
); */
|
||||
}
|
||||
|
||||
Future<bool> editSegment() async {
|
||||
var res = true;
|
||||
/* safeCall(
|
||||
showError: true,
|
||||
call: () async => await rootLogic.chickenRepository.editSegmentation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
model: SegmentationModel(
|
||||
key: selectedSegment.value?.key,
|
||||
weight: int.tryParse(weightController.text.clearComma) ?? 0,
|
||||
productionDate: productionDate.value?.toDateTime().formattedDashedGregorian,
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
res = true;
|
||||
onRefresh();
|
||||
},
|
||||
onError: (error, stacktrace) {
|
||||
res = false;
|
||||
},
|
||||
); */
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<bool> createSegment() async {
|
||||
var res = true;
|
||||
SegmentationModel segmentationModel = SegmentationModel(
|
||||
productKey: selectedProduct.value?.key,
|
||||
weight: int.tryParse(weightController.text.clearComma) ?? 0,
|
||||
saleType: priceType.value == 1 ? 'governmental' : 'free',
|
||||
quota: quotaType.value == 1 ? 'governmental' : 'free',
|
||||
);
|
||||
if (segmentType.value == 2) {
|
||||
segmentationModel = segmentationModel.copyWith(guildKey: selectedGuildModel.value?.key);
|
||||
}
|
||||
segmentationModel = segmentationModel.copyWith(
|
||||
productionDate: productionDate.value?.toDateTime().formattedDashedGregorian,
|
||||
);
|
||||
/* await safeCall(
|
||||
showError: true,
|
||||
call: () async => await rootLogic.chickenRepository.createSegmentation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
model: segmentationModel,
|
||||
),
|
||||
onSuccess: (result) async {
|
||||
res = true;
|
||||
isSubmitButtonEnabled.value = false;
|
||||
onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("قطعهبندی با موفقیت ثبت شد!"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
onError: (error, stacktrace) {
|
||||
res = false;
|
||||
},
|
||||
); */
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<void> getGuilds() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getGuilds(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(queryParams: {'all': true}, role: 'Steward'),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
guildsModel.clear();
|
||||
guildsModel.addAll(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
toggleExpansion();
|
||||
currentPage.value = 1;
|
||||
await rootLogic.onRefresh();
|
||||
await getAllSegmentation();
|
||||
await getBroadcastPrice();
|
||||
_updateFreeProductionDateData();
|
||||
_updateGovernmentalProductionDateData();
|
||||
}
|
||||
|
||||
Future<void> getBroadcastPrice() async {
|
||||
/* safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getBroadcastPrice(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
broadcastPrice.value = result;
|
||||
if (broadcastPrice.value?.active == true) {
|
||||
priceType.value = 2;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
); */
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/segmentation_model/segmentation_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/segmentation/widgets/cu_bottom_sheet.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 WarehouseAndDistributionSegmentationPage
|
||||
extends GetView<WarehouseAndDistributionSegmentationLogic> {
|
||||
WarehouseAndDistributionSegmentationPage({super.key});
|
||||
|
||||
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(controller),
|
||||
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(),
|
||||
);
|
||||
|
||||
Row 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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container 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(controller, isOnEdit: 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,396 +0,0 @@
|
||||
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/presentation/pages/kill_house/warehouse_and_distribution/segmentation/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
Widget addOrEditBottomSheet(WarehouseAndDistributionSegmentationLogic controller, {bool isOnEdit = false}) {
|
||||
return BaseBottomSheet(
|
||||
height: isOnEdit ? 350.h : 600.h,
|
||||
child: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
isOnEdit ? 'ویرایش قطعهبندی' : 'افزودن قطعهبندی',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
_productDropDown(controller),
|
||||
Visibility(
|
||||
visible: isOnEdit == false,
|
||||
child: 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.quotaType.value = 1;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 1),
|
||||
Text('دولتی', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.quotaType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Obx(() {
|
||||
return MonthlyDataCalendar(
|
||||
label: 'تاریخ تولید گوشت',
|
||||
selectedDate: controller.productionDate.value?.formatCompactDate(),
|
||||
onDateSelect: (value) {
|
||||
controller.productionDate.value = value.date;
|
||||
controller.remainingStock.value = value.remainingStock;
|
||||
},
|
||||
dayData: controller.quotaType.value == 1
|
||||
? controller.governmentalProductionDateData
|
||||
: controller.freeProductionDateData,
|
||||
);
|
||||
}),
|
||||
|
||||
RTextField(
|
||||
controller: controller.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
autoValidateMode: AutovalidateMode.onUserInteraction,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
validator: (value) {
|
||||
if ((int.tryParse(value?.clearComma ?? '0') ?? 0) >
|
||||
(controller.remainingStock.value ?? 0)) {
|
||||
return 'وزن تخصیصی بیشتر از موجودی انبار است';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (p0) {
|
||||
controller.weight.value = int.tryParse(p0.clearComma) ?? 0;
|
||||
},
|
||||
label: 'وزن لاشه (کیلوگرم)',
|
||||
),
|
||||
Visibility(
|
||||
visible: isOnEdit == false,
|
||||
child: Container(
|
||||
height: 58.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.priceType.value,
|
||||
onChanged: (value) {
|
||||
controller.priceType.value = value!;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: (controller.broadcastPrice.value?.active ?? false)
|
||||
? () {
|
||||
controller.priceType.value = 1;
|
||||
}
|
||||
: null,
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(
|
||||
value: 1,
|
||||
enabled: controller.broadcastPrice.value?.active ?? false,
|
||||
),
|
||||
Text(
|
||||
'قیمت مصوب',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: (controller.broadcastPrice.value?.active ?? false)
|
||||
? AppColor.textColor
|
||||
: AppColor.labelTextColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.priceType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('قیمت آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
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.priceType),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: data.value == 2,
|
||||
child: guildsDropDown(controller),
|
||||
);
|
||||
}, controller.segmentType),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
submitButtonWidget(controller, isOnEdit: isOnEdit),
|
||||
|
||||
SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget submitButtonWidget(WarehouseAndDistributionSegmentationLogic controller, {bool isOnEdit = false}) {
|
||||
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(WarehouseAndDistributionSegmentationLogic controller) {
|
||||
/* return Obx(() {
|
||||
return OverlayDropdownWidget<ProductModel>(
|
||||
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(),
|
||||
ObxValue((data) {
|
||||
return Visibility(visible: data.value != null, child: Text('موجودی: $data'));
|
||||
}, controller.remainingStock),
|
||||
],
|
||||
),
|
||||
);
|
||||
}); */
|
||||
return Container();
|
||||
}
|
||||
|
||||
Widget guildsDropDown(WarehouseAndDistributionSegmentationLogic controller) {
|
||||
return Obx(() {
|
||||
final item = controller.selectedGuildModel.value;
|
||||
return OverlayDropdownWidget<GuildModel>(
|
||||
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(WarehouseAndDistributionSegmentationLogic controller, ValueChanged<Jalali> onDateSelected) {
|
||||
Jalali currentDate = Jalali.now();
|
||||
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,
|
||||
maximumDate: currentDate.addDays(3),
|
||||
minimumDate: currentDate.toDateTime().subtract(Duration(days: 1)).toString().toJalali,
|
||||
maximumYear: currentDate.year,
|
||||
minimumYear: currentDate.year,
|
||||
onDateTimeChanged: (dateTime) {
|
||||
tempPickedDate = dateTime;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
export 'buy/logic.dart';
|
||||
export 'buy/view.dart';
|
||||
export 'buy_in_province/logic.dart';
|
||||
export 'buy_in_province/view.dart';
|
||||
export 'buy_in_province_all/logic.dart';
|
||||
export 'buy_in_province_all/view.dart';
|
||||
export 'buy_in_province_waiting/logic.dart';
|
||||
export 'buy_in_province_waiting/view.dart';
|
||||
export 'buy_out_of_province/logic.dart';
|
||||
export 'buy_out_of_province/view.dart';
|
||||
export 'home/logic.dart';
|
||||
export 'home/view.dart';
|
||||
export 'root/logic.dart';
|
||||
export 'root/view.dart';
|
||||
export 'sale/logic.dart';
|
||||
export 'sale/view.dart';
|
||||
export 'sales_in_province/logic.dart';
|
||||
export 'sales_in_province/view.dart';
|
||||
export 'sales_out_of_province/logic.dart';
|
||||
export 'sales_out_of_province/view.dart';
|
||||
export 'sales_out_of_province_buyers/logic.dart';
|
||||
export 'sales_out_of_province_buyers/view.dart';
|
||||
export 'sales_out_of_province_sales_list/logic.dart';
|
||||
export 'sales_out_of_province_sales_list/view.dart';
|
||||
export 'segmentation/logic.dart';
|
||||
export 'segmentation/view.dart';
|
||||
@@ -1,151 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
|
||||
class PoultryFarmInspectionHomeLogic extends GetxController
|
||||
with GetTickerProviderStateMixin {
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
RxList<Resource<PaginationModel<String>>> inspectionList = RxList([
|
||||
Resource<PaginationModel<String>>.success(
|
||||
PaginationModel(results: ["s", "b", "c", "d"]),
|
||||
),
|
||||
]);
|
||||
RxList<Resource<PaginationModel<String>>> inactiveInspectionList = RxList([
|
||||
Resource<PaginationModel<String>>.success(
|
||||
PaginationModel(results: ["s", "b", "c", "d"]),
|
||||
),
|
||||
]);
|
||||
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
|
||||
late TabController tabController;
|
||||
|
||||
RxInt selectedTabIndex = 0.obs;
|
||||
|
||||
RxInt activeStepperIndex = 0.obs;
|
||||
|
||||
PageController pageController = PageController(initialPage: 0);
|
||||
|
||||
//step1
|
||||
|
||||
TextEditingController nameOfThePoultryFarmUnit = TextEditingController();
|
||||
|
||||
//step2
|
||||
RxInt sanitaryConditionOfTheHallIndex = (-1).obs;
|
||||
RxInt ventilationStatusIndex = (-1).obs;
|
||||
RxInt beddingStatusIndex = (-1).obs;
|
||||
RxInt waterQualityIndex = (-1).obs;
|
||||
RxInt fuelTypeIndex = (-1).obs;
|
||||
RxInt sampleTypeIndex = (-1).obs;
|
||||
|
||||
//step3
|
||||
RxInt grainQualityInputIndex = (-1).obs;
|
||||
RxInt generatorOperatingStatusIndex = (-1).obs;
|
||||
RxInt workerContractStatusIndex = (-1).obs;
|
||||
RxInt newBeneficiaryRequestIndex = (-1).obs;
|
||||
|
||||
//step4
|
||||
RxInt inspectorConclusionIndex = (-1).obs;
|
||||
TextEditingController inspectorConclusionDescriptionController =
|
||||
TextEditingController();
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
|
||||
activeStepperIndex.listen((value) {
|
||||
pageController.animateToPage(
|
||||
value,
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.linear,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
void changeSegmentIndex(int index) {
|
||||
if (index == selectedSegmentIndex.value) {
|
||||
return;
|
||||
}
|
||||
expandedIndex.value = -1;
|
||||
selectedSegmentIndex.value = index;
|
||||
}
|
||||
|
||||
void changeTab(int index) {
|
||||
if (index == selectedTabIndex.value) {
|
||||
return;
|
||||
}
|
||||
selectedTabIndex.value = index;
|
||||
}
|
||||
|
||||
void clearForm() {
|
||||
nameOfThePoultryFarmUnit.clear();
|
||||
activeStepperIndex.value = 0;
|
||||
selectedTabIndex.value = 0;
|
||||
}
|
||||
|
||||
void setSanitaryConditionOfTheHallIndex(int index) {
|
||||
sanitaryConditionOfTheHallIndex.value =
|
||||
index == sanitaryConditionOfTheHallIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setFuelTypeIndex(int index) {
|
||||
fuelTypeIndex.value = index == fuelTypeIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setVentilationStatusIndex(int index) {
|
||||
ventilationStatusIndex.value = index == ventilationStatusIndex.value
|
||||
? -1
|
||||
: index;
|
||||
}
|
||||
|
||||
void setBeddingStatusIndex(int index) {
|
||||
beddingStatusIndex.value = index == beddingStatusIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setWaterQualityIndex(int index) {
|
||||
waterQualityIndex.value = index == waterQualityIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setSampleTypeIndex(int index) {
|
||||
sampleTypeIndex.value = index == sampleTypeIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setGrainQualityInputIndex(int index) {
|
||||
grainQualityInputIndex.value = index == grainQualityInputIndex.value
|
||||
? -1
|
||||
: index;
|
||||
}
|
||||
|
||||
void setGeneratorOperatingStatusIndex(int index) {
|
||||
generatorOperatingStatusIndex.value =
|
||||
index == generatorOperatingStatusIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setWorkerContractStatusIndex(int index) {
|
||||
workerContractStatusIndex.value = index == workerContractStatusIndex.value
|
||||
? -1
|
||||
: index;
|
||||
}
|
||||
|
||||
void setNewBeneficiaryRequestIndex(int index) {
|
||||
newBeneficiaryRequestIndex.value = index == newBeneficiaryRequestIndex.value
|
||||
? -1
|
||||
: index;
|
||||
}
|
||||
|
||||
void setInspectorConclusionIndex(int index) {
|
||||
inspectorConclusionIndex.value = index == inspectorConclusionIndex.value
|
||||
? -1
|
||||
: index;
|
||||
}
|
||||
}
|
||||
@@ -1,934 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/info_card/info_card.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import '../widgets/cu_bottom_sheet.dart';
|
||||
import 'logic.dart';
|
||||
|
||||
class PoultryFarmInspectionHomePage extends GetView<PoultryFarmInspectionHomeLogic> {
|
||||
const PoultryFarmInspectionHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
onFilterTap: () {
|
||||
//TODO
|
||||
},
|
||||
|
||||
onSearchTap: () {
|
||||
//TODO
|
||||
},
|
||||
|
||||
onSearchChanged: (data) {
|
||||
//TODO
|
||||
},
|
||||
backId: poultryFirstKey,
|
||||
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
infoCards(),
|
||||
segmentWidget(),
|
||||
ObxValue((data) {
|
||||
return data.value == 0 ? activeInspectionWidget() : inactiveInspectionWidget();
|
||||
}, controller.selectedSegmentIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Positioned(
|
||||
right: 10,
|
||||
bottom: 90.h,
|
||||
child: RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
addOrEditBottomSheet(controller),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).then((value) => controller.clearForm());
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Padding infoCards() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(9, 12, 9, 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
spacing: 8,
|
||||
children: [
|
||||
cardInfo(value: 2225256, description: 'بازرسی شده', color: const Color(0xFFB6DED8)),
|
||||
cardInfo(value: 2050, description: 'بازرسی نشده', color: const Color(0xFFE9CED7)),
|
||||
cardInfo(value: 2225256, description: 'عملکرد مناسب', color: const Color(0xFFCFE0FF)),
|
||||
cardInfo(value: 55225, description: 'عملکرد ضعیف', color: const Color(0xFFF3D6CB)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Padding segmentWidget() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RSegment(
|
||||
children: ['بازرسی فعال', 'بایگانی'],
|
||||
selectedIndex: 0,
|
||||
borderColor: const Color(0xFFB4B4B4),
|
||||
selectedBorderColor: AppColor.blueNormal,
|
||||
selectedBackgroundColor: AppColor.blueLight,
|
||||
onSegmentSelected: (index) => controller.changeSegmentIndex(index),
|
||||
backgroundColor: AppColor.whiteGreyNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget activeInspectionWidget() {
|
||||
return Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.first,
|
||||
hasMore: false,
|
||||
onLoadMore: () async {},
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: val.value.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: activeinspecitonItemListWidget(),
|
||||
secondChild: avtiveInspectionItemListExpandedWidget(),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.checkSquareSvg.path,
|
||||
labelIconColor: AppColor.mediumGreyDarkHover,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: 2,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
);
|
||||
}, controller.inspectionList),
|
||||
);
|
||||
}
|
||||
|
||||
Container avtiveInspectionItemListExpandedWidget() {
|
||||
const farmerName = 'آرمان صادقی';
|
||||
const showViolationLabel = true;
|
||||
const violationLabel = 'پیگیری';
|
||||
const breed = 'راس ۳۰۸';
|
||||
const ageInDays = '۴۲';
|
||||
const growPeriod = 'بهار ۱۴۰۴';
|
||||
const licenceNumber = '۱۲۳۴۵۶۷۸';
|
||||
const chickVolume = '۲۵,۰۰۰';
|
||||
const hallRemain = '۲۳,۴۵۰';
|
||||
const losses = '۱,۵۵۰';
|
||||
const vetInfo = 'دکتر نرگس مرادی(۰۹۳۵۴۵۶۶۷۷۹)';
|
||||
const showReportButton = true;
|
||||
const reportStatus = 'ارسال تصویر جوجه ریزی فارم';
|
||||
final reportColor = AppColor.redDark;
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
farmerName,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
Visibility(
|
||||
visible: showViolationLabel,
|
||||
child: Text(
|
||||
violationLabel,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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: [
|
||||
Text('نژاد:$breed', style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
|
||||
Text(
|
||||
' سن $ageInDays (روزه)',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:$growPeriod',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
buildRow(title: 'شماره مجوز جوجه ریزی', value: licenceNumber),
|
||||
buildUnitRow(title: 'حجم جوجه ریزی', value: chickVolume, unit: '(قطعه)'),
|
||||
buildUnitRow(title: 'مانده در سالن', value: hallRemain, unit: '(قطعه)'),
|
||||
buildUnitRow(title: 'تلفات', value: losses, unit: '(قطعه)'),
|
||||
buildRow(title: 'دامپزشک فارم', value: vetInfo),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: reportStatus,
|
||||
titleStyle: AppFonts.yekan14.copyWith(color: reportColor),
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: reportColor),
|
||||
),
|
||||
Visibility(
|
||||
visible: showReportButton,
|
||||
child: RElevated(
|
||||
text: 'ثبت بازرسی',
|
||||
isFullWidth: true,
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {},
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget activeinspecitonItemListWidget() {
|
||||
const farmerName = 'آرمان صادقی';
|
||||
const farmerMobile = '۰۹۱۲۱۲۳۴۵۶۷';
|
||||
const unitName = 'فارم نمونه آفتاب';
|
||||
const unitLicence = 'مجوز ۵۴۲۱-الف';
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 5,
|
||||
children: [
|
||||
Text(
|
||||
farmerName,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
farmerMobile,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 5,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
unitName,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
unitLicence,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget inactiveInspectionWidget() {
|
||||
return Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.first,
|
||||
hasMore: false,
|
||||
onLoadMore: () async {},
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: val.value.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: inActiveinspecitonItemListWidget(),
|
||||
secondChild: inAvtiveInspectionItemListExpandedWidget(),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.checkSquareSvg.path,
|
||||
labelIconColor: AppColor.mediumGreyDarkHover,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: 5,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
);
|
||||
}, controller.inspectionList),
|
||||
);
|
||||
}
|
||||
|
||||
Widget inActiveinspecitonItemListWidget() {
|
||||
const farmerName = 'زهرا موسوی';
|
||||
const farmerMobile = '۰۹۳۸۸۸۷۷۶۶۵';
|
||||
const unitName = 'کشت و پرورش افق سبز';
|
||||
const unitLicence = 'مجوز ۷۶۳۲-ج';
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 5,
|
||||
children: [
|
||||
Text(
|
||||
farmerName,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
farmerMobile,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 5,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
unitName,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
unitLicence,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container inAvtiveInspectionItemListExpandedWidget() {
|
||||
const farmerName = 'زهرا موسوی';
|
||||
const showViolationLabel = false;
|
||||
const violationLabel = 'عادی';
|
||||
const breed = 'کاب ۵۰۰';
|
||||
const ageInDays = '۳۵';
|
||||
const growPeriod = 'پاییز ۱۴۰۳';
|
||||
const licenceNumber = '۸۹۴۵۶۱۲۳';
|
||||
const chickVolume = '۱۸,۵۰۰';
|
||||
const hallRemain = '۱۷,۹۴۰';
|
||||
const losses = '۵۶۰';
|
||||
const vetInfo = 'دکتر حمید نادری(۰۹۱۳۴۴۵۵۶۶۷)';
|
||||
const reportStatus = 'بازدید تایید شده';
|
||||
final reportColor = AppColor.greenNormal;
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
farmerName,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
Visibility(
|
||||
visible: showViolationLabel,
|
||||
child: Text(
|
||||
violationLabel,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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: [
|
||||
Text('نژاد:$breed', style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
|
||||
Text(
|
||||
' سن $ageInDays (روزه)',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:$growPeriod',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
buildRow(title: 'شماره مجوز جوجه ریزی', value: licenceNumber),
|
||||
buildUnitRow(title: 'حجم جوجه ریزی', value: chickVolume, unit: '(قطعه)'),
|
||||
buildUnitRow(title: 'مانده در سالن', value: hallRemain, unit: '(قطعه)'),
|
||||
buildUnitRow(title: 'تلفات', value: losses, unit: '(قطعه)'),
|
||||
buildRow(title: 'دامپزشک فارم', value: vetInfo),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: reportStatus,
|
||||
titleStyle: AppFonts.yekan14.copyWith(color: reportColor),
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: reportColor),
|
||||
),
|
||||
ROutlinedElevated(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Assets.vec.excelDownloadSvg.svg(
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.greenDark, BlendMode.srcIn),
|
||||
),
|
||||
|
||||
Text(
|
||||
'مشاهده جزییات ',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
borderColor: AppColor.greenDark,
|
||||
onPressed: () {
|
||||
Get.bottomSheet(detailsWidget(), isScrollControlled: true, isDismissible: true);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget detailsWidget() {
|
||||
return BaseBottomSheet(
|
||||
height: Get.height * 0.8,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 10),
|
||||
child: Text(
|
||||
'جزییات',
|
||||
style: AppFonts.yekan18Bold.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Divider(color: AppColor.blackLightHover, height: 1, thickness: 1),
|
||||
ObxValue((data) {
|
||||
return tabBarWidget(
|
||||
['اطلاعات', 'پاییش سلامت', 'زیرساخت', 'مستندات'],
|
||||
controller.selectedTabIndex.value,
|
||||
(index) => controller.changeTab(index),
|
||||
);
|
||||
}, controller.selectedTabIndex),
|
||||
|
||||
ObxValue((data) {
|
||||
switch (data.value) {
|
||||
case 0:
|
||||
return infoTable();
|
||||
case 1:
|
||||
return healthTable();
|
||||
case 2:
|
||||
return infrastructureTable();
|
||||
case 3:
|
||||
return documentsTable();
|
||||
default:
|
||||
return infoTable();
|
||||
}
|
||||
}, controller.selectedTabIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Expanded در سطح بالاتر
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container infoTable() {
|
||||
return Container(
|
||||
height: Get.height,
|
||||
width: Get.width,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text('مشخصات کلی', style: AppFonts.yekan16Bold.copyWith(color: AppColor.iconColor)),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
children: [
|
||||
rTableRow(title: 'نام واحد مرغداری', value: 'لذیذ'),
|
||||
rTableRow(title: 'کد یکتا / شناسه واحد', value: '2541415'),
|
||||
rTableRow(title: 'نام مالک / بهرهبردار', value: 'مرغداری احمدی'),
|
||||
rTableRow(title: 'موجودی سوخت اضطراری', value: '200 لیتر'),
|
||||
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(title: 'تاریخ ثبت جوجه ریزی', value: '1402/09/19 (10:12)'),
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(title: 'تاریخ ثبت جوجه ریزی', value: '1402/09/19 (10:12)'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row rTableRow({String? title, String? value}) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 9, vertical: 11),
|
||||
alignment: Alignment.centerRight,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight2,
|
||||
border: Border(bottom: BorderSide(color: AppColor.blackLightHover, width: 1)),
|
||||
),
|
||||
child: Text(
|
||||
title ?? '',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 9, vertical: 11),
|
||||
alignment: Alignment.centerRight,
|
||||
decoration: BoxDecoration(
|
||||
border: Border(bottom: BorderSide(color: AppColor.blackLightHover, width: 1)),
|
||||
),
|
||||
child: Text(
|
||||
value ?? '',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget tabBarWidget(List<String> tabs, int selectedIndex, Function(int) onTabSelected) {
|
||||
return SizedBox(
|
||||
height: 38.h,
|
||||
width: Get.width,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned(
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Row(
|
||||
children: [
|
||||
...tabs.map(
|
||||
(tab) => GestureDetector(
|
||||
onTap: () => onTabSelected(tabs.indexOf(tab)),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 11),
|
||||
decoration: BoxDecoration(
|
||||
border: tab == tabs[selectedIndex]
|
||||
? Border(bottom: BorderSide(color: AppColor.blueNormalOld, width: 3))
|
||||
: null,
|
||||
),
|
||||
child: Text(
|
||||
tab,
|
||||
style: AppFonts.yekan12Bold.copyWith(
|
||||
color: tab == tabs[selectedIndex]
|
||||
? AppColor.blueNormalOld
|
||||
: AppColor.mediumGrey,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Divider(color: AppColor.blackLightHover, height: 1, thickness: 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget healthTable() {
|
||||
return Container(
|
||||
height: Get.height,
|
||||
width: Get.width,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text('پاییش سلامت', style: AppFonts.yekan16Bold.copyWith(color: AppColor.iconColor)),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
children: [
|
||||
rTableRow(title: 'نام واحد مرغداری', value: 'لذیذ'),
|
||||
rTableRow(title: 'کد یکتا / شناسه واحد', value: '2541415'),
|
||||
rTableRow(title: 'نام مالک / بهرهبردار', value: 'مرغداری احمدی'),
|
||||
rTableRow(title: 'موجودی سوخت اضطراری', value: '200 لیتر'),
|
||||
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(title: 'تاریخ ثبت جوجه ریزی', value: '1402/09/19 (10:12)'),
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(title: 'تاریخ ثبت جوجه ریزی', value: '1402/09/19 (10:12)'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget infrastructureTable() {
|
||||
return Container(
|
||||
height: Get.height,
|
||||
width: Get.width,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text('زیرساخت', style: AppFonts.yekan16Bold.copyWith(color: AppColor.iconColor)),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
children: [
|
||||
rTableRow(title: 'نام واحد مرغداری', value: 'لذیذ'),
|
||||
rTableRow(title: 'کد یکتا / شناسه واحد', value: '2541415'),
|
||||
rTableRow(title: 'نام مالک / بهرهبردار', value: 'مرغداری احمدی'),
|
||||
rTableRow(title: 'موجودی سوخت اضطراری', value: '200 لیتر'),
|
||||
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(title: 'تاریخ ثبت جوجه ریزی', value: '1402/09/19 (10:12)'),
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(title: 'تاریخ ثبت جوجه ریزی', value: '1402/09/19 (10:12)'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget documentsTable() {
|
||||
return Container(
|
||||
height: Get.height,
|
||||
width: Get.width,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text('مستندات', style: AppFonts.yekan16Bold.copyWith(color: AppColor.iconColor)),
|
||||
],
|
||||
),
|
||||
|
||||
SizedBox(height: 16),
|
||||
|
||||
Container(
|
||||
height: 135.h,
|
||||
width: Get.width,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 100.h,
|
||||
width: Get.width,
|
||||
child: ListView.separated(
|
||||
itemCount: 10,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
width: 80.w,
|
||||
height: 80.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x33000000),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: NetworkImage("https://picsum.photos/150/150?random=$index"),
|
||||
),
|
||||
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => SizedBox(width: 10),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'200 فارم در این سالن تخمین زده شده است.',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 16),
|
||||
|
||||
Container(
|
||||
height: 135.h,
|
||||
width: Get.width,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 100.h,
|
||||
width: Get.width,
|
||||
child: ListView.separated(
|
||||
itemCount: 10,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
width: 80.w,
|
||||
height: 80.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x33000000),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: NetworkImage(
|
||||
"https://picsum.photos/150/150?random=${index * 2 + 1}",
|
||||
),
|
||||
),
|
||||
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => SizedBox(width: 10),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'انبار نهاده ها',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 16),
|
||||
|
||||
Container(
|
||||
height: 135.h,
|
||||
width: Get.width,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 100.h,
|
||||
width: Get.width,
|
||||
child: ListView.separated(
|
||||
itemCount: 10,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
width: 80.w,
|
||||
height: 80.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x33000000),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: NetworkImage(
|
||||
"https://picsum.photos/150/150?random=${index * 3 + 1}",
|
||||
),
|
||||
),
|
||||
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => SizedBox(width: 10),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'تلفات',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export 'home/logic.dart';
|
||||
export 'home/view.dart';
|
||||
@@ -1,59 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_farm_inspection/home/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
Widget farmInfoWidget({
|
||||
required PoultryFarmInspectionHomeLogic controller,
|
||||
required String title,
|
||||
required Widget child,
|
||||
EdgeInsets? padding,
|
||||
}) {
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.50, color: AppColor.mediumGrey),
|
||||
),
|
||||
|
||||
padding:
|
||||
padding ?? EdgeInsets.symmetric(horizontal: 12.w, vertical: 11.h),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: -17,
|
||||
right: 7,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 5.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.50, color: AppColor.mediumGrey),
|
||||
),
|
||||
child: Text(
|
||||
title,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget cardInfo({required Widget child, EdgeInsets? padding}) {
|
||||
return Container(
|
||||
width: Get.width,
|
||||
padding: padding ?? EdgeInsets.symmetric(horizontal: 12.w, vertical: 14.h),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: AppColor.blackLight),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import '../home/logic.dart';
|
||||
import 'step1_page.dart';
|
||||
import 'step2_page.dart';
|
||||
import 'step3_page.dart';
|
||||
import 'step4_page.dart';
|
||||
import 'step5_page.dart';
|
||||
|
||||
Widget addOrEditBottomSheet(PoultryFarmInspectionHomeLogic controller) {
|
||||
List<Widget> pages = [
|
||||
step1Page(controller),
|
||||
step2Page(controller),
|
||||
step3Page(controller),
|
||||
step4Page(controller),
|
||||
step5Page(controller),
|
||||
];
|
||||
|
||||
return BaseBottomSheet(
|
||||
height: Get.height,
|
||||
rootChild: Column(
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return stepper(activeStep: data.value);
|
||||
}, controller.activeStepperIndex),
|
||||
Expanded(
|
||||
child: PageView.builder(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
reverse: true,
|
||||
controller: controller.pageController,
|
||||
itemBuilder: (context, index) => pages[index],
|
||||
),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Expanded(
|
||||
child: RElevated(
|
||||
height: 40.h,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
children: [
|
||||
Icon(Icons.arrow_back_ios, color: Colors.white),
|
||||
|
||||
Text('ادامه'),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
if (controller.activeStepperIndex.value <4) {
|
||||
controller.activeStepperIndex.value++;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ROutlinedElevated(
|
||||
borderColor: AppColor.error,
|
||||
height: 40.h,
|
||||
child: Text('برگشت'),
|
||||
enabled: controller.activeStepperIndex.value > 0,
|
||||
onPressed: () {
|
||||
if (controller.activeStepperIndex.value > 0) {
|
||||
controller.activeStepperIndex.value--;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.activeStepperIndex),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class stepper extends StatelessWidget {
|
||||
const stepper({super.key, required this.activeStep});
|
||||
final int activeStep;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: SizedBox(
|
||||
height: 24,
|
||||
width: Get.width,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: activeStep >= 0
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
child: Text(
|
||||
'1',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(
|
||||
color: activeStep >= 0 ? Colors.white : AppColor.iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Divider(
|
||||
color: activeStep >= 1
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
thickness: 8,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: activeStep >= 1
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
child: Text(
|
||||
'2',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(
|
||||
color: activeStep >= 1 ? Colors.white : AppColor.iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Divider(
|
||||
color: activeStep >= 2
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
thickness: 8,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: activeStep >= 2
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
child: Text(
|
||||
'3',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(
|
||||
color: activeStep >= 2 ? Colors.white : AppColor.iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Divider(
|
||||
color: activeStep >= 3
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
thickness: 8,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: activeStep >= 3
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
child: Text(
|
||||
'4',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(
|
||||
color: activeStep >= 3 ? Colors.white : AppColor.iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Divider(
|
||||
color: activeStep >= 4
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
thickness: 8,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: activeStep >= 4
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
child: Text(
|
||||
'5',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(
|
||||
color: activeStep >= 3 ? Colors.white : AppColor.iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_farm_inspection/widgets/card_info.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import '../home/logic.dart';
|
||||
|
||||
Widget step1Page(PoultryFarmInspectionHomeLogic controller) {
|
||||
return SingleChildScrollView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 25.h),
|
||||
|
||||
Container(
|
||||
height: 610.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'اطلاعات پایه واحد',
|
||||
child: basicUnitInformation(controller),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 30.h),
|
||||
|
||||
Container(
|
||||
height: 400.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'اطلاعات جوجه ریزی',
|
||||
child: hatchingInformation(controller),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Column basicUnitInformation(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'نام واحد مرغداری',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'کد یکتا / شناسه واحد',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'نام مالک / بهرهبردار',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['مالک', 'بهرهبردار', 'مشاور', 'دیگر']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'نوع مالکیت'),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'کد ملی بهرهبردار',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'شماره تماس بهرهبردار',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'ظرفیت اسمی سالنها',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'نوع سیستم پرورش',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RElevated(
|
||||
isFullWidth: true,
|
||||
height: 40.h,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
onPressed: () {},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Icon(Icons.my_location_rounded, color: Colors.white, size: 24),
|
||||
Text('دریافت موقعیت جغرافیایی', style: AppFonts.yekan14.copyWith(color: Colors.white)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column hatchingInformation(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تاریخ جوجه ریزی',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تعداد جوجهریزی اولیه',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'منبع تهیه جوجه',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['سرابی', 'پژدر', 'روتوایلر', 'دیگر']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'نوع نژاد'),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'گرید جوجه',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'میانگین وزن جوجه در ورود',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -1,499 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_farm_inspection/widgets/card_info.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import '../home/logic.dart';
|
||||
|
||||
Widget step2Page(PoultryFarmInspectionHomeLogic controller) {
|
||||
return SingleChildScrollView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 35.h),
|
||||
|
||||
Container(
|
||||
height: 760.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'وضعیت عمومی سالن',
|
||||
child: generalConditionOfTheHall(controller),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 30.h),
|
||||
|
||||
Container(
|
||||
height: 430.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'تلفات',
|
||||
child: casualtiesInformation(controller),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
|
||||
Container(
|
||||
height: 450.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'بیماریها و وضعیت سلامت',
|
||||
child: diseasesAndHealthInformation(controller),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Column generalConditionOfTheHall(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 12),
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(0, 12, 12, 6),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
padding: EdgeInsets.all(22),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFE9E9E9),
|
||||
border: Border.all(width: 1, color: AppColor.blackLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Assets.vec.galleryAddSvg.svg(width: 36, height: 36),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Text(
|
||||
'تعداد موجود فعلی',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColorLight),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'وضعیت بهداشتی سالن',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'عالی',
|
||||
onTap: (index) => controller.setSanitaryConditionOfTheHallIndex(index),
|
||||
),
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'خوب',
|
||||
onTap: (index) => controller.setSanitaryConditionOfTheHallIndex(index),
|
||||
),
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'متوسط',
|
||||
onTap: (index) => controller.setSanitaryConditionOfTheHallIndex(index),
|
||||
),
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 3,
|
||||
label: 'ضعیف',
|
||||
onTap: (index) => controller.setSanitaryConditionOfTheHallIndex(index),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.sanitaryConditionOfTheHallIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text('وضعیت تهویه', style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2)),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setVentilationStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'خشک',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setVentilationStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'نیمهمرطوب',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setVentilationStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'مرطوب',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.ventilationStatusIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text('وضعیت بستر', style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2)),
|
||||
|
||||
ObxValue((data) {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setBeddingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'خشک',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setBeddingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'نیمهمرطوب',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setBeddingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'مرطوب',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setBeddingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'نیازمند اصلاح',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.beddingStatusIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'دمای سالن',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
maxLines: 1,
|
||||
minLines: 1,
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'کیفیت آب مصرفی',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setWaterQualityIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'چاه',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setWaterQualityIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'شهری',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setWaterQualityIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'تصفیهشده',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.waterQualityIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'کیفیت آب مصرفی',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setFuelTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'گازوییل',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setFuelTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'بنزین',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setFuelTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'گاز',
|
||||
),
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 3,
|
||||
label: 'نفت',
|
||||
onTap: (index) => controller.setFuelTypeIndex(index),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.fuelTypeIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
ChoiceChip formChips({
|
||||
required int selectedIndex,
|
||||
required int index,
|
||||
required String label,
|
||||
required Function(int) onTap,
|
||||
}) {
|
||||
return ChoiceChip(
|
||||
selectedColor: AppColor.green1Normal,
|
||||
labelStyle: index == selectedIndex
|
||||
? AppFonts.yekan14Bold.copyWith(color: Colors.white)
|
||||
: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
surfaceTintColor: Colors.white,
|
||||
checkmarkColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: index == selectedIndex
|
||||
? BorderSide.none
|
||||
: BorderSide(width: 1, color: AppColor.blackLightHover),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
label: Text(label),
|
||||
selected: index == selectedIndex,
|
||||
onSelected: (value) => onTap(index),
|
||||
);
|
||||
}
|
||||
|
||||
Column casualtiesInformation(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تعداد تلفات عادی دوره',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تلفات غیرعادی',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'منبع تهیه جوجه',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['بیماری', 'قطعی برق', 'استرس گرمایی', 'مشکلات دانه']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'علت احتمالی تلفات غیرعادی'),
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['انجام نشد', 'انجام شد']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'نمونهبرداری انجامشده'),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text('نوع نمونه', style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2)),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setSampleTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'رنده',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setSampleTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'لاشه',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setSampleTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'ترکیبی',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.sampleTypeIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column diseasesAndHealthInformation(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['بیماری', 'قطعی برق', 'استرس گرمایی', 'مشکلات دانه']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'وجود علائم بیماری در گله'),
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['انجام نشد', 'انجام شد']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'نوع بیماری تشخیص دادهشده / مشکوک'),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تاریخ واکسیناسیونهای انجامشده',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success([
|
||||
'واکسن 1',
|
||||
'واکسن 2',
|
||||
'واکسن 3',
|
||||
'واکسن 4',
|
||||
'واکسن 5',
|
||||
'واکسن 6',
|
||||
'واکسن 7',
|
||||
'واکسن 8',
|
||||
'واکسن 9',
|
||||
'واکسن 10',
|
||||
]),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'نوع واکسن'),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'شرکت تولیدکننده',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'نام مسئول فنی بهداشتی',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'نام مسئول فنی نظام مهندسی',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -1,719 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_farm_inspection/widgets/card_info.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import '../home/logic.dart';
|
||||
|
||||
Widget step3Page(PoultryFarmInspectionHomeLogic controller) {
|
||||
return SingleChildScrollView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 35.h),
|
||||
|
||||
Container(
|
||||
height: 410.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'نهاده و خوراک',
|
||||
child: agriculturalInput(controller),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 30.h),
|
||||
|
||||
Container(
|
||||
height: 650.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'زیرساخت و انرژی',
|
||||
child: infrastructureAndEnergy(controller),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
|
||||
Container(
|
||||
height: 405.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'نیروی انسانی',
|
||||
child: humanResources(controller),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
|
||||
Container(
|
||||
height: 440.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'تسهیلات و حمایتها',
|
||||
child: facilitiesAndSupport(controller),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Column agriculturalInput2(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(0, 12, 12, 6),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
padding: EdgeInsets.all(22),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFE9E9E9),
|
||||
border: Border.all(width: 1, color: AppColor.blackLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Assets.vec.galleryAddSvg.svg(width: 36, height: 36),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Text(
|
||||
'تعداد موجود فعلی',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColorLight),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'وضعیت بهداشتی سالن',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'عالی',
|
||||
onTap: (index) => controller.setSanitaryConditionOfTheHallIndex(index),
|
||||
),
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'خوب',
|
||||
onTap: (index) => controller.setSanitaryConditionOfTheHallIndex(index),
|
||||
),
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'متوسط',
|
||||
onTap: (index) => controller.setSanitaryConditionOfTheHallIndex(index),
|
||||
),
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 3,
|
||||
label: 'ضعیف',
|
||||
onTap: (index) => controller.setSanitaryConditionOfTheHallIndex(index),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.sanitaryConditionOfTheHallIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text('وضعیت تهویه', style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2)),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setVentilationStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'خشک',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setVentilationStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'نیمهمرطوب',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setVentilationStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'مرطوب',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.ventilationStatusIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text('وضعیت بستر', style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2)),
|
||||
|
||||
ObxValue((data) {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setBeddingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'خشک',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setBeddingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'نیمهمرطوب',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setBeddingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'مرطوب',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setBeddingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'نیازمند اصلاح',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.beddingStatusIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'دمای سالن',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
maxLines: 1,
|
||||
minLines: 1,
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'کیفیت آب مصرفی',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setWaterQualityIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'چاه',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setWaterQualityIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'شهری',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setWaterQualityIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'تصفیهشده',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.waterQualityIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'کیفیت آب مصرفی',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setFuelTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'گازوییل',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setFuelTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'بنزین',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setFuelTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'گاز',
|
||||
),
|
||||
formChips(
|
||||
selectedIndex: data.value,
|
||||
index: 3,
|
||||
label: 'نفت',
|
||||
onTap: (index) => controller.setFuelTypeIndex(index),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.fuelTypeIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
ChoiceChip formChips({
|
||||
required int selectedIndex,
|
||||
required int index,
|
||||
required String label,
|
||||
required Function(int) onTap,
|
||||
}) {
|
||||
return ChoiceChip(
|
||||
selectedColor: AppColor.green1Normal,
|
||||
labelStyle: index == selectedIndex
|
||||
? AppFonts.yekan14Bold.copyWith(color: Colors.white)
|
||||
: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
surfaceTintColor: Colors.white,
|
||||
checkmarkColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: index == selectedIndex
|
||||
? BorderSide.none
|
||||
: BorderSide(width: 1, color: AppColor.blackLightHover),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
label: Text(label),
|
||||
selected: index == selectedIndex,
|
||||
onSelected: (value) => onTap(index),
|
||||
);
|
||||
}
|
||||
|
||||
Column infrastructureAndEnergy(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'نوع ژنراتور',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'ظرفیت (KVA)',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'وضعیت عملکرد ژنراتور',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setGeneratorOperatingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'سالم',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setGeneratorOperatingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'نیمهسالم',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setGeneratorOperatingStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'معیوب',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.generatorOperatingStatusIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'میزان موجودی سوخت اضطراری (لیتر)',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['بیماری', 'قطعی برق', 'استرس گرمایی', 'مشکلات دانه']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'علت احتمالی تلفات غیرعادی'),
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['ندارد', 'دارد']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'سابقه قطعی برق دوره جاری'),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تعداد تلفات',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'مدت قطعی',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'توضیحات تکمیلی',
|
||||
filled: true,
|
||||
maxLines: 3,
|
||||
minLines: 3,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column agriculturalInput(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'میزان نهاده مصرفی تا روز بازدید (کیلوگرم)',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'میزان نهاده موجود در انبار',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'میزان نهاده خریداریشده و حملنشده از بازارگاه',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text('کیفیت دانه', style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2)),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setSampleTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'خوب',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setSampleTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'متوسط',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setGrainQualityInputIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'ضعیف',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.grainQualityInputIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'فرمول دانه (در صورت ارائه)',
|
||||
filled: true,
|
||||
minLines: 3,
|
||||
maxLines: 3,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column humanResources(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تعداد افراد شاغل',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تعداد افراد بومی',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تعداد افراد غیر بومی',
|
||||
filled: true,
|
||||
maxLines: 3,
|
||||
minLines: 3,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'وضعیت قرارداد کارگران',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setWorkerContractStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'دائم',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setWorkerContractStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'موقت',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setWorkerContractStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'روزمزدی',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.workerContractStatusIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['آموزش ندیده است', 'آموزش دیده است']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'آموزشدیده در حوزه بهداشت و امنیت زیستی'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column facilitiesAndSupport(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تسهیلات دریافتی فعال',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'نوع تسهیلات',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'مبلغ',
|
||||
filled: true,
|
||||
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'سال دریافت',
|
||||
filled: true,
|
||||
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['دریافت نشده', 'دریافت شده']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'وضعیت بازپرداخت'),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'درخواست جدید بهرهبردار',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setNewBeneficiaryRequestIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'نهاده',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setNewBeneficiaryRequestIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'تسهیلات',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setNewBeneficiaryRequestIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'واکسن',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setNewBeneficiaryRequestIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 3,
|
||||
label: 'تجهیزات',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.newBeneficiaryRequestIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -1,487 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_farm_inspection/widgets/card_info.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import '../home/logic.dart';
|
||||
|
||||
Widget step4Page(PoultryFarmInspectionHomeLogic controller) {
|
||||
return SingleChildScrollView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 35.h),
|
||||
|
||||
Container(
|
||||
height: 455.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'مستندات',
|
||||
child: documents(controller),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 30.h),
|
||||
|
||||
Container(
|
||||
height: 220.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'جمعبندی بازرس',
|
||||
child: inspectorConclusion(controller),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Column documents(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(0, 12, 12, 6),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
padding: EdgeInsets.all(22),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFE9E9E9),
|
||||
border: Border.all(width: 1, color: AppColor.blackLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Assets.vec.galleryAddSvg.svg(width: 36, height: 36),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Text(
|
||||
'ثبت عکس سالن (حداقل ۳ زاویه) *',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColorLight),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(0, 12, 12, 6),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
padding: EdgeInsets.all(22),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFE9E9E9),
|
||||
border: Border.all(width: 1, color: AppColor.blackLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Assets.vec.galleryAddSvg.svg(width: 36, height: 36),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Text(
|
||||
'ثبت عکس انبار نهادهها',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColorLight),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(0, 12, 12, 6),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
padding: EdgeInsets.all(22),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFE9E9E9),
|
||||
border: Border.all(width: 1, color: AppColor.blackLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Assets.vec.galleryAddSvg.svg(width: 36, height: 36),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Text('ثبت عکس تلفات', style: AppFonts.yekan14.copyWith(color: AppColor.textColorLight)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
ChoiceChip formChips({
|
||||
required int selectedIndex,
|
||||
required int index,
|
||||
required String label,
|
||||
required Function(int) onTap,
|
||||
}) {
|
||||
return ChoiceChip(
|
||||
selectedColor: AppColor.green1Normal,
|
||||
labelStyle: index == selectedIndex
|
||||
? AppFonts.yekan14Bold.copyWith(color: Colors.white)
|
||||
: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
surfaceTintColor: Colors.white,
|
||||
checkmarkColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: index == selectedIndex
|
||||
? BorderSide.none
|
||||
: BorderSide(width: 1, color: AppColor.blackLightHover),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
label: Text(label),
|
||||
selected: index == selectedIndex,
|
||||
onSelected: (value) => onTap(index),
|
||||
);
|
||||
}
|
||||
|
||||
Column inspectorConclusion(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'وضعیت کلی واحد',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setInspectorConclusionIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'تایید شده',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setInspectorConclusionIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'نیازمند اصلاح',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setInspectorConclusionIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'پرریسک',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.inspectorConclusionIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.inspectorConclusionDescriptionController,
|
||||
hintText: 'توصیهها / اخطارها / اقدامات اصلاحی ...',
|
||||
hintStyle: AppFonts.yekan14.copyWith(color: AppColor.textColorLight),
|
||||
maxLines: 3,
|
||||
minLines: 3,
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column agriculturalInput(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'میزان نهاده مصرفی تا روز بازدید (کیلوگرم)',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'میزان نهاده موجود در انبار',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'میزان نهاده خریداریشده و حملنشده از بازارگاه',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text('کیفیت دانه', style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2)),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setSampleTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'خوب',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setSampleTypeIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'متوسط',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setGrainQualityInputIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'ضعیف',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.grainQualityInputIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'فرمول دانه (در صورت ارائه)',
|
||||
filled: true,
|
||||
minLines: 3,
|
||||
maxLines: 3,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column humanResources(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تعداد افراد شاغل',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تعداد افراد بومی',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تعداد افراد غیر بومی',
|
||||
filled: true,
|
||||
maxLines: 3,
|
||||
minLines: 3,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'وضعیت قرارداد کارگران',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setWorkerContractStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'دائم',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setWorkerContractStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'موقت',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setWorkerContractStatusIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'روزمزدی',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.workerContractStatusIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['آموزش ندیده است', 'آموزش دیده است']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'آموزشدیده در حوزه بهداشت و امنیت زیستی'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column facilitiesAndSupport(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'تسهیلات دریافتی فعال',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'نوع تسهیلات',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'مبلغ',
|
||||
filled: true,
|
||||
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.nameOfThePoultryFarmUnit,
|
||||
label: 'سال دریافت',
|
||||
filled: true,
|
||||
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success(['دریافت نشده', 'دریافت شده']),
|
||||
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? 'وضعیت بازپرداخت'),
|
||||
),
|
||||
|
||||
cardInfo(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 9,
|
||||
children: [
|
||||
Text(
|
||||
'درخواست جدید بهرهبردار',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
formChips(
|
||||
onTap: (index) => controller.setNewBeneficiaryRequestIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 0,
|
||||
label: 'نهاده',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setNewBeneficiaryRequestIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 1,
|
||||
label: 'تسهیلات',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setNewBeneficiaryRequestIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 2,
|
||||
label: 'واکسن',
|
||||
),
|
||||
formChips(
|
||||
onTap: (index) => controller.setNewBeneficiaryRequestIndex(index),
|
||||
selectedIndex: data.value,
|
||||
index: 3,
|
||||
label: 'تجهیزات',
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.newBeneficiaryRequestIndex),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -1,598 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import '../home/logic.dart';
|
||||
|
||||
Widget step5Page(PoultryFarmInspectionHomeLogic controller) {
|
||||
return SingleChildScrollView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
child: detailsWidget(controller),
|
||||
);
|
||||
}
|
||||
|
||||
Widget detailsWidget(PoultryFarmInspectionHomeLogic controller) {
|
||||
return Column(
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 4,
|
||||
vertical: 10,
|
||||
),
|
||||
child: Text(
|
||||
'جزییات',
|
||||
style: AppFonts.yekan18Bold.copyWith(
|
||||
color: AppColor.iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Divider(color: AppColor.blackLightHover, height: 1, thickness: 1),
|
||||
ObxValue((data) {
|
||||
return tabBarWidget(
|
||||
['اطلاعات', 'پاییش سلامت', 'زیرساخت', 'مستندات'],
|
||||
controller.selectedTabIndex.value,
|
||||
(index) => controller.changeTab(index),
|
||||
);
|
||||
}, controller.selectedTabIndex),
|
||||
|
||||
ObxValue((data) {
|
||||
switch (data.value) {
|
||||
case 0:
|
||||
return infoTable();
|
||||
case 1:
|
||||
return healthTable();
|
||||
case 2:
|
||||
return infrastructureTable();
|
||||
case 3:
|
||||
return documentsTable();
|
||||
default:
|
||||
return infoTable();
|
||||
}
|
||||
}, controller.selectedTabIndex),
|
||||
],
|
||||
),
|
||||
|
||||
// Expanded در سطح بالاتر
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column infoTable() {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'مشخصات کلی',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
rTableRow(title: 'نام واحد مرغداری', value: 'لذیذ'),
|
||||
rTableRow(title: 'کد یکتا / شناسه واحد', value: '2541415'),
|
||||
rTableRow(title: 'نام مالک / بهرهبردار', value: 'مرغداری احمدی'),
|
||||
rTableRow(title: 'موجودی سوخت اضطراری', value: '200 لیتر'),
|
||||
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(
|
||||
title: 'تاریخ ثبت جوجه ریزی',
|
||||
value: '1402/09/19 (10:12)',
|
||||
),
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(
|
||||
title: 'تاریخ ثبت جوجه ریزی',
|
||||
value: '1402/09/19 (10:12)',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Row rTableRow({String? title, String? value}) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 9, vertical: 11),
|
||||
alignment: Alignment.centerRight,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight2,
|
||||
border: Border(
|
||||
bottom: BorderSide(color: AppColor.blackLightHover, width: 1),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
title ?? '',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 9, vertical: 11),
|
||||
alignment: Alignment.centerRight,
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(color: AppColor.blackLightHover, width: 1),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
value ?? '',
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget tabBarWidget(
|
||||
List<String> tabs,
|
||||
int selectedIndex,
|
||||
Function(int) onTabSelected,
|
||||
) {
|
||||
return SizedBox(
|
||||
height: 38.h,
|
||||
width: Get.width,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned(
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Row(
|
||||
children: [
|
||||
...tabs.map(
|
||||
(tab) => GestureDetector(
|
||||
onTap: () => onTabSelected(tabs.indexOf(tab)),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 11),
|
||||
decoration: BoxDecoration(
|
||||
border: tab == tabs[selectedIndex]
|
||||
? Border(
|
||||
bottom: BorderSide(
|
||||
color: AppColor.blueNormalOld,
|
||||
width: 3,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
child: Text(
|
||||
tab,
|
||||
style: AppFonts.yekan12Bold.copyWith(
|
||||
color: tab == tabs[selectedIndex]
|
||||
? AppColor.blueNormalOld
|
||||
: AppColor.mediumGrey,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Divider(
|
||||
color: AppColor.blackLightHover,
|
||||
height: 1,
|
||||
thickness: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget healthTable() {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'پاییش سلامت',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
rTableRow(title: 'نام واحد مرغداری', value: 'لذیذ'),
|
||||
rTableRow(title: 'کد یکتا / شناسه واحد', value: '2541415'),
|
||||
rTableRow(title: 'نام مالک / بهرهبردار', value: 'مرغداری احمدی'),
|
||||
rTableRow(title: 'موجودی سوخت اضطراری', value: '200 لیتر'),
|
||||
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(
|
||||
title: 'تاریخ ثبت جوجه ریزی',
|
||||
value: '1402/09/19 (10:12)',
|
||||
),
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(
|
||||
title: 'تاریخ ثبت جوجه ریزی',
|
||||
value: '1402/09/19 (10:12)',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget infrastructureTable() {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'زیرساخت',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
rTableRow(title: 'نام واحد مرغداری', value: 'لذیذ'),
|
||||
rTableRow(title: 'کد یکتا / شناسه واحد', value: '2541415'),
|
||||
rTableRow(title: 'نام مالک / بهرهبردار', value: 'مرغداری احمدی'),
|
||||
rTableRow(title: 'موجودی سوخت اضطراری', value: '200 لیتر'),
|
||||
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(
|
||||
title: 'تاریخ ثبت جوجه ریزی',
|
||||
value: '1402/09/19 (10:12)',
|
||||
),
|
||||
rTableRow(title: 'شهر/تعاونی', value: 'خرم آباد/تعاونی خرم آباد'),
|
||||
|
||||
rTableRow(title: 'شماره تلفن واحد', value: '021-12345678'),
|
||||
rTableRow(title: 'دامپزشک فارم', value: 'dd dd (05218569685)'),
|
||||
|
||||
rTableRow(title: 'سالن', value: '2'),
|
||||
rTableRow(
|
||||
title: 'تاریخ ثبت جوجه ریزی',
|
||||
value: '1402/09/19 (10:12)',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget documentsTable() {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'مستندات',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
SizedBox(height: 16),
|
||||
|
||||
Container(
|
||||
height: 135.h,
|
||||
width: Get.width,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 100.h,
|
||||
width: Get.width,
|
||||
child: ListView.separated(
|
||||
itemCount: 10,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
width: 80.w,
|
||||
height: 80.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x33000000),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: NetworkImage(
|
||||
"https://picsum.photos/150/150?random=$index",
|
||||
),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned(
|
||||
top: 6,
|
||||
left: 6,
|
||||
child: Container(
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.80),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Assets.vec.trashSvg.svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColor.redNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => SizedBox(width: 10),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'200 فارم در این سالن تخمین زده شده است.',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14Bold.copyWith(
|
||||
color: AppColor.textColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 16),
|
||||
|
||||
Container(
|
||||
height: 135.h,
|
||||
width: Get.width,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 100.h,
|
||||
width: Get.width,
|
||||
child: ListView.separated(
|
||||
itemCount: 10,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
width: 80.w,
|
||||
height: 80.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x33000000),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: NetworkImage(
|
||||
"https://picsum.photos/150/150?random=${index * 2 + 1}",
|
||||
),
|
||||
),
|
||||
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned(
|
||||
top: 6,
|
||||
left: 6,
|
||||
child: Container(
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.80),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Assets.vec.trashSvg.svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColor.redNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => SizedBox(width: 10),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'انبار نهاده ها',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14Bold.copyWith(
|
||||
color: AppColor.textColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 16),
|
||||
|
||||
Container(
|
||||
height: 135.h,
|
||||
width: Get.width,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 100.h,
|
||||
width: Get.width,
|
||||
child: ListView.separated(
|
||||
itemCount: 10,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
width: 80.w,
|
||||
height: 80.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x33000000),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: NetworkImage(
|
||||
"https://picsum.photos/150/150?random=${index * 3 + 1}",
|
||||
),
|
||||
),
|
||||
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned(
|
||||
top: 6,
|
||||
left: 6,
|
||||
child: Container(
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.80),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Assets.vec.trashSvg.svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColor.redNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => SizedBox(width: 10),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'تلفات',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14Bold.copyWith(
|
||||
color: AppColor.textColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import 'package:rasadyar_chicken/data/models/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingLogic extends GetxController {
|
||||
PoultryScienceRootLogic rootLogic = Get.find<PoultryScienceRootLogic>();
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
Rx<Resource<PaginationModel<HatchingModel>>> activeHatchingList =
|
||||
Resource<PaginationModel<HatchingModel>>.loading().obs;
|
||||
|
||||
final RxBool isLoadingMoreList = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
List<String> routesName = ['اقدام', 'جوجه ریزی فعال'];
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getHatchingList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
|
||||
Future<void> getHatchingList([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreList.value = true;
|
||||
} else {
|
||||
activeHatchingList.value = Resource<PaginationModel<HatchingModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getHatchingPoultry(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'hatching'},
|
||||
role: 'PoultryScience',
|
||||
pageSize: 50,
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
activeHatchingList.value = Resource<PaginationModel<HatchingModel>>.empty();
|
||||
} else {
|
||||
activeHatchingList.value = Resource<PaginationModel<HatchingModel>>.success(
|
||||
PaginationModel<HatchingModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [...(activeHatchingList.value.data?.results ?? []), ...(res?.results ?? [])],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await getHatchingList();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
|
||||
const ActiveHatchingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasSearch: true,
|
||||
hasFilter: false,
|
||||
backId: poultryFirstKey,
|
||||
routes: controller.routesName,
|
||||
onSearchChanged: (data) {
|
||||
controller.searchedValue.value = data;
|
||||
controller.getHatchingList();
|
||||
},
|
||||
child: hatchingWidget(),
|
||||
/*widgets: [
|
||||
hatchingWidget()
|
||||
],*/
|
||||
);
|
||||
}
|
||||
|
||||
Widget hatchingWidget() {
|
||||
return ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
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.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.activeFramSvg.path,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getHatchingList(true),
|
||||
|
||||
);
|
||||
}, controller.activeHatchingList);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(HatchingModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
item.violation == true ? 'پیگیری' : 'عادی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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: [
|
||||
Text(
|
||||
'نژاد:${item.breed?.first.breed ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
' سن${item.age} (روز)',
|
||||
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:${item.period}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(title: 'شماره مجوز جوجه ریزی', value: item.licenceNumber ?? 'N/A'),
|
||||
buildUnitRow(
|
||||
title: 'حجم جوجه ریزی',
|
||||
value: item.quantity.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده در سالن',
|
||||
value: item.leftOver.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(title: 'تلفات', value: item.losses.separatedByCommaFa, unit: '(قطعه)'),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value: '${item.vetFarm?.vetFarmFullName}(${item.vetFarm?.vetFarmMobile})',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: item.reportInfo?.image == false ? 'ارسال تصویر جوجه ریزی فارم ' : 'تکمیل شده',
|
||||
titleStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false) ? AppColor.greenNormal : AppColor.redDark,
|
||||
),
|
||||
valueStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false) ? AppColor.greenNormal : AppColor.redDark,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(HatchingModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.licenceNumber ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/poultry_farm/poultry_farm.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class FarmLogic extends GetxController {
|
||||
List<String> routes = ['اقدام', 'فارم ها'];
|
||||
PoultryScienceRootLogic rootLogic = Get.find<PoultryScienceRootLogic>();
|
||||
BasePageLogic baseLogic = Get.find<BasePageLogic>();
|
||||
final PoultryScienceHomeLogic _homeLogic = Get.find<PoultryScienceHomeLogic>();
|
||||
RxList<InformationTagData> tagInfo = <InformationTagData>[
|
||||
InformationTagData(
|
||||
labelTitle: 'کل فارم ها',
|
||||
isLoading: true,
|
||||
labelVecIcon: Assets.vec.cubeScanSvg.path,
|
||||
iconColor: AppColor.blueNormalOld,
|
||||
valueBgColor: Colors.white,
|
||||
labelGradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [AppColor.blueLight, Colors.white],
|
||||
),
|
||||
),
|
||||
InformationTagData(
|
||||
labelTitle: 'حجم جوجه ریزی',
|
||||
unit: 'قطعه',
|
||||
isLoading: true,
|
||||
labelVecIcon: Assets.vec.cubeCardSvg.path,
|
||||
blendMode: BlendMode.dst,
|
||||
valueBgColor: Colors.white,
|
||||
labelGradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [AppColor.greenLightHover, Colors.white],
|
||||
),
|
||||
),
|
||||
].obs;
|
||||
Rx<Resource<PaginationModel<PoultryFarm>>> farmList =
|
||||
Resource<PaginationModel<PoultryFarm>>.loading().obs;
|
||||
|
||||
RxInt currentPage = 1.obs;
|
||||
final RxBool isLoadingMoreList = false.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
tagInfo[0] = tagInfo[0].copyWith(
|
||||
isLoading: false,
|
||||
value: _homeLogic.tagInfo['first']!.first.value,
|
||||
);
|
||||
tagInfo[1] = tagInfo[1].copyWith(
|
||||
isLoading: false,
|
||||
value: _homeLogic.tagInfo['second']!.first.value,
|
||||
);
|
||||
|
||||
getFarmList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getFarmList([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreList.value = true;
|
||||
} else {
|
||||
farmList.value = Resource<PaginationModel<PoultryFarm>>.loading();
|
||||
}
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getPoultryScienceFarmList(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'farm'},
|
||||
role: 'PoultryScience',
|
||||
pageSize: 50,
|
||||
search: 'filter',
|
||||
value: '',
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
farmList.value = Resource<PaginationModel<PoultryFarm>>.empty();
|
||||
} else {
|
||||
farmList.value = Resource<PaginationModel<PoultryFarm>>.success(
|
||||
PaginationModel<PoultryFarm>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [...(farmList.value.data?.results ?? []), ...?res?.results],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
farmList.value = Resource<PaginationModel<PoultryFarm>>.loading();
|
||||
await getFarmList();
|
||||
}
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/poultry_farm/poultry_farm.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.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 FarmPage extends GetView<FarmLogic> {
|
||||
const FarmPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasFilter: false,
|
||||
hasSearch: true,
|
||||
onRefresh: controller.onRefresh,
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
filterBottomSheet(),
|
||||
);
|
||||
},
|
||||
onSearchChanged: (data) {
|
||||
controller.searchedValue.value = data;
|
||||
controller.getFarmList();
|
||||
},
|
||||
routes: controller.routes,
|
||||
backId: poultryFirstKey,
|
||||
child: Column(children: [firstTagInformation(), farmListWidget()]),
|
||||
);
|
||||
}
|
||||
|
||||
Widget firstTagInformation() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 13),
|
||||
child: ObxValue((data) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.w),
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: List.generate(
|
||||
data.length,
|
||||
(index) => Expanded(child: InformationTag(data: data[index])),
|
||||
),
|
||||
),
|
||||
);
|
||||
}, controller.tagInfo),
|
||||
);
|
||||
}
|
||||
|
||||
Widget farmListWidget() {
|
||||
return Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
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.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.cubeScanSvg.path,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getFarmList(true),
|
||||
|
||||
);
|
||||
}, controller.farmList),
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(PoultryFarm item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.unitName ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
'${item.address?.province?.name} / ${item.address?.city?.name}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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: [
|
||||
Text(
|
||||
'تعاونی : ${item.cityOperator ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
' تعداد سالن : ${item.numberOfHalls}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(title: 'مالک/ تلفن', value: '${item.user?.fullname} (${item.user?.mobile})'),
|
||||
buildRow(title: 'شناسه یکتا', value: item.breedingUniqueId ?? 'N/A'),
|
||||
buildRow(title: 'کد اپیدمیولوژیک', value: item.epidemiologicalCode ?? 'N/A'),
|
||||
buildRow(title: 'کد بهداشتی', value: item.healthCertificateNumber ?? 'N/A'),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value: '${item.vetFarm?.fullName} (${item.vetFarm?.mobile ?? '-'})',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'ظرفیت فارم',
|
||||
value: item.totalCapacity.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildRow(
|
||||
title: 'جوجه ریزی فعال (تعداد دوره) ',
|
||||
value:
|
||||
'${(item.hatchingInfo?.activeHatching ?? false) ? 'دارد' : 'ندارد'} (${item.hatchingInfo?.period ?? 0})',
|
||||
),
|
||||
|
||||
/* buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: item.reportInfo?.image == false ? 'ارسال تصویر جوجه ریزی فارم ' : 'تکمیل شده',
|
||||
titleStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false) ? AppColor.greenNormal : AppColor.redDark,
|
||||
),
|
||||
valueStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false) ? AppColor.greenNormal : AppColor.redDark,
|
||||
),
|
||||
),*/
|
||||
/* Visibility(
|
||||
visible: (item.reportInfo?.image == false),
|
||||
child: RElevated(
|
||||
text: 'ثبت بازرسی',
|
||||
isFullWidth: true,
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
cameraBottomSheet(item.id!);
|
||||
},
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
),
|
||||
),*/
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(PoultryFarm item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.unitName ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'شناسه یکتا: ${item.breedingUniqueId}',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
'${item.address?.province?.name}/${item.address?.city?.name}',
|
||||
textAlign: TextAlign.left,
|
||||
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() => filterBottomSheetWidget(
|
||||
fromDate: controller.fromDateFilter,
|
||||
onChangedFromDate: (jalali) => controller.fromDateFilter.value = jalali,
|
||||
toDate: controller.toDateFilter,
|
||||
onChangedToDate: (jalali) => controller.toDateFilter.value = jalali,
|
||||
onSubmit: () => controller.getFarmList(),
|
||||
);
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
import 'package:rasadyar_chicken/data/models/response/poultry_order/poultry_order.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/killing_registration/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class GenocideLogic extends GetxController {
|
||||
List<String> routesName = ['اقدام', 'درخواست کشتارها'];
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
var gService = Get.find<GService>();
|
||||
var rootLogic = Get.find<PoultryScienceRootLogic>();
|
||||
var killRegistration = Get.find<KillingRegistrationLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<PoultryOrder>>> poultryOrderList =
|
||||
Resource<PaginationModel<PoultryOrder>>.loading().obs;
|
||||
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
final RxInt currentPage = 1.obs;
|
||||
|
||||
final RxBool isLoadingMore = false.obs;
|
||||
|
||||
final RxBool isLoadingDelete = false.obs;
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
/* final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
final RxBool isOnLoadingSubmitOrEdit = false.obs;*/
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getPoultryOrderList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getPoultryOrderList([bool loadingMore = false]) async {
|
||||
if (loadingMore) {
|
||||
isLoadingMore.value = true;
|
||||
} else {
|
||||
poultryOrderList.value = Resource<PaginationModel<PoultryOrder>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getPoultryOderList(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
pageSize: 20,
|
||||
page: currentPage.value,
|
||||
search: 'filter',
|
||||
role: gService.getRole(Module.chicken),
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
queryParams: {'today': null},
|
||||
),
|
||||
),
|
||||
onSuccess: (res) async {
|
||||
await Future.delayed(Duration(milliseconds: 500));
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
poultryOrderList.value = Resource<PaginationModel<PoultryOrder>>.empty();
|
||||
} else {
|
||||
if (loadingMore) {
|
||||
poultryOrderList.value = Resource<PaginationModel<PoultryOrder>>.success(
|
||||
PaginationModel<PoultryOrder>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [...(poultryOrderList.value.data?.results ?? []), ...(res?.results ?? [])],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
|
||||
poultryOrderList.value = Resource<PaginationModel<PoultryOrder>>.success(res!);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deletePoultryOrder(int id) async {
|
||||
toggleExpanded(-1);
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.deletePoultryOder(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
orderId: id.toString(),
|
||||
),
|
||||
onSuccess: (_) {
|
||||
defaultShowSuccessMessage('درخواست با موفقیت حذف شد');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
String getRequestType(PoultryOrder item) {
|
||||
if (item.market ?? false) {
|
||||
return 'پنل معاملات';
|
||||
} else if (item.union ?? false) {
|
||||
return 'اتحادیه';
|
||||
} else {
|
||||
return 'خرید مستقیم';
|
||||
}
|
||||
}
|
||||
|
||||
String getKillType(PoultryOrder item) {
|
||||
if (item.export ?? false) {
|
||||
return 'صادرات';
|
||||
} else if (item.freezing ?? false) {
|
||||
return 'انجماد';
|
||||
} else {
|
||||
return 'عادی';
|
||||
}
|
||||
}
|
||||
|
||||
String getState(PoultryOrder item) {
|
||||
if (item.stateProcess == 'pending') {
|
||||
return 'در انتظار تایید';
|
||||
} else {
|
||||
return 'تایید شده';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await getPoultryOrderList();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,296 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/poultry_order/poultry_order.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/killing_registration/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.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 GenocidePage extends GetView<GenocideLogic> {
|
||||
const GenocidePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
hasSearch: true,
|
||||
hasFilter: true,
|
||||
onRefresh: controller.onRefresh,
|
||||
onSearchChanged: (data) {
|
||||
controller.searchedValue.value = data;
|
||||
controller.getPoultryOrderList();
|
||||
},
|
||||
backId: poultryFirstKey,
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
filterBottomSheet(),
|
||||
);
|
||||
},
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned.fill(child: poultryOrderListWidget()),
|
||||
Positioned(
|
||||
bottom: 130,
|
||||
right: 16,
|
||||
child: RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
killRegistrationBottomSheet(),
|
||||
).whenComplete(() {
|
||||
controller.killRegistration.clearAllFields();
|
||||
controller.killRegistration.onReady();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
//region List and Items
|
||||
Widget poultryOrderListWidget() {
|
||||
return ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
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.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.timerSvg.path,
|
||||
labelIconColor: AppColor.yellowNormal2,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getPoultryOrderList(true),
|
||||
|
||||
);
|
||||
}, controller.poultryOrderList);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(PoultryOrder item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
'${item.poultry?.address?.province?.name} / ${item.poultry?.address?.city?.name}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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: [
|
||||
Text(
|
||||
'سن مرغ:${item.hatching?.age ?? '-'} (روز)',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
item.sendDate?.formattedJalaliDate ?? '-',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'تعداد:${item.quantity.separatedByComma} (قطعه)',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(title: 'کد سفارش', value: '${item.orderCode} '),
|
||||
buildRow(
|
||||
title: 'نوع فروش',
|
||||
value: (item.freeSaleInProvince ?? false) ? 'آزاد' : 'دولتی ',
|
||||
),
|
||||
buildRow(title: 'نوع کشتار ', value: controller.getKillType(item)),
|
||||
buildRow(title: 'درخواست', value: controller.getRequestType(item)),
|
||||
|
||||
buildRow(title: 'میانگین وزنی', value: '${(item.indexWeight)} (کیلوگرم)'),
|
||||
buildRow(title: 'قیمت مرغدار', value: '${item.amount.separatedByComma} (ریال)'),
|
||||
buildRow(
|
||||
title: 'مانده در سالن ',
|
||||
value: '${item.hatching?.leftOver.separatedByComma ?? 0} (قطعه)',
|
||||
),
|
||||
buildRow(title: ' وضعیت', value: controller.getState(item)),
|
||||
|
||||
Visibility(
|
||||
visible: item.stateProcess == 'pending',
|
||||
child: ObxValue((data) {
|
||||
return ROutlinedElevatedIcon(
|
||||
height: 40.h,
|
||||
width: Get.width,
|
||||
text: 'حذف',
|
||||
icon: Assets.vec.trashSvg.svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.error, BlendMode.srcIn),
|
||||
),
|
||||
textStyle: AppFonts.yekan16Bold.copyWith(color: AppColor.error),
|
||||
borderColor: AppColor.error,
|
||||
foregroundColor: AppColor.error,
|
||||
pressedBackgroundColor: AppColor.error,
|
||||
onPressed: data.value
|
||||
? null
|
||||
: () => _buildDeleteDialog(
|
||||
onConfirm: () async {
|
||||
Get.back();
|
||||
await controller.deletePoultryOrder(item.id!);
|
||||
controller.getPoultryOrderList();
|
||||
},
|
||||
),
|
||||
);
|
||||
}, controller.isLoadingDelete),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(PoultryOrder item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.sendDate?.formattedJalaliDate ?? '-',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'کد سفارش : ${item.orderCode ?? '-'}',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
|
||||
Text(
|
||||
'تعداد:${item.quantity.separatedByComma} (قطعه)',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
//region other widgets
|
||||
void _buildDeleteDialog({required VoidCallback onConfirm}) {
|
||||
Get.defaultDialog(
|
||||
title: 'حذف درخواست کشتار',
|
||||
middleText: 'آیا از حذف این درخواست کشتار مطمئن هستید؟',
|
||||
confirm: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColor.error,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
onPressed: onConfirm,
|
||||
child: Text('بله'),
|
||||
),
|
||||
cancel: ElevatedButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Text('خیر'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() => filterBottomSheetWidget(
|
||||
fromDate: controller.fromDateFilter,
|
||||
onChangedFromDate: (jalali) => controller.fromDateFilter.value = jalali,
|
||||
toDate: controller.toDateFilter,
|
||||
onChangedToDate: (jalali) => controller.toDateFilter.value = jalali,
|
||||
onSubmit: () => controller.getPoultryOrderList(),
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region kill registration bottom sheet
|
||||
Widget killRegistrationBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: Get.height * 0.9,
|
||||
bgColor: Color(0x66E4E4E4),
|
||||
child: KillingRegistrationPage(),
|
||||
);
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_core/presentation/widget/custom/information_card_widget.dart';
|
||||
|
||||
class PoultryScienceHomeLogic extends GetxController {
|
||||
PoultryScienceRootLogic rootLogic = Get.find<PoultryScienceRootLogic>();
|
||||
Rxn<HomePoultryScienceModel> homeInformation = Rxn();
|
||||
RxBool isExpanded = false.obs;
|
||||
RxMap<String, List<InformationTagData>> tagInfo = RxMap({
|
||||
'first': [
|
||||
InformationTagData(
|
||||
labelTitle: 'کل فارم ها',
|
||||
isLoading: true,
|
||||
labelVecIcon: Assets.vec.cubeScanSvg.path,
|
||||
iconColor: AppColor.blueFlashing,
|
||||
blendMode: BlendMode.srcOut,
|
||||
valueBgColor: Colors.white,
|
||||
labelGradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [AppColor.blueLight, Colors.white],
|
||||
),
|
||||
),
|
||||
InformationTagData(
|
||||
labelTitle: 'تعداد جوجه ریزی',
|
||||
isLoading: true,
|
||||
labelVecIcon: Assets.vec.cubeCardSvg.path,
|
||||
blendMode: BlendMode.dst,
|
||||
valueBgColor: Colors.white,
|
||||
labelGradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [AppColor.greenLightHover, Colors.white],
|
||||
),
|
||||
),
|
||||
],
|
||||
'second': [
|
||||
InformationTagData(
|
||||
labelTitle: 'حجم جوجه ریزی',
|
||||
unit: 'قطعه',
|
||||
isLoading: true,
|
||||
labelVecIcon: Assets.vec.hashtagSvg.path,
|
||||
iconColor: const Color(0xFF6C5D60),
|
||||
labelBgColor: const Color(0xFFDDC0C7),
|
||||
valueBgColor: const Color(0xFFEDDCE0),
|
||||
),
|
||||
InformationTagData(
|
||||
labelTitle: 'مانده در سالن',
|
||||
unit: 'قطعه',
|
||||
isLoading: true,
|
||||
labelVecIcon: Assets.vec.homeHashtagSvg.path,
|
||||
labelBgColor: const Color(0xFFAFCBFF),
|
||||
valueBgColor: const Color(0xFFCEDFFF),
|
||||
),
|
||||
],
|
||||
'third': [
|
||||
InformationTagData(
|
||||
labelTitle: 'تلفات',
|
||||
unit: 'قطعه',
|
||||
isLoading: true,
|
||||
labelVecIcon: Assets.vec.boxRemoveSvg.path,
|
||||
|
||||
iconColor: const Color(0xFF426060),
|
||||
labelBgColor: const Color(0xFFA5D1D2),
|
||||
valueBgColor: const Color(0xFFC7DFE0),
|
||||
),
|
||||
InformationTagData(
|
||||
labelTitle: 'حجم کشتار شده',
|
||||
unit: 'قطعه',
|
||||
isLoading: true,
|
||||
labelVecIcon: Assets.vec.closeSquareFilledSvg.path,
|
||||
blendMode: BlendMode.dst,
|
||||
labelBgColor: Color(0xFFC8B8D1),
|
||||
valueBgColor: Color(0xFFDAD4DD),
|
||||
),
|
||||
],
|
||||
});
|
||||
|
||||
RxList<InformationCardData> ageCardData = [
|
||||
InformationCardData(
|
||||
labelTitle: 'بیشترین سن جوجه ریزی',
|
||||
isLoading: true,
|
||||
unit: 'روز',
|
||||
labelVecIcon: Assets.vec.homeTrendUpSvg.path,
|
||||
iconColor: const Color.fromRGBO(85, 97, 93, 1),
|
||||
cardBgColor: const Color(0xFFE6FAF5),
|
||||
labelBgColor: const Color(0xFFB0EFDF),
|
||||
),
|
||||
InformationCardData(
|
||||
labelTitle: 'کمترین سن جوجه ریزی',
|
||||
isLoading: true,
|
||||
unit: 'روز',
|
||||
labelVecIcon: Assets.vec.homeTrendDownSvg.path,
|
||||
iconColor: const Color(0xFF6F6164),
|
||||
cardBgColor: const Color(0xFFEDDCE0),
|
||||
labelBgColor: const Color(0xFFE0BCC5),
|
||||
),
|
||||
].obs;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getHomePoultryHatching();
|
||||
}
|
||||
|
||||
Future<void> getHomePoultryHatching() async {
|
||||
await safeCall<HomePoultryScienceModel?>(
|
||||
call: () async => await rootLogic.poultryRepository.getHomePoultry(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
type: 'home',
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
homeInformation.value = result;
|
||||
tagInfo['first'] = tagInfo['first']!.map((tag) {
|
||||
if (tag.labelTitle == 'کل فارم ها') {
|
||||
return tag.copyWith(
|
||||
value: result.farmCount?.separatedByCommaFa ?? '0',
|
||||
isLoading: false,
|
||||
);
|
||||
}
|
||||
if (tag.labelTitle == 'تعداد جوجه ریزی') {
|
||||
return tag.copyWith(
|
||||
value: result.hatchingCount?.separatedByCommaFa ?? '0',
|
||||
isLoading: false,
|
||||
);
|
||||
}
|
||||
return tag;
|
||||
}).toList();
|
||||
|
||||
// second
|
||||
tagInfo['second'] = tagInfo['second']!.map((tag) {
|
||||
switch (tag.labelTitle) {
|
||||
case 'حجم جوجه ریزی':
|
||||
return tag.copyWith(
|
||||
value: result.hatchingQuantity?.separatedByCommaFa ?? '0',
|
||||
isLoading: false,
|
||||
);
|
||||
case 'مانده در سالن':
|
||||
return tag.copyWith(
|
||||
value: result.hatchingLeftOver?.separatedByCommaFa ?? '0',
|
||||
isLoading: false,
|
||||
);
|
||||
default:
|
||||
return tag;
|
||||
}
|
||||
}).toList();
|
||||
|
||||
// third
|
||||
tagInfo['third'] = tagInfo['third']!.map((tag) {
|
||||
switch (tag.labelTitle) {
|
||||
case 'تلفات':
|
||||
return tag.copyWith(
|
||||
value: result.hatchingLosses?.separatedByCommaFa ?? '0',
|
||||
isLoading: false,
|
||||
);
|
||||
case 'حجم کشتار شده':
|
||||
return tag.copyWith(
|
||||
value: result.hatchingKilledQuantity?.separatedByCommaFa ?? '0',
|
||||
isLoading: false,
|
||||
);
|
||||
default:
|
||||
return tag;
|
||||
}
|
||||
}).toList();
|
||||
|
||||
ageCardData.value = ageCardData.map((element) {
|
||||
switch (element.labelTitle) {
|
||||
case 'کمترین سن جوجه ریزی':
|
||||
return element.copyWith(
|
||||
value: result.hatchingMinAge?.separatedByCommaFa ?? '0',
|
||||
isLoading: false,
|
||||
);
|
||||
case 'بیشترین سن جوجه ریزی':
|
||||
return element.copyWith(
|
||||
value: result.hatchingMaxAge?.separatedByCommaFa ?? '0',
|
||||
isLoading: false,
|
||||
);
|
||||
default:
|
||||
return element;
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,393 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart' hide LinearGradient;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:rasadyar_core/presentation/widget/custom/information_card_widget.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class PoultryScienceHomePage extends GetView<PoultryScienceHomeLogic> {
|
||||
const PoultryScienceHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
hasNotification: true,
|
||||
hasNews: true,
|
||||
scrollable: true,
|
||||
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 18.h),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
controller.isExpanded.value = !controller.isExpanded.value;
|
||||
},
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
margin: EdgeInsetsGeometry.all(6),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.50, color: const Color(0xFFA9A9A9)),
|
||||
),
|
||||
|
||||
child: ObxValue((data) {
|
||||
return AnimatedSize(
|
||||
duration: Duration(milliseconds: 300),
|
||||
child: data.value ? mainItemWidget() : mainItemWidgetExpanded(),
|
||||
);
|
||||
}, controller.isExpanded),
|
||||
),
|
||||
Positioned(
|
||||
top: -10,
|
||||
right: 20,
|
||||
child: Container(
|
||||
height: 32.h,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.50, color: const Color(0xFFA9A9A9)),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Assets.vec.chicken2Svg.svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueDark, BlendMode.srcIn),
|
||||
),
|
||||
Text(
|
||||
'اطلاعات فارمها',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.iconColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
widelyWidget(),
|
||||
SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Padding mainItemWidget() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [SizedBox(height: 8), firstTagInformation(), secondTagInformation()],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Padding mainItemWidgetExpanded() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 8),
|
||||
/* Row(
|
||||
spacing: 8,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 0.25, color: const Color(0xFFB0B0B0)),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
),
|
||||
child: Assets.images.liveChicken.image(
|
||||
width: 40.w,
|
||||
height: 40.h,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'فارم ها',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDarkActive),
|
||||
),
|
||||
Spacer(),
|
||||
AnimatedRotation(
|
||||
turns: 180,
|
||||
duration: Duration(milliseconds: 3000),
|
||||
child: Icon(CupertinoIcons.chevron_up, size: 18),
|
||||
),
|
||||
],
|
||||
),*/
|
||||
SizedBox(height: 8),
|
||||
firstTagInformation(),
|
||||
Row(
|
||||
children: [
|
||||
Text('اطلاعات جوجهریزی', textAlign: TextAlign.right, style: AppFonts.yekan16),
|
||||
],
|
||||
),
|
||||
secondTagInformation(),
|
||||
thirdTagInformation(),
|
||||
ageCardInformation(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget firstTagInformation() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 13),
|
||||
child: ObxValue((data) {
|
||||
List<InformationTagData>? items = data['first']!;
|
||||
return Row(
|
||||
spacing: 8,
|
||||
children: List.generate(
|
||||
items.length,
|
||||
(index) => Expanded(child: InformationTag(data: items[index])),
|
||||
),
|
||||
);
|
||||
}, controller.tagInfo),
|
||||
);
|
||||
}
|
||||
|
||||
Widget secondTagInformation() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 13),
|
||||
child: ObxValue((data) {
|
||||
List<InformationTagData>? items = data['second']!;
|
||||
return Row(
|
||||
spacing: 8,
|
||||
children: List.generate(
|
||||
items.length,
|
||||
(index) => Expanded(child: InformationTag(data: items[index])),
|
||||
),
|
||||
);
|
||||
}, controller.tagInfo),
|
||||
);
|
||||
}
|
||||
|
||||
Widget thirdTagInformation() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 13),
|
||||
child: ObxValue((data) {
|
||||
List<InformationTagData>? items = data['third']!;
|
||||
return Row(
|
||||
spacing: 8,
|
||||
children: List.generate(
|
||||
items.length,
|
||||
(index) => Expanded(child: InformationTag(data: items[index])),
|
||||
),
|
||||
);
|
||||
}, controller.tagInfo),
|
||||
);
|
||||
}
|
||||
|
||||
Widget ageCardInformation() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(30.w, 8, 30.w, 13),
|
||||
child: ObxValue((data) {
|
||||
return Row(
|
||||
spacing: 8,
|
||||
children: List.generate(
|
||||
data.length,
|
||||
(index) => Expanded(child: InformationCard(data: data[index])),
|
||||
),
|
||||
);
|
||||
}, controller.ageCardData),
|
||||
);
|
||||
}
|
||||
|
||||
//region Widely Used Widget
|
||||
Widget widelyWidget() {
|
||||
return Container(
|
||||
margin: EdgeInsetsGeometry.all(6),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.50, color: const Color(0xFFA9A9A9)),
|
||||
),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(12.w, 24.h, 12.w, 16.h),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
widelyUsed(
|
||||
title: 'بازرسی',
|
||||
iconPath: Assets.vec.cubeSearchSvg.path,
|
||||
isOnEdit: false,
|
||||
cardColor: AppColor.greenLightActive,
|
||||
labelColor: AppColor.greenNormal,
|
||||
textColor: AppColor.textColor,
|
||||
onTap: () async {
|
||||
controller.rootLogic.currentPage.value = 0;
|
||||
|
||||
Get.toNamed(ChickenRoutes.inspectionPoultryScience, id: poultryFirstKey);
|
||||
},
|
||||
),
|
||||
|
||||
widelyUsed(
|
||||
title: 'ثبت کشتار',
|
||||
iconPath: Assets.vec.noteRemoveSvg.path,
|
||||
isOnEdit: false,
|
||||
cardColor: AppColor.blueLightActive,
|
||||
labelColor: AppColor.blueNormalOld,
|
||||
textColor: AppColor.textColor,
|
||||
onTap: () async {
|
||||
controller.rootLogic.currentPage.value = 0;
|
||||
Get.toNamed(ChickenRoutes.genocidePoultryScience, id: poultryFirstKey);
|
||||
},
|
||||
),
|
||||
widelyUsed(
|
||||
title: 'فارم ها',
|
||||
iconPath: Assets.vec.cubeScanSvg.path,
|
||||
cardColor: Color(0xFFFFCFA3),
|
||||
labelColor: Color(0xFFF68D2B),
|
||||
textColor: AppColor.textColor,
|
||||
isOnEdit: false,
|
||||
onTap: () async {
|
||||
controller.rootLogic.currentPage.value = 0;
|
||||
Get.toNamed(ChickenRoutes.farmPoultryScience, id: poultryFirstKey);
|
||||
},
|
||||
),
|
||||
|
||||
widelyUsed(
|
||||
title: 'جوجهریزی فعال',
|
||||
iconPath: Assets.vec.boxTickSvg.path,
|
||||
isOnEdit: false,
|
||||
cardColor: Color(0xFFD9BEFF),
|
||||
labelColor: Color(0xFF9757FF),
|
||||
textColor: AppColor.textColor,
|
||||
onTap: () async {
|
||||
controller.rootLogic.currentPage.value = 0;
|
||||
Get.toNamed(ChickenRoutes.activeHatchingPoultryScience, id: poultryFirstKey);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: -17,
|
||||
right: 11,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.50, color: const Color(0xFFA9A9A9)),
|
||||
),
|
||||
child: Text('پر کاربردها', textAlign: TextAlign.right, style: AppFonts.yekan16),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget widelyUsed({
|
||||
required String title,
|
||||
required String iconPath,
|
||||
required VoidCallback onTap,
|
||||
required bool isOnEdit,
|
||||
Color? cardColor,
|
||||
Color? labelColor,
|
||||
Color? textColor,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: !isOnEdit ? onTap : null,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
width: 48,
|
||||
height: 48,
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: ShapeDecoration(
|
||||
color: cardColor ?? Color(0xFFBECDFF),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: ShapeDecoration(
|
||||
color: labelColor ?? 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,
|
||||
),
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: isOnEdit,
|
||||
child: Container(
|
||||
width: 48,
|
||||
height: 48,
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: ShapeDecoration(
|
||||
color: Colors.white60,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: isOnEdit,
|
||||
child: Positioned(
|
||||
top: -15,
|
||||
left: -12,
|
||||
child: SizedBox(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
child: GestureDetector(
|
||||
onTap: () {},
|
||||
behavior: HitTestBehavior.translucent,
|
||||
child: Center(
|
||||
child: Container(
|
||||
width: 16,
|
||||
height: 16,
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.white),
|
||||
alignment: Alignment.center,
|
||||
child: Icon(CupertinoIcons.minus, color: AppColor.error, size: 15),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
title,
|
||||
style: AppFonts.yekan10Bold.copyWith(color: textColor ?? AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
@@ -1,266 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/hatching_report/hatching_report.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class InspectionPoultryScienceLogic extends GetxController {
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
Rx<Resource<PaginationModel<HatchingModel>>> hatchingList =
|
||||
Resource<PaginationModel<HatchingModel>>.loading().obs;
|
||||
|
||||
Rx<Resource<PaginationModel<HatchingReport>>> hatchingReportList =
|
||||
Resource<PaginationModel<HatchingReport>>.loading().obs;
|
||||
|
||||
PoultryScienceRootLogic rootLogic = Get.find<PoultryScienceRootLogic>();
|
||||
|
||||
Rx<LatLng> currentLocation = LatLng(34.798315281272544, 48.51479142983491).obs;
|
||||
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
RxList<XFile> pickedImages = <XFile>[].obs;
|
||||
final List<MultipartFile> _multiPartPickedImages = <MultipartFile>[];
|
||||
|
||||
RxBool isOnUpload = false.obs;
|
||||
|
||||
RxDouble presentUpload = 0.0.obs;
|
||||
RxList<String> routesName = RxList();
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
|
||||
RxnString searchedValue = RxnString();
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
|
||||
routesName.value = ['اقدام'].toList();
|
||||
|
||||
ever(selectedSegmentIndex, (callback) {
|
||||
routesName.removeLast();
|
||||
routesName.add(callback == 0 ? 'بازرسی' : 'بایگانی');
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getHatchingList();
|
||||
getHatchingReport();
|
||||
|
||||
checkLocationPermission(request: true);
|
||||
|
||||
ever(pickedImages, (callback) {
|
||||
_multiPartPickedImages.clear();
|
||||
for (var element in pickedImages) {
|
||||
_multiPartPickedImages.add(
|
||||
MultipartFile.fromFileSync(element.path, filename: element.name),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getHatchingList([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
hatchingList.value = Resource<PaginationModel<HatchingModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getHatchingPoultry(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'hatching', 'report': true},
|
||||
role: 'PoultryScience',
|
||||
search: 'filter',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
pageSize: 50,
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
hatchingList.value = Resource<PaginationModel<HatchingModel>>.empty();
|
||||
} else {
|
||||
hatchingList.value = Resource<PaginationModel<HatchingModel>>.success(
|
||||
PaginationModel<HatchingModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [...(hatchingList.value.data?.results ?? []), ...(res?.results ?? [])],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getHatchingReport([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
hatchingReportList.value = Resource<PaginationModel<HatchingReport>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getHatchingPoultryReport(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
role: 'PoultryScience',
|
||||
pageSize: 50,
|
||||
search: 'filter',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
hatchingReportList.value = Resource<PaginationModel<HatchingReport>>.empty();
|
||||
} else {
|
||||
hatchingReportList.value = Resource<PaginationModel<HatchingReport>>.success(
|
||||
PaginationModel<HatchingReport>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [...(hatchingReportList.value.data?.results ?? []), ...(res?.results ?? [])],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> pickImages() async {
|
||||
determineCurrentPosition();
|
||||
var tmp = await pickCameraImage();
|
||||
if (tmp?.path != null && pickedImages.length < 7) {
|
||||
pickedImages.add(tmp!);
|
||||
}
|
||||
}
|
||||
|
||||
void removeImage(int index) {
|
||||
pickedImages.removeAt(index);
|
||||
}
|
||||
|
||||
void clearImages() {
|
||||
pickedImages.clear();
|
||||
}
|
||||
|
||||
Future<void> submitInspectionReport({required int id}) async {
|
||||
isOnUpload.value = true;
|
||||
|
||||
final tmpFiles = await Future.wait(
|
||||
pickedImages.map((element) => MultipartFile.fromFile(element.path, filename: element.name)),
|
||||
);
|
||||
|
||||
var data = FormData.fromMap({
|
||||
'file': tmpFiles,
|
||||
'hatching_id': id.toString(),
|
||||
'lat': currentLocation.value.latitude.toString(),
|
||||
'log': currentLocation.value.longitude.toString(),
|
||||
});
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.submitPoultryScienceReport(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
data: data,
|
||||
onSendProgress: (sent, total) {
|
||||
presentUpload.value = calculateUploadProgress(sent: sent, total: total);
|
||||
},
|
||||
),
|
||||
onSuccess: (res) {
|
||||
closeBottomSheet();
|
||||
clearImages();
|
||||
getHatchingList();
|
||||
getHatchingReport();
|
||||
isOnUpload.value = false;
|
||||
},
|
||||
onError: (error, stackTrace) async {
|
||||
clearImages();
|
||||
isOnUpload.value = false;
|
||||
|
||||
await Future.delayed(const Duration(seconds: 4)).then((value) => closeBottomSheet());
|
||||
},
|
||||
showError: true,
|
||||
);
|
||||
}
|
||||
|
||||
void closeBottomSheet() {
|
||||
Get.back();
|
||||
}
|
||||
|
||||
double calculateUploadProgress({required int sent, required int total}) {
|
||||
if (total != 0) {
|
||||
double progress = (sent * 100 / total) / 100;
|
||||
return progress;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
String getStatus(HatchingReport item) {
|
||||
if (item.state == 'accepted') {
|
||||
return 'تکمیل شده';
|
||||
} else if (item.state == 'rejected') {
|
||||
return 'رد شده';
|
||||
} else {
|
||||
return 'در حال بررسی';
|
||||
}
|
||||
}
|
||||
|
||||
Color getStatusColor(HatchingReport item) {
|
||||
if (item.state == 'accepted') {
|
||||
return AppColor.greenNormal;
|
||||
} else if (item.state == 'rejected') {
|
||||
return AppColor.redNormal;
|
||||
} else {
|
||||
return AppColor.yellowNormal;
|
||||
}
|
||||
}
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
dLog('Search Value: $data');
|
||||
searchedValue.value = data?.trim();
|
||||
final isReporter = selectedSegmentIndex.value == 1;
|
||||
if (isReporter) {
|
||||
getHatchingReport();
|
||||
} else {
|
||||
getHatchingList();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
|
||||
await Future.wait([getHatchingList(), getHatchingReport()]);
|
||||
}
|
||||
}
|
||||
@@ -1,699 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/hatching_report/hatching_report.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class InspectionPoultrySciencePage extends GetView<InspectionPoultryScienceLogic> {
|
||||
const InspectionPoultrySciencePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasBack: true,
|
||||
hasFilter: true,
|
||||
hasSearch: true,
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(filterBottomSheet());
|
||||
},
|
||||
onRefresh: controller.onRefresh,
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
backId: poultryFirstKey,
|
||||
routesWidget: ContainerBreadcrumb(rxRoutes: controller.routesName),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 50, child: segmentWidget()),
|
||||
ObxValue((data) {
|
||||
return data.value == 0 ? hatchingWidget() : reportWidget();
|
||||
}, controller.selectedSegmentIndex),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget hatchingWidget() {
|
||||
return Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
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.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: item.reportInfo?.image == false
|
||||
? Assets.vec.timerSvg.path
|
||||
: Assets.vec.checkSquareSvg.path,
|
||||
labelIconColor: item.reportInfo?.image == false
|
||||
? AppColor.yellowNormal2
|
||||
: AppColor.mediumGreyDarkHover,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getHatchingList(true),
|
||||
);
|
||||
}, controller.hatchingList),
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(HatchingModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
item.violation == true ? 'پیگیری' : 'عادی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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: [
|
||||
Text(
|
||||
'نژاد:${item.breed?.first.breed ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
' سن ${item.age} (روزه)',
|
||||
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:${item.period}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(title: 'شماره مجوز جوجه ریزی', value: item.licenceNumber ?? 'N/A'),
|
||||
buildUnitRow(
|
||||
title: 'حجم جوجه ریزی',
|
||||
value: item.quantity.separatedByCommaFa,
|
||||
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده در سالن',
|
||||
value: item.leftOver.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(title: 'تلفات', value: item.losses.separatedByCommaFa, unit: '(قطعه)'),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value: '${item.vetFarm?.vetFarmFullName}(${item.vetFarm?.vetFarmMobile})',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: item.reportInfo?.image == false ? 'ارسال تصویر جوجه ریزی فارم ' : 'تکمیل شده',
|
||||
titleStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false) ? AppColor.greenNormal : AppColor.redDark,
|
||||
),
|
||||
valueStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false) ? AppColor.greenNormal : AppColor.redDark,
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: (item.reportInfo?.image == false),
|
||||
child: RElevated(
|
||||
text: 'ثبت بازرسی',
|
||||
isFullWidth: true,
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
cameraBottomSheet(item.id!);
|
||||
},
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void cameraBottomSheet(int id) {
|
||||
Get.bottomSheet(
|
||||
isDismissible: false,
|
||||
isScrollControlled: false,
|
||||
BaseBottomSheet(
|
||||
height: 350.h,
|
||||
child: Column(
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
mainAxisSpacing: 8,
|
||||
crossAxisSpacing: 8,
|
||||
childAspectRatio: 1,
|
||||
),
|
||||
shrinkWrap: true,
|
||||
itemCount: controller.pickedImages.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if (index + 1 < 7 && index == data.length) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
await controller.pickImages();
|
||||
},
|
||||
child: Container(
|
||||
width: 80.h,
|
||||
height: 80.h,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.lightGreyNormal,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.add_a_photo,
|
||||
color: AppColor.lightGreyDarker,
|
||||
size: 32.h,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Container(
|
||||
width: 80.h,
|
||||
height: 80.h,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.lightGreyNormal,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Image.file(File(data[index].path), fit: BoxFit.cover),
|
||||
),
|
||||
|
||||
Positioned(
|
||||
top: 4,
|
||||
left: 4,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.removeImage(index);
|
||||
},
|
||||
child: Container(
|
||||
width: 24.w,
|
||||
height: 24.h,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: ShapeDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.80),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
),
|
||||
child: Assets.vec.trashSvg.svg(
|
||||
width: 8.w,
|
||||
height: 8.h,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColor.redNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}, controller.pickedImages),
|
||||
|
||||
SizedBox(height: 35.h),
|
||||
Text(
|
||||
'حداقل ۲ تصویر برای ثبت بازرسی لازم است',
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
Row(
|
||||
spacing: 16,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Obx(() {
|
||||
return RElevated(
|
||||
height: 40.h,
|
||||
text: 'ارسال',
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
progress: controller.presentUpload.value,
|
||||
isLoading: controller.isOnUpload.value,
|
||||
enabled: controller.pickedImages.length >= 2,
|
||||
onPressed: () async {
|
||||
controller.submitInspectionReport(id: id);
|
||||
},
|
||||
);
|
||||
}),
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
height: 40.h,
|
||||
text: 'انصراف',
|
||||
backgroundColor: AppColor.redNormal,
|
||||
enabled: !data.value,
|
||||
onPressed: () {
|
||||
if (!data.value) {
|
||||
controller.clearImages();
|
||||
Get.back();
|
||||
}
|
||||
},
|
||||
);
|
||||
}, controller.isOnUpload),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
),
|
||||
).whenComplete(() {
|
||||
controller.pickedImages.clear();
|
||||
});
|
||||
}
|
||||
|
||||
Padding segmentWidget() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RSegment(
|
||||
children: ['بازرسی', 'بایگانی'],
|
||||
selectedIndex: 0,
|
||||
borderColor: const Color(0xFFB4B4B4),
|
||||
selectedBorderColor: AppColor.blueNormal,
|
||||
selectedBackgroundColor: AppColor.blueLight,
|
||||
onSegmentSelected: (index) => controller.selectedSegmentIndex.value = index,
|
||||
backgroundColor: AppColor.whiteGreyNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget reportWidget() {
|
||||
return Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
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.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidgetReport(item),
|
||||
secondChild: itemListExpandedWidgetReport(item),
|
||||
labelColor: item.state == 'rejected' ? AppColor.redLight : AppColor.greenLight,
|
||||
labelIcon: Assets.vec.cubeSearchSvg.path,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getHatchingReport(true),
|
||||
);
|
||||
}, controller.hatchingReportList),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListExpandedWidgetReport(HatchingReport item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.hatching?.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
item.hatching?.violation == true ? 'پیگیری' : 'عادی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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('نژاد:', style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
|
||||
Text(
|
||||
item.hatching?.chickenBreed ?? 'N/A',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
' سن ${item.hatching?.chickenAge} (روزه)',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:${item.hatching?.period}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(title: 'شماره مجوز جوجه ریزی', value: item.hatching?.licenceNumber ?? 'N/A'),
|
||||
buildUnitRow(
|
||||
title: 'حجم جوجه ریزی',
|
||||
value: item.hatching?.quantity.separatedByCommaFa ?? 'N/A',
|
||||
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده در سالن',
|
||||
value: item.hatching?.leftOver.separatedByCommaFa ?? 'N/A',
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'تلفات',
|
||||
value: item.hatching?.losses.separatedByCommaFa ?? 'N/A',
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value:
|
||||
'${item.hatching?.vetFarm?.vetFarmFullName}(${item.hatching?.vetFarm?.vetFarmMobile})',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: controller.getStatus(item),
|
||||
titleStyle: AppFonts.yekan14.copyWith(color: controller.getStatusColor(item)),
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: controller.getStatusColor(item)),
|
||||
),
|
||||
|
||||
if (item.state == 'accepted') ...{
|
||||
Visibility(
|
||||
visible: item.realQuantityAi != null,
|
||||
child: buildRow(
|
||||
title: 'تعداد تاییده هوش مصنوعی',
|
||||
value: item.realQuantityAi.separatedByComma,
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: item.realQuantity != null,
|
||||
child: buildRow(
|
||||
title: 'تعداد تاییده',
|
||||
value: item.realQuantity.separatedByComma,
|
||||
),
|
||||
),
|
||||
},
|
||||
|
||||
if (item.state == 'rejected') ...{
|
||||
Visibility(
|
||||
visible: item.messageAi != null,
|
||||
child: buildRow(title: 'پیام هوش مصنوعی', value: item.messageAi ?? '-'),
|
||||
),
|
||||
Visibility(
|
||||
visible: item.message != null,
|
||||
child: buildRow(title: 'پیام', value: item.message ?? '-'),
|
||||
),
|
||||
Visibility(
|
||||
visible: item.messageRegistererFullname != null,
|
||||
child: buildRow(
|
||||
title: 'ثبت کننده گزارش',
|
||||
value: item.messageRegistererFullname ?? '-',
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: item.messageRegistererMobile != null,
|
||||
child: buildRow(
|
||||
title: 'موبایل کننده گزارش',
|
||||
value: item.messageRegistererMobile ?? '-',
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: item.messageRegistererRole != null,
|
||||
child: buildRow(title: 'نقش کننده گزارش', value: item.messageRegistererRole ?? '-'),
|
||||
),
|
||||
},
|
||||
|
||||
SizedBox(
|
||||
height: 140.h,
|
||||
child: GridView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: item.image?.length ?? 0,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 10,
|
||||
crossAxisSpacing: 10,
|
||||
),
|
||||
itemBuilder: (context, index) => Container(
|
||||
height: 100.h,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Image.network(
|
||||
item.image?[index] ?? '',
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
return Padding(
|
||||
padding: EdgeInsetsGeometry.all(80),
|
||||
|
||||
child: CircularProgressIndicator(
|
||||
color: AppColor.blueDark,
|
||||
value: loadingProgress.expectedTotalBytes != null
|
||||
? loadingProgress.cumulativeBytesLoaded /
|
||||
(loadingProgress.expectedTotalBytes ?? 1)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8.r)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(HatchingModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 5,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 5,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.licenceNumber ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidgetReport(HatchingReport item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 5,
|
||||
children: [
|
||||
Text(
|
||||
item.hatching?.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.hatching?.poultry?.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 5,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.hatching?.poultry?.unitName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.hatching?.licenceNumber ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 200,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text('فیلترها', style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
date: controller.fromDateFilter,
|
||||
onChanged: (jalali) => controller.fromDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
isFrom: false,
|
||||
date: controller.toDateFilter,
|
||||
onChanged: (jalali) => controller.toDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RElevated(
|
||||
text: 'اعمال فیلتر',
|
||||
isFullWidth: true,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
onPressed: () {
|
||||
final isReporter = controller.selectedSegmentIndex.value == 0;
|
||||
if (isReporter) {
|
||||
controller.getHatchingReport();
|
||||
} else {
|
||||
controller.getHatchingList();
|
||||
}
|
||||
Get.back();
|
||||
},
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,414 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/poultry_export/poultry_export.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/kill_registration/kill_registration.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/all_poultry/all_poultry.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/approved_price/approved_price.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/kill_house_poultry/kill_house_poultry.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/kill_request_poultry/kill_request_poultry.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/poultry_hatching/poultry_hatching.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/sell_for_freezing/sell_for_freezing.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/genocide/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class KillingRegistrationLogic extends GetxController {
|
||||
List<String> routes = ['اقدام', 'درخواست کشتارها', 'ثبت کشتار'];
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
var gService = Get.find<GService>();
|
||||
var rootLogic = Get.find<PoultryScienceRootLogic>();
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
|
||||
Rxn<ApprovedPrice> approvedPrice = Rxn<ApprovedPrice>();
|
||||
Rx<Jalali> killsDate = Jalali.now().obs;
|
||||
|
||||
Rxn<SellForFreezing> sellForFreezing = Rxn<SellForFreezing>();
|
||||
Rxn<PoultryExport> poultryExport = Rxn<PoultryExport>();
|
||||
|
||||
TextEditingController quantityKillsController = TextEditingController();
|
||||
RxBool quantityKillsIsCompleted = false.obs;
|
||||
TextEditingController quantityLoseController = TextEditingController(text: 0.toString());
|
||||
TextEditingController averageWeightKillsController = TextEditingController();
|
||||
RxBool averageWeightKillsIsCompleted = false.obs;
|
||||
TextEditingController priceFreeSaleController = TextEditingController();
|
||||
|
||||
RxInt generatedApprovedPrice = 0.obs;
|
||||
RxBool isOnSubmitLoading = false.obs;
|
||||
|
||||
RxBool isExportSelected = false.obs;
|
||||
RxBool isFreezedSelected = false.obs;
|
||||
RxBool isMarketSelected = false.obs;
|
||||
RxBool isFreeSale = false.obs;
|
||||
|
||||
//step 1
|
||||
Rx<Resource<List<AllPoultry>>> allPoultryList = Resource<List<AllPoultry>>.loading().obs;
|
||||
Rxn<AllPoultry> selectedPoultry = Rxn();
|
||||
|
||||
//step 2
|
||||
Rx<Resource<List<KillRequestPoultry>>> poultryList = Resource<List<KillRequestPoultry>>.success(
|
||||
[],
|
||||
).obs;
|
||||
Rxn<KillRequestPoultry> selectedKillRequestPoultry = Rxn();
|
||||
|
||||
//step 3
|
||||
Rx<Resource<List<PoultryHatching>>> poultryHatchingList = Resource<List<PoultryHatching>>.success(
|
||||
[],
|
||||
).obs;
|
||||
Rxn<PoultryHatching> selectedPoultryHatching = Rxn();
|
||||
|
||||
//step 5
|
||||
Rx<Resource<List<KillHousePoultry>>> killHouseList = Resource<List<KillHousePoultry>>.success(
|
||||
[],
|
||||
).obs;
|
||||
Rxn<KillHousePoultry> selectedKillHouse = Rxn();
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
|
||||
getApprovedPrice();
|
||||
|
||||
getAllPoultryList();
|
||||
|
||||
getSellForFreezing();
|
||||
|
||||
getPoultryExport();
|
||||
|
||||
priceListener();
|
||||
|
||||
ever(selectedKillRequestPoultry, (callback) {
|
||||
if (callback?.provinceAllowChooseKillHouse?.allowState ?? false) {
|
||||
getKillHouseList();
|
||||
}
|
||||
});
|
||||
|
||||
everAll(
|
||||
[selectedPoultry, selectedKillRequestPoultry, selectedPoultryHatching, selectedKillHouse],
|
||||
(callback) {
|
||||
checkSubmitButton();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
quantityKillsController.dispose();
|
||||
quantityLoseController.dispose();
|
||||
averageWeightKillsController.dispose();
|
||||
priceFreeSaleController.dispose();
|
||||
clearSelectedStep1();
|
||||
clearSelectedStep2();
|
||||
selectedKillHouse.value = null;
|
||||
killHouseList.value = Resource<List<KillHousePoultry>>.success([]);
|
||||
}
|
||||
|
||||
void priceListener() {
|
||||
quantityKillsController.addListener(() {
|
||||
quantityKillsIsCompleted.value = quantityKillsController.text.trim().isNotEmpty;
|
||||
|
||||
if (averageWeightKillsController.text.isNotEmpty &&
|
||||
quantityKillsController.text.trim().isNotEmpty) {
|
||||
generatedApprovedPrice.value = calculateApprovedPrice().toInt();
|
||||
priceFreeSaleController.text = generatedApprovedPrice.value.separatedByComma;
|
||||
|
||||
checkSubmitButton();
|
||||
} else {
|
||||
generatedApprovedPrice.value = 0;
|
||||
priceFreeSaleController.text = '0';
|
||||
checkSubmitButton();
|
||||
}
|
||||
});
|
||||
|
||||
averageWeightKillsController.addListener(() {
|
||||
averageWeightKillsIsCompleted.value = averageWeightKillsController.text.trim().isNotEmpty;
|
||||
|
||||
if (averageWeightKillsController.text.trim().isNotEmpty &&
|
||||
quantityKillsController.text.trim().isNotEmpty) {
|
||||
generatedApprovedPrice.value = calculateApprovedPrice().toInt();
|
||||
priceFreeSaleController.text = generatedApprovedPrice.value.separatedByComma;
|
||||
checkSubmitButton();
|
||||
} else {
|
||||
generatedApprovedPrice.value = 0;
|
||||
priceFreeSaleController.text = '0';
|
||||
checkSubmitButton();
|
||||
}
|
||||
});
|
||||
|
||||
priceFreeSaleController.addListener(() {
|
||||
final text = priceFreeSaleController.text;
|
||||
if (text.isNotEmpty) {
|
||||
generatedApprovedPrice.value = int.parse(text.replaceAll(',', ''));
|
||||
} else {
|
||||
generatedApprovedPrice.value = 0;
|
||||
}
|
||||
checkSubmitButton();
|
||||
});
|
||||
}
|
||||
|
||||
void clearSelectedStep1() {
|
||||
selectedPoultry.value = null;
|
||||
selectedKillRequestPoultry.value = null;
|
||||
selectedPoultryHatching.value = null;
|
||||
poultryList.value = Resource<List<KillRequestPoultry>>.success([]);
|
||||
poultryHatchingList.value = Resource<List<PoultryHatching>>.success([]);
|
||||
}
|
||||
|
||||
void clearSelectedStep2() {
|
||||
selectedKillRequestPoultry.value = null;
|
||||
selectedPoultryHatching.value = null;
|
||||
poultryHatchingList.value = Resource<List<PoultryHatching>>.success([]);
|
||||
}
|
||||
|
||||
Future<void> getApprovedPrice() async {
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getApprovedPrice(
|
||||
token: tokenService.accessToken.value ?? '',
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
approvedPrice.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getAllPoultryList() async {
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getAllPoultry(
|
||||
token: tokenService.accessToken.value ?? '',
|
||||
queryParameters: buildRawQueryParams(role: gService.getRole(Module.chicken)),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
allPoultryList.value = Resource<List<AllPoultry>>.success(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
allPoultryList.value = Resource<List<AllPoultry>>.error('$error -- $stackTrace');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getSellForFreezing() async {
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getSellForFreezing(
|
||||
token: tokenService.accessToken.value ?? '',
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
sellForFreezing.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getPoultryExport() async {
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getPoultryExport(
|
||||
token: tokenService.accessToken.value ?? '',
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
poultryExport.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getUserPoultryList() async {
|
||||
poultryList.value = Resource<List<KillRequestPoultry>>.loading();
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getUserPoultry(
|
||||
token: tokenService.accessToken.value ?? '',
|
||||
queryParameters: buildQueryParams(
|
||||
value: selectedPoultry.value?.user?.mobile,
|
||||
queryParams: {'type': 'filter'},
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
poultryList.value = Resource<List<KillRequestPoultry>>.success(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
poultryList.value = Resource<List<KillRequestPoultry>>.error('$error -- $stackTrace');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getPoultryHatchingList() async {
|
||||
poultryHatchingList.value = Resource<List<PoultryHatching>>.loading();
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getPoultryHatching(
|
||||
token: tokenService.accessToken.value ?? '',
|
||||
queryParameters: buildRawQueryParams(
|
||||
queryParams: {'key': selectedKillRequestPoultry.value?.key},
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
poultryHatchingList.value = Resource<List<PoultryHatching>>.success(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
poultryHatchingList.value = Resource<List<PoultryHatching>>.error('$error -- $stackTrace');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getKillHouseList() async {
|
||||
killHouseList.value = Resource<List<KillHousePoultry>>.loading();
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.getKillHouseList(
|
||||
token: tokenService.accessToken.value ?? '',
|
||||
queryParameters: buildRawQueryParams(
|
||||
queryParams: {'show_poultry': '', 'date': DateTime.now().formattedDashedGregorian},
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
killHouseList.value = Resource<List<KillHousePoultry>>.success(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
killHouseList.value = Resource<List<KillHousePoultry>>.error('$error -- $stackTrace');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
double calculateApprovedPrice() {
|
||||
final inputWeight = double.parse(averageWeightKillsController.text) * 1000;
|
||||
final lowestWeight = approvedPrice.value?.lowestWeight ?? 0;
|
||||
final highestWeight = approvedPrice.value?.highestWeight ?? 0;
|
||||
final lowestPrice = approvedPrice.value?.lowestPrice ?? 0;
|
||||
final highestPrice = approvedPrice.value?.highestPrice ?? 0;
|
||||
|
||||
if (inputWeight <= lowestWeight) {
|
||||
return lowestPrice;
|
||||
} else if (inputWeight >= highestWeight) {
|
||||
return highestPrice;
|
||||
} else {
|
||||
final diffWeight = highestWeight - lowestWeight;
|
||||
final diffPrice = highestPrice - lowestPrice;
|
||||
final fraction = diffPrice / diffWeight;
|
||||
final diffFromMinWeight = inputWeight - lowestWeight;
|
||||
return diffFromMinWeight * fraction + lowestPrice;
|
||||
}
|
||||
}
|
||||
|
||||
void changeSaleType() {
|
||||
isFreeSale.value = !isFreeSale.value;
|
||||
generatedApprovedPrice.value = calculateApprovedPrice().toInt();
|
||||
}
|
||||
|
||||
void checkSubmitButton() {
|
||||
isOnSubmitLoading.value =
|
||||
selectedPoultry.value != null &&
|
||||
selectedKillRequestPoultry.value != null &&
|
||||
selectedPoultryHatching.value != null &&
|
||||
quantityKillsController.text.isNotEmpty &&
|
||||
averageWeightKillsController.text.isNotEmpty &&
|
||||
((selectedKillRequestPoultry.value?.provinceAllowChooseKillHouse?.mandatory ?? false)
|
||||
? selectedKillHouse.value != null
|
||||
: true);
|
||||
}
|
||||
|
||||
Future<void> submitKillRegistration() async {
|
||||
isOnSubmitLoading.value = false;
|
||||
if (!formKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
dLog(double.parse(averageWeightKillsController.text));
|
||||
KillRegistrationRequest registrationRequest = KillRegistrationRequest(
|
||||
indexWeight: double.parse(averageWeightKillsController.text),
|
||||
amount: generatedApprovedPrice.value,
|
||||
approvedPrice: approvedPrice.value?.approved ?? false,
|
||||
auctionList: [],
|
||||
cash: true,
|
||||
chickenBreed: selectedPoultryHatching.value?.chickenBreed,
|
||||
confirmPoultryMobile: selectedPoultry.value?.user?.mobile,
|
||||
credit: false,
|
||||
export: isExportSelected.value,
|
||||
financialOperation: "outside-system",
|
||||
freeSaleInProvince: isMarketSelected.value,
|
||||
freezing: isFreezedSelected.value,
|
||||
killHouseList: [
|
||||
if (selectedKillHouse.value != null)
|
||||
'${selectedKillHouse.value?.name}(${selectedKillHouse.value?.fullname})',
|
||||
],
|
||||
killReqKey: selectedKillHouse.value?.killReqKey,
|
||||
losses: quantityLoseController.text,
|
||||
market: isMarketSelected.value,
|
||||
operatorKey: "",
|
||||
poultryHatchingKey: selectedPoultryHatching.value?.key,
|
||||
poultryKey: selectedPoultry.value?.key,
|
||||
quantity: int.parse(quantityKillsController.text.clearComma),
|
||||
role: gService.getRole(Module.chicken),
|
||||
sendDate: killsDate.value.toDateTime().formattedDashedGregorian,
|
||||
);
|
||||
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.poultryRepository.submitKillRegistration(
|
||||
token: tokenService.accessToken.value ?? '',
|
||||
request: registrationRequest,
|
||||
),
|
||||
onSuccess: (result) async {
|
||||
defaultShowSuccessMessage(
|
||||
'ثبت با موفقیت انجام شد',
|
||||
durationInSeconds: 2,
|
||||
onDismissed: () async {
|
||||
Get.find<GenocideLogic>().getPoultryOrderList();
|
||||
Future.delayed(Duration(milliseconds: 300), () {
|
||||
Get.back();
|
||||
});
|
||||
Get.find<GenocideLogic>().getPoultryOrderList();
|
||||
},
|
||||
);
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void clearAllFields() {
|
||||
// ریست فرم
|
||||
formKey.currentState?.reset();
|
||||
|
||||
// ریست Rxn ها
|
||||
approvedPrice.value = null;
|
||||
sellForFreezing.value = null;
|
||||
poultryExport.value = null;
|
||||
selectedPoultry.value = null;
|
||||
selectedKillRequestPoultry.value = null;
|
||||
selectedPoultryHatching.value = null;
|
||||
selectedKillHouse.value = null;
|
||||
|
||||
// ریست Rx ها
|
||||
killsDate.value = Jalali.now();
|
||||
generatedApprovedPrice.value = 0;
|
||||
isOnSubmitLoading.value = false;
|
||||
isExportSelected.value = false;
|
||||
isFreezedSelected.value = false;
|
||||
isMarketSelected.value = false;
|
||||
isFreeSale.value = false;
|
||||
|
||||
// ریست TextEditingController ها
|
||||
quantityKillsController.clear();
|
||||
quantityLoseController.text = '0';
|
||||
averageWeightKillsController.clear();
|
||||
priceFreeSaleController.clear();
|
||||
|
||||
// ریست RxBool ها
|
||||
quantityKillsIsCompleted.value = false;
|
||||
averageWeightKillsIsCompleted.value = false;
|
||||
|
||||
// ریست Resource لیستها
|
||||
allPoultryList.value = Resource<List<AllPoultry>>.loading();
|
||||
poultryList.value = Resource<List<KillRequestPoultry>>.success([]);
|
||||
poultryHatchingList.value = Resource<List<PoultryHatching>>.success([]);
|
||||
killHouseList.value = Resource<List<KillHousePoultry>>.success([]);
|
||||
}
|
||||
}
|
||||
@@ -1,587 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/all_poultry/all_poultry.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/kill_house_poultry/kill_house_poultry.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/kill_request_poultry/kill_request_poultry.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/poultry_hatching/poultry_hatching.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class KillingRegistrationPage extends GetView<KillingRegistrationLogic> {
|
||||
const KillingRegistrationPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
poultryFarmWidget(),
|
||||
poultryUserListWidget(),
|
||||
poultryHatchingWidget(),
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: controller.selectedPoultryHatching.value != null,
|
||||
child: Column(
|
||||
children: [
|
||||
informationWidget(),
|
||||
killDateWidget(
|
||||
date: controller.killsDate,
|
||||
onChanged: (Jalali jalali) {
|
||||
controller.killsDate.value = jalali;
|
||||
},
|
||||
),
|
||||
quantityKillsWidget(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.selectedPoultryHatching),
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: data.value,
|
||||
child: Column(children: [averageWeightKillsWidget()]),
|
||||
);
|
||||
}, controller.quantityKillsIsCompleted),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: data.value,
|
||||
child: Column(
|
||||
children: [
|
||||
saleTypeWidget(),
|
||||
priceWidget(),
|
||||
buyerListWidget(),
|
||||
slaughterhouseSelectedWidget(),
|
||||
submitButtonWidget(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.averageWeightKillsIsCompleted),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget poultryFarmWidget() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 10.h),
|
||||
child: ObxValue((data) {
|
||||
return ResourceOverlayDropdown<AllPoultry>(
|
||||
items: data.value,
|
||||
background: Colors.white,
|
||||
onChanged: (value) {
|
||||
controller.clearSelectedStep1();
|
||||
controller.selectedPoultry.value = value;
|
||||
controller.getUserPoultryList();
|
||||
},
|
||||
selectedItem: controller.selectedPoultry.value,
|
||||
itemBuilder: (item) => labelPoultryWidget(item),
|
||||
labelBuilder: (item) => labelPoultryWidget(item),
|
||||
);
|
||||
}, controller.allPoultryList),
|
||||
);
|
||||
}
|
||||
|
||||
Widget labelPoultryWidget(AllPoultry? item) {
|
||||
if (item == null) {
|
||||
return Row(
|
||||
children: [
|
||||
Assets.vec.farmSvg.svg(
|
||||
width: 28.w,
|
||||
height: 28.h,
|
||||
colorFilter: const ColorFilter.mode(AppColor.darkGreyDark, BlendMode.srcIn),
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
Text('انتخاب مرغداری', style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDark)),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Text('${item.unitName} (${item.address?.city?.name})', maxLines: 2);
|
||||
}
|
||||
}
|
||||
|
||||
Widget poultryUserListWidget() {
|
||||
return ObxValue((data) {
|
||||
if (data.value == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w),
|
||||
child: ObxValue((data) {
|
||||
return ResourceOverlayDropdown<KillRequestPoultry>(
|
||||
items: data.value,
|
||||
background: Colors.white,
|
||||
onChanged: (value) {
|
||||
controller.clearSelectedStep2();
|
||||
controller.selectedKillRequestPoultry.value = value;
|
||||
controller.getPoultryHatchingList();
|
||||
},
|
||||
selectedItem: controller.selectedKillRequestPoultry.value,
|
||||
itemBuilder: (item) => labelPoultryUser(item),
|
||||
labelBuilder: (item) => labelPoultryUser(item),
|
||||
);
|
||||
}, controller.poultryList),
|
||||
);
|
||||
}, controller.selectedPoultry);
|
||||
}
|
||||
|
||||
Widget labelPoultryUser(KillRequestPoultry? item) {
|
||||
if (item == null) {
|
||||
return Row(
|
||||
children: [
|
||||
Assets.vec.chickenHouseSvg.svg(
|
||||
width: 28.w,
|
||||
height: 28.h,
|
||||
colorFilter: const ColorFilter.mode(AppColor.darkGreyDark, BlendMode.srcIn),
|
||||
),
|
||||
SizedBox(width: 6.w),
|
||||
Text('محل پرورش', style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDark)),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Text(item.unitName ?? '-');
|
||||
}
|
||||
}
|
||||
|
||||
Widget poultryHatchingWidget() {
|
||||
return ObxValue((data) {
|
||||
if (data.value == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 10.h),
|
||||
child: ObxValue((data) {
|
||||
return ResourceOverlayDropdown<PoultryHatching>(
|
||||
items: data.value,
|
||||
background: Colors.white,
|
||||
onChanged: (value) {
|
||||
controller.selectedPoultryHatching.value = value;
|
||||
},
|
||||
selectedItem: controller.selectedPoultryHatching.value,
|
||||
itemBuilder: (item) => labelPoultryHatching(item),
|
||||
labelBuilder: (item) => labelPoultryHatching(item),
|
||||
);
|
||||
}, controller.poultryHatchingList),
|
||||
);
|
||||
}, controller.selectedKillRequestPoultry);
|
||||
}
|
||||
|
||||
Widget labelPoultryHatching(PoultryHatching? item) {
|
||||
if (item == null) {
|
||||
return Row(
|
||||
children: [
|
||||
Assets.vec.calendarSvg.svg(
|
||||
width: 28.w,
|
||||
height: 28.h,
|
||||
colorFilter: const ColorFilter.mode(AppColor.darkGreyDark, BlendMode.srcIn),
|
||||
),
|
||||
SizedBox(width: 6.w),
|
||||
Text('دوره جوجه ریزی', style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDark)),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Text(
|
||||
' دوره ${item.period} سالن ${item.hall} نژاد ${item.chickenBreed} باقیمانده ${item.leftOver} قطعه ',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget informationWidget() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
margin: EdgeInsets.fromLTRB(8.w, 0, 8.w, 10.h),
|
||||
padding: EdgeInsets.all(7),
|
||||
child: ObxValue(
|
||||
(data) => Column(
|
||||
spacing: 8,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Text(
|
||||
'اطلاعات مرغداری',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: const Color(0xFFEAEFFF),
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: const Color(0xFFE0E7FF)),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
padding: EdgeInsets.all(4),
|
||||
child: buildUnitRow(
|
||||
title: 'تعداد جوجه ریزی',
|
||||
value: data.value?.quantity.separatedByCommaFa,
|
||||
unit: 'قطعه',
|
||||
),
|
||||
),
|
||||
|
||||
buildUnitRow(
|
||||
title: 'تلفات',
|
||||
value: data.value?.losses.separatedByCommaFa,
|
||||
unit: 'قطعه',
|
||||
padding: EdgeInsetsGeometry.symmetric(horizontal: 4),
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'باقیمانده',
|
||||
value: data.value?.leftOver.separatedByCommaFa,
|
||||
unit: 'قطعه',
|
||||
padding: EdgeInsetsGeometry.symmetric(horizontal: 4),
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'سن جوجه',
|
||||
value: data.value?.chickenAge.separatedByCommaFa,
|
||||
unit: 'روز',
|
||||
padding: EdgeInsetsGeometry.symmetric(horizontal: 4),
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مجوز فروش آزاد',
|
||||
value:
|
||||
data.value?.freeGovernmentalInfo?.totalFreeCommitmentQuantity.separatedByCommaFa,
|
||||
unit: 'قطعه',
|
||||
padding: EdgeInsetsGeometry.symmetric(horizontal: 4),
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده فروش آزاد',
|
||||
value: data
|
||||
.value
|
||||
?.freeGovernmentalInfo
|
||||
?.leftTotalFreeCommitmentQuantity
|
||||
.separatedByCommaFa,
|
||||
unit: 'قطعه',
|
||||
padding: EdgeInsetsGeometry.symmetric(horizontal: 4),
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'تلفن مرغدار',
|
||||
value: data.value?.poultry?.userprofile?.mobile,
|
||||
unit: '',
|
||||
padding: EdgeInsetsGeometry.symmetric(horizontal: 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
controller.selectedPoultryHatching,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget killDateWidget({required Rx<Jalali> date, required Function(Jalali jalali) onChanged}) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.bottomSheet(modalDatePicker(onDateSelected: (value) => onChanged(value)));
|
||||
},
|
||||
child: Container(
|
||||
height: 40,
|
||||
margin: EdgeInsets.symmetric(horizontal: 8.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: AppColor.darkGreyLight),
|
||||
),
|
||||
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.yekan14.copyWith(color: AppColor.bgDark)),
|
||||
Spacer(),
|
||||
ObxValue((data) {
|
||||
return Text(
|
||||
date.value.formatCompactDate(),
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDark),
|
||||
);
|
||||
}, date),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget quantityKillsWidget() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 10.h),
|
||||
child: RTextField(
|
||||
label: 'تعداد کشتار (قطعه)',
|
||||
filled: true,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'تعداد کشتار را وارد کنید';
|
||||
}
|
||||
final count = double.tryParse(value.replaceAll(',', ''));
|
||||
if (controller.isFreeSale.value) {
|
||||
if (count! >
|
||||
(controller
|
||||
.selectedPoultryHatching
|
||||
.value
|
||||
?.freeGovernmentalInfo
|
||||
?.leftTotalFreeCommitmentQuantity ??
|
||||
0)) {
|
||||
return 'مجوز فروش آزاد شما کافی نیست';
|
||||
}
|
||||
} else {
|
||||
if (count! > (controller.selectedPoultryHatching.value?.leftOver ?? 0)) {
|
||||
return 'تعداد کشتار نباید بیشتر از باقیمانده جوجه ریزی باشد';
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
textInputAction: TextInputAction.next,
|
||||
filledColor: Colors.white,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
controller: controller.quantityKillsController,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget averageWeightKillsWidget() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w),
|
||||
child: RTextField(
|
||||
label: 'میانگین وزن (کیلوگرم)',
|
||||
filled: true,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'میانگین وزن را وارد کنید';
|
||||
}
|
||||
final weight = double.tryParse(value.replaceAll(',', ''));
|
||||
if (weight == null || weight <= 0) {
|
||||
return 'میانگین وزن باید عددی بزرگتر از صفر باشد';
|
||||
} else if (weight >
|
||||
(controller.selectedPoultryHatching.value?.managementHatchingAgeRange?.toWeight ??
|
||||
10000) ||
|
||||
weight <
|
||||
(controller
|
||||
.selectedPoultryHatching
|
||||
.value
|
||||
?.managementHatchingAgeRange
|
||||
?.fromWeight ??
|
||||
-10000)) {
|
||||
return 'میانگین وزن باید بین ${controller.selectedPoultryHatching.value?.managementHatchingAgeRange?.fromWeight} تا ${controller.selectedPoultryHatching.value?.managementHatchingAgeRange?.toWeight} کیلوگرم باشد';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
filledColor: Colors.white,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FirstDigitDecimalFormatter()],
|
||||
controller: controller.averageWeightKillsController,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget saleTypeWidget() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
margin: EdgeInsets.symmetric(horizontal: 8.w, vertical: 10.h),
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.h),
|
||||
child: ObxValue((data) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
'نوع فروش',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
RadioGroup(
|
||||
groupValue: data.value ? 1 : 0,
|
||||
onChanged: (value) {
|
||||
controller.changeSaleType();
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Radio(value: 0, activeColor: AppColor.blueNormal),
|
||||
Text('دولتی', style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDark)),
|
||||
Spacer(),
|
||||
Radio(value: 1, activeColor: AppColor.blueNormal),
|
||||
Text('آزاد', style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDark)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.isFreeSale),
|
||||
);
|
||||
}
|
||||
|
||||
Widget priceWidget() {
|
||||
return ObxValue((data) {
|
||||
if (!data.value) {
|
||||
return Container(
|
||||
height: 40.h,
|
||||
margin: EdgeInsets.symmetric(horizontal: 8.w),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.greenLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1.w, color: AppColor.whiteNormalHover),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 11.w, vertical: 4.h),
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text('قیمت مصوب', style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
|
||||
Spacer(),
|
||||
|
||||
ObxValue((data) {
|
||||
return Text(
|
||||
' ${data.value.separatedByCommaFa} ریال',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
);
|
||||
}, controller.generatedApprovedPrice),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(8.w, 0, 8.w, 0),
|
||||
child: RTextField(
|
||||
label: 'قیمت پیشنهادی (ریال)',
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'قیمت پیشنهادی را وارد کنید';
|
||||
}
|
||||
final price = double.tryParse(value.replaceAll(',', ''));
|
||||
|
||||
if (price == null || price <= 0) {
|
||||
return 'قیمت پیشنهادی باید عددی بزرگتر از صفر باشد';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
filled: true,
|
||||
borderColor: AppColor.whiteNormalHover,
|
||||
filledColor: AppColor.accent1,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
controller: controller.priceFreeSaleController,
|
||||
),
|
||||
);
|
||||
}
|
||||
}, controller.isFreeSale);
|
||||
}
|
||||
|
||||
Widget buyerListWidget() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.h, horizontal: 8.w),
|
||||
child: ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: data.value?.provinceAllowChooseKillHouse?.allowState ?? false,
|
||||
child: ObxValue((data) {
|
||||
return ResourceOverlayDropdown<KillHousePoultry>(
|
||||
items: data.value,
|
||||
background: Colors.white,
|
||||
onChanged: (value) {
|
||||
controller.selectedKillHouse.value = value;
|
||||
},
|
||||
selectedItem: controller.selectedKillHouse.value,
|
||||
itemBuilder: (item) => Text(buildKillHouseLabel(item)),
|
||||
labelBuilder: (item) => Text(buildKillHouseLabel(item)),
|
||||
);
|
||||
}, controller.killHouseList),
|
||||
);
|
||||
}, controller.selectedKillRequestPoultry),
|
||||
);
|
||||
}
|
||||
|
||||
String buildKillHouseLabel(KillHousePoultry? item) {
|
||||
if (item == null) {
|
||||
return 'خریدار/ظرفیت باقیمانده';
|
||||
} else {
|
||||
return '${item.name} / ${item.quantitySum} قطعه ';
|
||||
}
|
||||
}
|
||||
|
||||
Widget slaughterhouseSelectedWidget() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
margin: EdgeInsets.symmetric(horizontal: 8.w),
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 8.h),
|
||||
Text('عملیات کشتار', style: AppFonts.yekan14Bold.copyWith(color: AppColor.blueNormal)),
|
||||
SizedBox(height: 8.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: data.value?.permission ?? false,
|
||||
child: ObxValue(
|
||||
(data) => TitleCheckBox(
|
||||
title: ' انجماد',
|
||||
onChanged: (_) {
|
||||
controller.isFreezedSelected.value = !controller.isFreezedSelected.value;
|
||||
},
|
||||
isSelected: data.value,
|
||||
),
|
||||
controller.isFreezedSelected,
|
||||
),
|
||||
);
|
||||
}, controller.sellForFreezing),
|
||||
|
||||
ObxValue((data) {
|
||||
return TitleCheckBox(
|
||||
title: 'پنل معاملات',
|
||||
onChanged: (_) {
|
||||
controller.isMarketSelected.value = !controller.isMarketSelected.value;
|
||||
},
|
||||
isSelected: data.value,
|
||||
);
|
||||
}, controller.isMarketSelected),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: data.value?.allow ?? false,
|
||||
child: ObxValue((data) {
|
||||
return TitleCheckBox(
|
||||
title: 'صادرات',
|
||||
isSelected: data.value,
|
||||
onChanged: (_) {
|
||||
controller.isExportSelected.value = !controller.isExportSelected.value;
|
||||
},
|
||||
);
|
||||
}, controller.isExportSelected),
|
||||
);
|
||||
}, controller.poultryExport),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget submitButtonWidget() {
|
||||
return ObxValue((data) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 12.h),
|
||||
child: RElevated(
|
||||
enabled: data.value,
|
||||
height: 45.h,
|
||||
isFullWidth: true,
|
||||
disabledBackgroundColor: AppColor.greenDarkHover,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
textStyle: AppFonts.yekan16Bold.copyWith(color: Colors.white),
|
||||
onPressed: () {
|
||||
controller.submitKillRegistration();
|
||||
},
|
||||
text: 'ثبت کشتار',
|
||||
),
|
||||
);
|
||||
}, controller.isOnSubmitLoading);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class PoultryActionItem {
|
||||
final String title;
|
||||
final String route;
|
||||
final String icon;
|
||||
|
||||
PoultryActionItem({required this.title, required this.route, required this.icon});
|
||||
}
|
||||
|
||||
class PoultryActionLogic extends GetxController {
|
||||
RxList<PoultryActionItem> items = [
|
||||
PoultryActionItem(
|
||||
title: "بازرسی",
|
||||
route: ChickenRoutes.inspectionPoultryScience,
|
||||
icon: Assets.vec.chickenInspectionSvg.path,
|
||||
),
|
||||
PoultryActionItem(
|
||||
title: "ثبت کشتار",
|
||||
route: ChickenRoutes.genocidePoultryScience,
|
||||
icon: Assets.vec.registerKillSvg.path,
|
||||
),
|
||||
PoultryActionItem(
|
||||
title: "فارم ها",
|
||||
route: ChickenRoutes.farmPoultryScience,
|
||||
icon: Assets.vec.farmsSvg.path,
|
||||
),
|
||||
PoultryActionItem(
|
||||
title: "جوجه ریزی فعال",
|
||||
route: ChickenRoutes.activeHatchingPoultryScience,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
|
||||
PoultryActionItem(
|
||||
title: "بازرسی مزارع طیور",
|
||||
route: ChickenRoutes.poultryFarmInspectionHome,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
].obs;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class PoultryActionPage extends GetView<PoultryActionLogic> {
|
||||
PoultryActionPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(isBase: true, hasNews: true, hasNotification: true, child: gridWidget());
|
||||
}
|
||||
|
||||
Widget gridWidget() {
|
||||
return ObxValue((data) {
|
||||
return GridView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.symmetric(vertical: 18.h, horizontal: 32.w),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 24.h,
|
||||
crossAxisSpacing: 24.w,
|
||||
),
|
||||
itemCount: data.length,
|
||||
hitTestBehavior: HitTestBehavior.opaque,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = data[index];
|
||||
return GlassMorphismCardIcon(
|
||||
title: item.title,
|
||||
vecIcon: item.icon,
|
||||
onTap: () async {
|
||||
Get.toNamed(item.route, id: poultryFirstKey);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}, controller.items);
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/data/repositories/poultry_science/poultry_science_repository.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/home/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/pages.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||
|
||||
class PoultryScienceRootLogic extends GetxController {
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
late PoultryScienceRepository poultryRepository;
|
||||
|
||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||
RxMap<int, dynamic> homeExpandedList = RxMap();
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
RxInt currentPage = 1.obs;
|
||||
|
||||
final pages = [
|
||||
Navigator(
|
||||
key: Get.nestedKey(poultryFirstKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == ChickenRoutes.actionPoultryScience,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
PoultryScienceHomePage(),
|
||||
ProfilePage(),
|
||||
|
||||
|
||||
];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
poultryRepository = diChicken.get<PoultryScienceRepository>();
|
||||
}
|
||||
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
if (homeExpandedList.keys.contains(index)) {
|
||||
homeExpandedList.remove(index);
|
||||
} else {
|
||||
homeExpandedList[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void rootErrorHandler(DioException error) {
|
||||
handleGeneric(error, () {
|
||||
tokenService.deleteModuleTokens(Module.chicken);
|
||||
});
|
||||
}
|
||||
|
||||
void changePage(int index) {
|
||||
currentPage.value = index;
|
||||
}
|
||||
|
||||
int getNestedKey() {
|
||||
switch (currentPage.value) {
|
||||
case 0:
|
||||
return poultryFirstKey;
|
||||
case 1:
|
||||
return poultrySecondKey;
|
||||
case 2:
|
||||
return poultryThirdKey;
|
||||
default:
|
||||
return poultryFirstKey;
|
||||
}
|
||||
}
|
||||
|
||||
void popBackTaped() async{
|
||||
final nestedKeyId = getNestedKey();
|
||||
GlobalKey<NavigatorState>? currentNestedKey = Get.nestedKey(nestedKeyId);
|
||||
|
||||
if (currentNestedKey?.currentState?.canPop() == true) {
|
||||
Get.back(id: nestedKeyId);
|
||||
} else {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class PoultryScienceRootPage extends GetView<PoultryScienceRootLogic> {
|
||||
const PoultryScienceRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
onPopScopTaped: controller.popBackTaped,
|
||||
child: ObxValue((data) {
|
||||
return Stack(
|
||||
children: [
|
||||
IndexedStack(children: controller.pages, index: data.value),
|
||||
Positioned(
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
child: RBottomNavigation(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
items: [
|
||||
RBottomNavigationItem(
|
||||
label: 'عملیات',
|
||||
icon: Assets.vec.settingSvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
poultrySecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
poultryFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
poultryFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
poultryThirdKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 2,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
poultryFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
poultrySecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(2);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.currentPage),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class BuyLogic extends GetxController {
|
||||
List<String> routesName = ['خرید'];
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
fLog('BuyLogic onReady');
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void onPopScopTaped() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null || now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class BuyPage extends GetView<BuyLogic> {
|
||||
const BuyPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
isBase: true,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 21.w,
|
||||
children: [
|
||||
GlassMorphismCardIcon(
|
||||
title: 'خرید داخل استان',
|
||||
vecIcon: Assets.vec.map1Svg.path,
|
||||
gradient: LinearGradient(
|
||||
colors: [Color(0xFF00E096), Color(0xFF007D5E)],
|
||||
stops: [0.0, 0.95],
|
||||
begin: AlignmentGeometry.topLeft,
|
||||
end: AlignmentGeometry.bottomRight,
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed(ChickenRoutes.buysInProvinceSteward, id: stewardFirstKey);
|
||||
},
|
||||
),
|
||||
GlassMorphismCardIcon(
|
||||
title: 'خرید خارج استان',
|
||||
vecIcon: Assets.vec.buyOutProvinceSvg.path,
|
||||
gradient: LinearGradient(
|
||||
colors: [Color(0xFF00E096), Color(0xFF007D5E)],
|
||||
stops: [0.0, 0.95],
|
||||
begin: AlignmentGeometry.topLeft,
|
||||
end: AlignmentGeometry.bottomRight,
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed(ChickenRoutes.buysOutOfProvinceSteward, id: stewardFirstKey);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/buy/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/buy_in_province_all/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/buy_in_province_waiting/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class BuyInProvinceLogic extends GetxController {
|
||||
RxList<String> routesName = RxList();
|
||||
RxList<int> isExpandedList = <int>[].obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
|
||||
BuyLogic get buyLogic => Get.find<BuyLogic>();
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
|
||||
BuyInProvinceAllLogic buyAllLogic = Get.find<BuyInProvinceAllLogic>();
|
||||
BuyInProvinceWaitingLogic buyWaitingLogic = Get.find<BuyInProvinceWaitingLogic>();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName.value = [...buyLogic.routesName, 'داخل استان'].toList();
|
||||
routesName.add(selectedSegmentIndex.value == 0 ? 'در انتظار' : 'کل خریدها');
|
||||
ever(selectedSegmentIndex, (callback) {
|
||||
routesName.removeLast();
|
||||
routesName.add(callback == 0 ? 'در انتظار' : 'کل خریدها');
|
||||
});
|
||||
|
||||
ever(fromDateFilter, (callback) => _setFromDateFilter(callback));
|
||||
ever(toDateFilter, (callback) => _setToDateFilter(callback));
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
fLog('BuyInProvinceLogic onReady');
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void _setFromDateFilter(Jalali jalali) {
|
||||
final isWaiting = selectedSegmentIndex.value == 0;
|
||||
if (isWaiting) {
|
||||
buyWaitingLogic.fromDateFilter.value = fromDateFilter.value;
|
||||
} else {
|
||||
buyAllLogic.fromDateFilter.value = fromDateFilter.value;
|
||||
}
|
||||
}
|
||||
|
||||
void _setToDateFilter(Jalali jalali) {
|
||||
final isWaiting = selectedSegmentIndex.value == 0;
|
||||
if (isWaiting) {
|
||||
buyWaitingLogic.toDateFilter.value = fromDateFilter.value;
|
||||
} else {
|
||||
buyAllLogic.toDateFilter.value = fromDateFilter.value;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> submitFilter() async {
|
||||
final isWaiting = selectedSegmentIndex.value == 0;
|
||||
if (isWaiting) {
|
||||
buyWaitingLogic.getWaitingArrivals();
|
||||
} else {
|
||||
buyAllLogic.getAllArrivals();
|
||||
}
|
||||
}
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
searchedValue.value = data?.trim();
|
||||
final isWaiting = selectedSegmentIndex.value == 0;
|
||||
if (isWaiting) {
|
||||
buyWaitingLogic.searchedValue.value = searchedValue.value;
|
||||
} else {
|
||||
buyAllLogic.searchedValue.value = searchedValue.value;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
await rootLogic.onRefresh();
|
||||
await Future.wait([buyWaitingLogic.getWaitingArrivals(), buyAllLogic.getAllArrivals()]);
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/buy_in_province_all/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/buy_in_province_waiting/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/inventory/inventory_widget.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class BuyInProvincePage extends GetView<BuyInProvinceLogic> {
|
||||
const BuyInProvincePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routesWidget: ContainerBreadcrumb(rxRoutes: controller.routesName),
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
hasBack: true,
|
||||
backId: stewardFirstKey,
|
||||
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(filterBottomSheet());
|
||||
},
|
||||
onRefresh: controller.onRefresh,
|
||||
child: Column(
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return InventoryWidget(inventoryModel: data.value!);
|
||||
}, controller.rootLogic.inventoryModel),
|
||||
|
||||
segmentWidget(),
|
||||
ObxValue((index) {
|
||||
return Expanded(
|
||||
child: index.value == 0 ? BuyInProvinceWaitingPage() : BuyInProvinceAllPage(),
|
||||
);
|
||||
}, controller.selectedSegmentIndex),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Padding segmentWidget() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RSegment(
|
||||
children: ['در انتظار', 'کل خریدها'],
|
||||
selectedIndex: 0,
|
||||
borderColor: const Color(0xFFB4B4B4),
|
||||
selectedBorderColor: AppColor.blueNormal,
|
||||
selectedBackgroundColor: AppColor.blueLight,
|
||||
onSegmentSelected: (index) => controller.selectedSegmentIndex.value = index,
|
||||
backgroundColor: AppColor.whiteGreyNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 200,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text('فیلترها', style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
date: controller.fromDateFilter,
|
||||
onChanged: (jalali) => controller.fromDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
isFrom: false,
|
||||
date: controller.toDateFilter,
|
||||
onChanged: (jalali) => controller.toDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
RElevated(
|
||||
text: 'اعمال فیلتر',
|
||||
|
||||
isFullWidth: true,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
onPressed: () {
|
||||
controller.submitFilter();
|
||||
Get.back();
|
||||
},
|
||||
height: 40,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/steward_allocation/steward_allocation_request.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class BuyInProvinceAllLogic extends GetxController {
|
||||
RxInt isExpandedListIndex = (-1).obs;
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
RxMap<String, bool> isLoadingConfirmMap = RxMap();
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<WaitingArrivalModel>>> allProduct =
|
||||
Resource<PaginationModel<WaitingArrivalModel>>.loading().obs;
|
||||
|
||||
TextEditingController weightController = TextEditingController();
|
||||
TextEditingController countController = TextEditingController();
|
||||
TextEditingController lossController = TextEditingController();
|
||||
TextEditingController approvedWithOtpController = TextEditingController();
|
||||
|
||||
RxBool approvedWithOtpCode = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
getAllArrivals();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
debounce(searchedValue, (callback) => getAllArrivals(), time: Duration(milliseconds: 2000));
|
||||
super.onReady();
|
||||
ever(approvedWithOtpCode, (callback) {
|
||||
if (callback == false) {
|
||||
approvedWithOtpController.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
Future<void> getAllArrivals([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
allProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getWaitingArrivals(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'all'},
|
||||
pageSize: 20,
|
||||
page: currentPage.value,
|
||||
search: 'filter',
|
||||
role: 'Steward',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
),
|
||||
),
|
||||
onSuccess: (res) async {
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
allProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.empty();
|
||||
} else {
|
||||
allProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.success(
|
||||
PaginationModel<WaitingArrivalModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [...(allProduct.value.data?.results ?? []), ...(res?.results ?? [])],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> acceptEntries(WaitingArrivalModel model) async {
|
||||
var request = StewardAllocationRequest(
|
||||
allocationKey: model.key,
|
||||
checkAllocation: true,
|
||||
state: 'accepted',
|
||||
receiverRealNumberOfCarcasses: model.realNumberOfCarcasses ?? 0,
|
||||
receiverRealWeightOfCarcasses: model.realWeightOfCarcasses?.toInt() ?? 0,
|
||||
registrationCode: approvedWithOtpCode.value
|
||||
? int.parse(approvedWithOtpController.text)
|
||||
: null,
|
||||
weightLossOfCarcasses: model.weightLossOfCarcasses?.toInt() ?? 0,
|
||||
).toJson();
|
||||
request.removeWhere((key, value) => value == null);
|
||||
|
||||
safeCall(
|
||||
showError: true,
|
||||
call: () async => await rootLogic.chickenRepository.setSateForArrivals(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: request,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllArrivals();
|
||||
rootLogic.onRefresh();
|
||||
clearApprovedController();
|
||||
toggleExpansion();
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> denyEntries(WaitingArrivalModel model) async {
|
||||
var request = StewardAllocationRequest(
|
||||
allocationKey: model.key,
|
||||
checkAllocation: true,
|
||||
state: 'rejected',
|
||||
).toJson();
|
||||
request.removeWhere((key, value) => value == null);
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.setSateForArrivals(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: request,
|
||||
),
|
||||
onError: (error, stackTrace) {
|
||||
eLog(error);
|
||||
},
|
||||
onSuccess: (result) {
|
||||
getAllArrivals();
|
||||
rootLogic.onRefresh();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
String getVecPathItem(String? item) {
|
||||
switch (item) {
|
||||
case 'pending':
|
||||
return Assets.vec.timerSvg.path;
|
||||
case 'accepted':
|
||||
return Assets.vec.checkSquareSvg.path;
|
||||
case 'rejected':
|
||||
return Assets.vec.closeCircleSvg.path;
|
||||
default:
|
||||
return Assets.vec.timerSvg.path;
|
||||
}
|
||||
}
|
||||
|
||||
void clearApprovedController() {
|
||||
weightController.clear();
|
||||
countController.clear();
|
||||
lossController.clear();
|
||||
approvedWithOtpController.clear();
|
||||
approvedWithOtpCode.value = false;
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (isExpandedListIndex.value == index || index == null) {
|
||||
isExpandedListIndex.value = -1;
|
||||
} else {
|
||||
isExpandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
|
||||
Color getLabelColor(String? receiverState) {
|
||||
if (receiverState == 'pending') {
|
||||
return AppColor.yellowNormal2;
|
||||
}
|
||||
return AppColor.mediumGreyDarkHover;
|
||||
}
|
||||
}
|
||||
@@ -1,381 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/string_utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class BuyInProvinceAllPage extends GetView<BuyInProvinceAllLogic> {
|
||||
const BuyInProvinceAllPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
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),
|
||||
labelColor: getLabelColor(item.receiverState),
|
||||
labelIcon: controller.getVecPathItem(item.receiverState),
|
||||
labelIconColor: controller.getLabelColor(item.receiverState),
|
||||
);
|
||||
}, controller.isExpandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getAllArrivals(true),
|
||||
);
|
||||
}, controller.allProduct),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(WaitingArrivalModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.toSteward?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.date?.formattedJalaliDate ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 6,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: item.product?.name?.contains('مرغ گرم') ?? false,
|
||||
child: Assets.vec.hotChickenSvg.svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item.weightOfCarcasses?.separatedByCommaFa.addKg ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
textDirection: TextDirection.ltr,
|
||||
style: AppFonts.yekan12Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
item.toSteward?.guildsName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(WaitingArrivalModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.toSteward?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
item.receiverState?.faItem ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
SizedBox(width: 7),
|
||||
SvgGenImage.vec(controller.getVecPathItem(item.receiverState)).svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.darkGreyDark, BlendMode.srcIn),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'N/A',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(title: 'مشخصات فروشنده', value: item.toSteward?.user?.fullname ?? 'N/A'),
|
||||
buildRow(
|
||||
title: 'تلفن فروشنده',
|
||||
value: item.toSteward?.user?.mobile ?? 'N/A',
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
buildRow(title: 'نوع تخصیص', value: item.allocationType?.faAllocationType ?? 'N/A'),
|
||||
buildRow(title: ' سهمیه', value: item.quota?.faTitle ?? 'N/A'),
|
||||
buildRow(title: 'محصول', value: item.product?.name ?? 'N/A'),
|
||||
buildRow(
|
||||
title: 'وزن خریداری شده',
|
||||
value: item.weightOfCarcasses?.separatedByCommaFa ?? 'N/A',
|
||||
valueLabel: 'کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلوگرم',
|
||||
titleLabel: (item.approvedPriceStatus ?? false) ? 'مصوب' : 'آزاد',
|
||||
titleLabelStyle: AppFonts.yekan14Bold.copyWith(color: AppColor.greenNormal),
|
||||
value: item.amount?.separatedByCommaFa ?? 'N/A',
|
||||
valueLabel: 'ریال',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت کل',
|
||||
value: item.totalAmount?.separatedByCommaFa ?? 'N/A',
|
||||
valueLabel: 'ریال',
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: item.receiverState == 'pending',
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
text: 'تایید',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
isLoading: data[item.key!] ?? false,
|
||||
onPressed: () async {
|
||||
await Get.bottomSheet(
|
||||
conformationBottomSheet(item),
|
||||
isScrollControlled: true,
|
||||
).then((value) {
|
||||
Get.back();
|
||||
controller.clearApprovedController();
|
||||
});
|
||||
},
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
);
|
||||
}, controller.isLoadingConfirmMap),
|
||||
ROutlinedElevated(
|
||||
text: 'رد',
|
||||
textStyle: AppFonts.yekan20.copyWith(color: AppColor.redNormal),
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
buildWarningDialog(
|
||||
title: 'اخطار',
|
||||
middleText: 'آیا از رد شدن این مورد اطمینان دارید؟',
|
||||
onConfirm: () => controller.denyEntries(item),
|
||||
onRefresh: () => controller.getAllArrivals(),
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Color getLabelColor(String? item) {
|
||||
switch (item) {
|
||||
case 'pending':
|
||||
return AppColor.blueLight;
|
||||
case 'accepted':
|
||||
return AppColor.greenLightHover;
|
||||
case 'rejected':
|
||||
return AppColor.redLightHover;
|
||||
default:
|
||||
return AppColor.blueLight;
|
||||
}
|
||||
}
|
||||
|
||||
Widget conformationBottomSheet(WaitingArrivalModel item) {
|
||||
controller.weightController.text = item.weightOfCarcasses.separatedByComma;
|
||||
return BaseBottomSheet(
|
||||
height: 430.h,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
RTextField(
|
||||
label: 'وزن(کیلوگرم)',
|
||||
controller: controller.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
RTextField(
|
||||
label: 'حجم(قطعه)',
|
||||
controller: controller.countController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
RTextField(
|
||||
label: 'افت وزن(کیلوگرم)',
|
||||
controller: controller.lossController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
|
||||
Text('تایید ', style: AppFonts.yekan16Bold.copyWith(color: AppColor.textColor)),
|
||||
ObxValue((data) {
|
||||
return Column(
|
||||
children: [
|
||||
RadioGroup(
|
||||
groupValue: data.value,
|
||||
onChanged: (value) {
|
||||
controller.approvedWithOtpCode.value = value ?? false;
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
radioRow(
|
||||
value: true,
|
||||
label: ' با کد احراز',
|
||||
onTap: () {
|
||||
controller.approvedWithOtpCode.value = true;
|
||||
},
|
||||
),
|
||||
radioRow(
|
||||
value: false,
|
||||
label: 'بدون کد احراز',
|
||||
onTap: () {
|
||||
controller.approvedWithOtpCode.value = false;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
child: RTextField(
|
||||
controller: controller.approvedWithOtpController,
|
||||
label: 'کد احراز',
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
visible: data.value,
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.approvedWithOtpCode),
|
||||
SizedBox(height: 30.h),
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
enabled: controller.approvedWithOtpCode.value
|
||||
? controller.approvedWithOtpController.text.isNotEmpty
|
||||
: true,
|
||||
text: 'تایید',
|
||||
onPressed: () async {
|
||||
await controller.acceptEntries(item);
|
||||
},
|
||||
isFullWidth: true,
|
||||
);
|
||||
}, controller.approvedWithOtpCode),
|
||||
SizedBox(height: 20.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget radioRow({
|
||||
required bool value,
|
||||
required String label,
|
||||
TextStyle? textStyle,
|
||||
GestureTapCallback? onTap,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: value),
|
||||
Text(label, style: textStyle ?? AppFonts.yekan16.copyWith(color: AppColor.textColor)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/steward_allocation/steward_allocation_request.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class BuyInProvinceWaitingLogic extends GetxController {
|
||||
RxInt isExpandedListIndex = (-1).obs;
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
RxMap<String, bool> isLoadingConfirmMap = RxMap();
|
||||
Rx<Color> bgConfirmAllColor = AppColor.blueNormal.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
RxBool isButtonConfirm = false.obs;
|
||||
|
||||
Rx<Resource<PaginationModel<WaitingArrivalModel>>> waitingProduct =
|
||||
Resource<PaginationModel<WaitingArrivalModel>>.loading().obs;
|
||||
|
||||
TextEditingController weightController = TextEditingController();
|
||||
TextEditingController countController = TextEditingController();
|
||||
TextEditingController lossController = TextEditingController();
|
||||
TextEditingController approvedWithOtpController = TextEditingController();
|
||||
|
||||
RxBool approvedWithOtpCode = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getWaitingArrivals(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getWaitingArrivals();
|
||||
approvedWithOtpController.addListener(() {
|
||||
isButtonConfirm.value = approvedWithOtpController.text.trim().length > 4;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
searchedValue.value = data?.trim();
|
||||
}
|
||||
|
||||
Future<void> getWaitingArrivals([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
waitingProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getWaitingArrivals(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'not_entered'},
|
||||
pageSize: 20,
|
||||
page: currentPage.value,
|
||||
search: 'filter',
|
||||
role: 'Steward',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
),
|
||||
),
|
||||
onSuccess: (res) async {
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
waitingProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.empty();
|
||||
} else {
|
||||
waitingProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.success(
|
||||
PaginationModel<WaitingArrivalModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [...(waitingProduct.value.data?.results ?? []), ...(res?.results ?? [])],
|
||||
),
|
||||
);
|
||||
flashingFabBgColor();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> acceptEntries(WaitingArrivalModel model) async {
|
||||
var request = StewardAllocationRequest(
|
||||
allocationKey: model.key,
|
||||
checkAllocation: true,
|
||||
state: 'accepted',
|
||||
receiverRealNumberOfCarcasses: model.realNumberOfCarcasses ?? 0,
|
||||
receiverRealWeightOfCarcasses: model.realWeightOfCarcasses?.toInt() ?? 0,
|
||||
registrationCode: approvedWithOtpCode.value
|
||||
? int.parse(approvedWithOtpController.text.trim())
|
||||
: null,
|
||||
weightLossOfCarcasses: model.weightLossOfCarcasses?.toInt() ?? 0,
|
||||
stewardCheckAllocation: true,
|
||||
).toJson();
|
||||
request.removeWhere((key, value) => value == null);
|
||||
|
||||
safeCall(
|
||||
showError: true,
|
||||
showSuccess: true,
|
||||
call: () async => await rootLogic.chickenRepository.setSateForArrivals(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: request,
|
||||
),
|
||||
onError: (error, stackTrace) {
|
||||
eLog(error);
|
||||
},
|
||||
onSuccess: (result) {
|
||||
getWaitingArrivals();
|
||||
rootLogic.onRefresh();
|
||||
clearApprovedController();
|
||||
toggleExpansion();
|
||||
Future.delayed(Duration(seconds: 3), () {
|
||||
Get.back();
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> denyEntries(WaitingArrivalModel model) async {
|
||||
var request = StewardAllocationRequest(
|
||||
allocationKey: model.key,
|
||||
checkAllocation: true,
|
||||
state: 'rejected',
|
||||
).toJson();
|
||||
request.removeWhere((key, value) => value == null);
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.setSateForArrivals(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: request,
|
||||
),
|
||||
onError: (error, stackTrace) {
|
||||
eLog(error);
|
||||
},
|
||||
onSuccess: (result) {
|
||||
getWaitingArrivals();
|
||||
rootLogic.onRefresh();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void flashingFabBgColor() {
|
||||
Timer.periodic(Duration(seconds: 2), (timer) {
|
||||
if (bgConfirmAllColor.value == AppColor.blueNormal) {
|
||||
bgConfirmAllColor.value = AppColor.blueLightHover;
|
||||
} else {
|
||||
bgConfirmAllColor.value = AppColor.blueNormal;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void clearApprovedController() {
|
||||
weightController.clear();
|
||||
countController.clear();
|
||||
lossController.clear();
|
||||
approvedWithOtpController.clear();
|
||||
approvedWithOtpCode.value = false;
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (isExpandedListIndex.value == index || index == null) {
|
||||
isExpandedListIndex.value = -1;
|
||||
} else {
|
||||
isExpandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,373 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/string_utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class BuyInProvinceWaitingPage extends GetView<BuyInProvinceWaitingLogic> {
|
||||
const BuyInProvinceWaitingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
var item = data.value.data!.results![index];
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: controller.isExpandedListIndex.value == index,
|
||||
onTap: () => controller.toggleExpansion(index: index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.timerSvg.path,
|
||||
labelIconColor: AppColor.yellowNormal2,
|
||||
);
|
||||
}, controller.isExpandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getWaitingArrivals(true),
|
||||
);
|
||||
}, controller.waitingProduct),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(WaitingArrivalModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
'${controller.rootLogic.isKillHouse(item) ? 'کشتارگاه' : 'مباشر'} ${controller.rootLogic.isKillHouse(item) ? item.killHouse?.name : item.steward?.user?.fullname} ',
|
||||
textAlign: TextAlign.start,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.date?.formattedJalaliDate ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 6,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: item.product?.name?.contains('مرغ گرم') ?? false,
|
||||
child: Assets.vec.hotChickenSvg.svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item.weightOfCarcasses?.separatedByCommaFa.addKg ?? 'ندارد',
|
||||
textAlign: TextAlign.left,
|
||||
textDirection: TextDirection.ltr,
|
||||
style: AppFonts.yekan12Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
'${item.amount?.separatedByCommaFa} ریال',
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
(item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
style: AppFonts.yekan12Bold.copyWith(
|
||||
color: (item.approvedPriceStatus ?? false)
|
||||
? AppColor.blueNormal
|
||||
: AppColor.greenNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(WaitingArrivalModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${controller.rootLogic.isKillHouse(item) ? item.killHouse?.name : item.steward?.user?.fullname} ',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'در انتظار',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
SizedBox(width: 7),
|
||||
Assets.vec.clockSvg.svg(width: 16.w, height: 16.h),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'ندارد',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'مشخصات فروشنده',
|
||||
value:
|
||||
'${controller.rootLogic.isKillHouse(item) ? item.killHouse?.killHouseOperator?.user?.fullname : item.steward?.user?.fullname} ',
|
||||
),
|
||||
buildRow(
|
||||
title: 'تلفن فروشنده',
|
||||
value:
|
||||
'${controller.rootLogic.isKillHouse(item) ? item.killHouse?.killHouseOperator?.user?.mobile : item.steward?.user?.mobile} ',
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
buildRow(title: 'نوع تخصیص', value: item.allocationType?.faAllocationType ?? 'ندارد'),
|
||||
buildRow(title: ' سهمیه', value: item.quota?.faTitle ?? 'ندارد'),
|
||||
buildRow(title: 'نوع فروش', value: item.saleType == "governmental" ? 'دولتی' : 'آزاد'),
|
||||
buildRow(title: 'محصول', value: item.product?.name ?? 'ندارد'),
|
||||
buildRow(
|
||||
title: 'تاریخ تولید گوشت',
|
||||
value: item.productionDate?.toJalali.toJalaliDateTime() ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'وزن خریداری شده',
|
||||
value: '${item.weightOfCarcasses?.separatedByCommaFa} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلوگرم',
|
||||
titleLabel: (item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
titleLabelStyle: AppFonts.yekan14Bold.copyWith(color: AppColor.greenNormal),
|
||||
value: '${item.amount?.separatedByCommaFa} ریال',
|
||||
),
|
||||
|
||||
buildRow(title: 'قیمت کل', value: '${item.totalAmount?.separatedByCommaFa} ریال'),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
text: 'تایید',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
isLoading: data[item.key!] ?? false,
|
||||
onPressed: () async {
|
||||
await Get.bottomSheet(conformationBottomSheet(item), isScrollControlled: true);
|
||||
},
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
);
|
||||
}, controller.isLoadingConfirmMap),
|
||||
ROutlinedElevated(
|
||||
text: 'رد',
|
||||
textStyle: AppFonts.yekan20.copyWith(color: AppColor.redNormal),
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
buildWarningDialog(
|
||||
title: 'اخطار',
|
||||
middleText: 'آیا از رد شدن این مورد اطمینان دارید؟',
|
||||
onConfirm: () => controller.denyEntries(item),
|
||||
onRefresh: () => controller.getWaitingArrivals(),
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget conformationBottomSheet(WaitingArrivalModel item) {
|
||||
controller.weightController.text = item.weightOfCarcasses.separatedByComma;
|
||||
return BaseBottomSheet(
|
||||
height: 450.h,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
RTextField(
|
||||
label: 'وزن(کیلوگرم)',
|
||||
controller: controller.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
RTextField(
|
||||
label: 'حجم(قطعه)',
|
||||
controller: controller.countController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
RTextField(
|
||||
label: 'افت وزن(کیلوگرم)',
|
||||
controller: controller.lossController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
|
||||
Text('تایید ', style: AppFonts.yekan16Bold.copyWith(color: AppColor.textColor)),
|
||||
ObxValue((data) {
|
||||
return Column(
|
||||
children: [
|
||||
RadioGroup(
|
||||
groupValue: data.value,
|
||||
onChanged: (value) {
|
||||
controller.approvedWithOtpCode.value = value ?? false;
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
radioRow(
|
||||
value: true,
|
||||
label: ' با کد احراز',
|
||||
onTap: () {
|
||||
controller.approvedWithOtpCode.value = true;
|
||||
},
|
||||
),
|
||||
radioRow(
|
||||
value: false,
|
||||
label: 'بدون کد احراز',
|
||||
onTap: () {
|
||||
controller.approvedWithOtpCode.value = false;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
child: RTextField(
|
||||
controller: controller.approvedWithOtpController,
|
||||
label: 'کد احراز',
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 5,
|
||||
),
|
||||
visible: data.value,
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.approvedWithOtpCode),
|
||||
SizedBox(height: 30.h),
|
||||
Obx(() {
|
||||
return RElevated(
|
||||
enabled: controller.approvedWithOtpCode.value
|
||||
? controller.isButtonConfirm.value
|
||||
: true,
|
||||
text: 'تایید',
|
||||
onPressed: () async {
|
||||
await controller.acceptEntries(item);
|
||||
},
|
||||
isFullWidth: true,
|
||||
);
|
||||
}),
|
||||
SizedBox(height: 20.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget radioRow({
|
||||
required bool value,
|
||||
required String label,
|
||||
TextStyle? textStyle,
|
||||
GestureTapCallback? onTap,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: value),
|
||||
Text(label, style: textStyle ?? AppFonts.yekan16.copyWith(color: AppColor.textColor)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/create_steward_free_bar/create_steward_free_bar.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_free_bar.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/buy/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class BuyOutOfProvinceLogic extends GetxController {
|
||||
late List<String> routesName;
|
||||
RxBool isSubmitButtonEnabled = false.obs;
|
||||
RxInt expandedListIndex = (-1).obs;
|
||||
|
||||
final RxInt currentPage = 1.obs;
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
final RxBool isOnLoadingSubmitOrEdit = false.obs;
|
||||
|
||||
//TODO add this to Di
|
||||
ImagePicker imagePicker = ImagePicker();
|
||||
|
||||
Rx<Resource<PaginationModel<StewardFreeBar>>> purchaseOutOfProvinceList =
|
||||
Resource<PaginationModel<StewardFreeBar>>.loading().obs;
|
||||
Rxn<ProductModel> selectedProduct = Rxn();
|
||||
|
||||
RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
|
||||
Rxn<IranProvinceCityModel> selectedProvince = Rxn();
|
||||
Rxn<IranProvinceCityModel> selectedCity = Rxn();
|
||||
Rxn<XFile> selectedImage = Rxn<XFile>();
|
||||
final RxnString _base64Image = RxnString();
|
||||
RxnString editImageUrl = RxnString();
|
||||
RxnString editFreeBarKey = RxnString();
|
||||
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
|
||||
BuyLogic buyLogic = Get.find<BuyLogic>();
|
||||
|
||||
SaleLogic outOfTheProvinceLogic = Get.find<SaleLogic>();
|
||||
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
TextEditingController sellerNameController = TextEditingController();
|
||||
TextEditingController sellerPhoneController = TextEditingController();
|
||||
TextEditingController carcassWeightController = TextEditingController();
|
||||
TextEditingController carcassCountController = TextEditingController();
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName = [...buyLogic.routesName, 'خارج استان'].toList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getStewardPurchaseOutOfProvince();
|
||||
selectedProvince.listen((p0) => getCites());
|
||||
|
||||
selectedProduct.value = rootLogic.rolesProductsModel.first;
|
||||
setupListeners();
|
||||
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getStewardPurchaseOutOfProvince(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
sellerNameController.dispose();
|
||||
sellerPhoneController.dispose();
|
||||
carcassWeightController.dispose();
|
||||
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
searchedValue.value = data?.trim();
|
||||
}
|
||||
|
||||
Future<void> getStewardPurchaseOutOfProvince([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.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.getStewardPurchasesOutSideOfTheProvince(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
pageSize: 20,
|
||||
page: currentPage.value,
|
||||
search: 'filter',
|
||||
role: 'Steward',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
),
|
||||
),
|
||||
onSuccess: (res) async {
|
||||
await Future.delayed(Duration(milliseconds: 500));
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.empty();
|
||||
} else {
|
||||
purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.success(
|
||||
PaginationModel<StewardFreeBar>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [
|
||||
...(purchaseOutOfProvinceList.value.data?.results ?? []),
|
||||
...(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() {
|
||||
sellerNameController.addListener(() {
|
||||
checkFormValid();
|
||||
if (!isSubmitButtonEnabled.value) {
|
||||
isSubmitButtonEnabled.value = !isSubmitButtonEnabled.value;
|
||||
}
|
||||
});
|
||||
sellerPhoneController.addListener(checkFormValid);
|
||||
carcassWeightController.addListener(checkFormValid);
|
||||
carcassCountController.addListener(checkFormValid);
|
||||
|
||||
ever(selectedProvince, (_) => checkFormValid());
|
||||
ever(selectedCity, (_) => checkFormValid());
|
||||
ever(selectedProduct, (_) => checkFormValid());
|
||||
ever(selectedImage, (data) async {
|
||||
checkFormValid();
|
||||
if (data?.path != null) {
|
||||
_base64Image.value = await convertImageToBase64(data!.path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void checkFormValid() {
|
||||
isSubmitButtonEnabled.value =
|
||||
sellerNameController.text.isNotEmpty &&
|
||||
sellerPhoneController.text.isNotEmpty &&
|
||||
carcassWeightController.text.isNotEmpty &&
|
||||
carcassCountController.text.isNotEmpty &&
|
||||
selectedProvince.value != null &&
|
||||
selectedCity.value != null &&
|
||||
selectedProduct.value != null &&
|
||||
(selectedImage.value != null || editImageUrl.value != null);
|
||||
|
||||
if (isSubmitButtonEnabled.value) {
|
||||
isOnLoadingSubmitOrEdit.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> createStewardPurchaseOutOfProvince() async {
|
||||
bool res = false;
|
||||
isOnLoadingSubmitOrEdit.value = true;
|
||||
if (!(formKey.currentState?.validate() ?? false)) {
|
||||
isOnLoadingSubmitOrEdit.value = false;
|
||||
return res;
|
||||
}
|
||||
await safeCall(
|
||||
showError: true,
|
||||
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),
|
||||
numberOfCarcasses: int.parse(carcassCountController.text.clearComma),
|
||||
barImage: _base64Image.value,
|
||||
date: DateTime.now().formattedYHMS,
|
||||
);
|
||||
await rootLogic.chickenRepository.createStewardPurchasesOutSideOfTheProvince(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
body: createStewardFreeBar,
|
||||
);
|
||||
},
|
||||
onSuccess: (result) {
|
||||
getStewardPurchaseOutOfProvince();
|
||||
resetSubmitForm();
|
||||
toggleExpansion();
|
||||
res = true;
|
||||
},
|
||||
);
|
||||
isOnLoadingSubmitOrEdit.value = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
void resetSubmitForm() {
|
||||
sellerNameController.clear();
|
||||
sellerPhoneController.clear();
|
||||
carcassWeightController.clear();
|
||||
carcassCountController.clear();
|
||||
selectedProvince.value = null;
|
||||
selectedCity.value = null;
|
||||
selectedImage.value = null;
|
||||
_base64Image.value = null;
|
||||
editImageUrl.value = null;
|
||||
|
||||
isSubmitButtonEnabled.value = false;
|
||||
}
|
||||
|
||||
void setEditData(StewardFreeBar item) async {
|
||||
editImageUrl.value = item.barImage;
|
||||
sellerNameController.text = item.killHouseName ?? '';
|
||||
sellerPhoneController.text = item.killHouseMobile ?? '';
|
||||
carcassWeightController.text = item.weightOfCarcasses.separatedByComma;
|
||||
carcassCountController.text = item.numberOfCarcasses.separatedByComma;
|
||||
editFreeBarKey.value = item.key;
|
||||
selectedProvince.value = IranProvinceCityModel(name: item.province);
|
||||
selectedCity.value = IranProvinceCityModel(name: item.city);
|
||||
selectedProduct.value = rootLogic.rolesProductsModel.firstWhere(
|
||||
(element) => element.key == item.product!.key,
|
||||
);
|
||||
|
||||
isSubmitButtonEnabled.value = true;
|
||||
}
|
||||
|
||||
Future<void> editStewardPurchaseOutOfProvince() async {
|
||||
CreateStewardFreeBar edit = CreateStewardFreeBar(
|
||||
productKey: selectedProduct.value!.key,
|
||||
key: editFreeBarKey.value,
|
||||
killHouseName: sellerNameController.text,
|
||||
killHouseMobile: sellerPhoneController.text,
|
||||
province: selectedProvince.value!.name,
|
||||
city: selectedCity.value!.name,
|
||||
weightOfCarcasses: int.parse(carcassWeightController.text.clearComma),
|
||||
numberOfCarcasses: int.parse(carcassCountController.text.clearComma),
|
||||
date: DateTime.now().formattedYHMS,
|
||||
);
|
||||
|
||||
if (_base64Image.value != null) {
|
||||
edit = edit.copyWith(barImage: _base64Image.value);
|
||||
}
|
||||
|
||||
await safeCall(
|
||||
showError: true,
|
||||
call: () => rootLogic.chickenRepository.editStewardPurchasesOutSideOfTheProvince(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
body: edit,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
toggleExpansion();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteStewardPurchaseOutOfProvince(String key) async {
|
||||
await safeCall(
|
||||
call: () => rootLogic.chickenRepository.deleteStewardPurchasesOutSideOfTheProvince(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildRawQueryParams(queryParams: {'key': key}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await rootLogic.onRefresh();
|
||||
await getStewardPurchaseOutOfProvince();
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,638 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart' hide Image;
|
||||
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';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/inventory/inventory_widget.dart';
|
||||
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class BuyOutOfProvincePage extends GetView<BuyOutOfProvinceLogic> {
|
||||
const BuyOutOfProvincePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
backId: stewardFirstKey,
|
||||
onRefresh: controller.onRefresh,
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(filterBottomSheet());
|
||||
},
|
||||
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Column(
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return InventoryWidget(inventoryModel: data.value!);
|
||||
}, controller.rootLogic.inventoryModel),
|
||||
|
||||
ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
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),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.truckFastOutlinedSvg.path,
|
||||
);
|
||||
}, controller.expandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getStewardPurchaseOutOfProvince(true),
|
||||
);
|
||||
}, controller.purchaseOutOfProvinceList),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 5,
|
||||
bottom: 95,
|
||||
child: RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
addPurchasedInformationBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).whenComplete(() {
|
||||
controller.resetSubmitForm();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(StewardFreeBar item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${item.province}-${item.city}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'ندارد',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(title: 'مشخصات فروشنده', value: item.killHouseName ?? 'ندارد'),
|
||||
|
||||
buildRow(
|
||||
title: 'تلفن فروشنده',
|
||||
value: item.killHouseMobile ?? 'ندارد',
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
buildRow(title: 'محصول', value: item.product?.name ?? 'ندارد'),
|
||||
buildRow(
|
||||
title: 'وزن خریداری شده',
|
||||
value: '${item.weightOfCarcasses?.separatedByCommaFa} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'حجم خریداری شده',
|
||||
value: '${item.numberOfCarcasses?.separatedByCommaFa} قطعه',
|
||||
),
|
||||
buildRowOnTapped(
|
||||
title: 'مشاهده بارنامه',
|
||||
titleStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
valueWidget: Assets.vec.clipboardEyeSvg.svg(
|
||||
width: 20,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
BaseBottomSheet(
|
||||
height: 400,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
'بارنامه',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
|
||||
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;
|
||||
return CupertinoActivityIndicator();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'ویرایش',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
controller.setEditData(item);
|
||||
Get.bottomSheet(
|
||||
addPurchasedInformationBottomSheet(true),
|
||||
isScrollControlled: true,
|
||||
).whenComplete(() {
|
||||
controller.resetSubmitForm();
|
||||
});
|
||||
},
|
||||
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: () => controller.deleteStewardPurchaseOutOfProvince(item.key!),
|
||||
onRefresh: () async {
|
||||
controller.rootLogic.onRefresh();
|
||||
controller.onRefresh();
|
||||
controller.toggleExpansion();
|
||||
},
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(StewardFreeBar item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.killHouseName ?? 'ندارد',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.date?.formattedJalaliDate ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: item.product?.name?.contains('مرغ گرم') ?? false,
|
||||
child: Assets.vec.hotChickenSvg.svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${item.weightOfCarcasses?.separatedByCommaFa}kg',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
'${item.numberOfCarcasses.separatedByComma} ${'قطعه'}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
'${item.province}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
'${item.city}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget addPurchasedInformationBottomSheet([bool isOnEdit = false]) {
|
||||
return BaseBottomSheet(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
isOnEdit ? 'ویرایش اطلاعات خرید' : 'ثبت اطلاعات خرید',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
_productDropDown(),
|
||||
|
||||
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: [_provinceWidget(), _cityWidget()]),
|
||||
),
|
||||
|
||||
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: [
|
||||
RTextField(
|
||||
controller: controller.sellerNameController,
|
||||
label: 'نام فروشنده',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.sellerPhoneController,
|
||||
label: 'تلفن فروشنده',
|
||||
keyboardType: TextInputType.phone,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
maxLength: 11,
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
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;
|
||||
},
|
||||
),
|
||||
|
||||
UnitTextField(
|
||||
controller: controller.carcassWeightController,
|
||||
hint: 'وزن',
|
||||
unit: 'کیلوگرم',
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
),
|
||||
|
||||
UnitTextField(
|
||||
controller: controller.carcassCountController,
|
||||
hint: 'حجم',
|
||||
unit: 'قطعه',
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_imageCarcasesWidget(isOnEdit),
|
||||
submitButtonWidget(isOnEdit),
|
||||
SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget submitButtonWidget(bool isOnEdit) {
|
||||
return Obx(() {
|
||||
return RElevated(
|
||||
text: isOnEdit ? 'ویرایش' : 'ثبت',
|
||||
width: Get.width,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
isLoading: controller.isOnLoadingSubmitOrEdit.value,
|
||||
enabled: controller.isSubmitButtonEnabled.value,
|
||||
onPressed: isOnEdit
|
||||
? () async {
|
||||
await controller.editStewardPurchaseOutOfProvince();
|
||||
Get.back();
|
||||
}
|
||||
: () async {
|
||||
var res = await controller.createStewardPurchaseOutOfProvince();
|
||||
if (res) {
|
||||
Get.back();
|
||||
}
|
||||
},
|
||||
height: 40,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _productDropDown() {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<ProductModel>(
|
||||
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 _provinceWidget() {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<IranProvinceCityModel>(
|
||||
items: controller.rootLogic.provinces,
|
||||
onChanged: (value) {
|
||||
controller.selectedProvince.value = value;
|
||||
},
|
||||
selectedItem: controller.selectedProvince.value,
|
||||
itemBuilder: (item) => Text(
|
||||
item.name ?? 'بدون نام',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.lightGreyDarker),
|
||||
),
|
||||
labelBuilder: (item) => item?.name != null
|
||||
? Text(item!.name!, style: AppFonts.yekan14.copyWith(color: AppColor.textColor))
|
||||
: Text(
|
||||
'انتخاب استان',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColorLight),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _cityWidget() {
|
||||
return ObxValue((data) {
|
||||
return OverlayDropdownWidget<IranProvinceCityModel>(
|
||||
items: data,
|
||||
onChanged: (value) {
|
||||
controller.selectedCity.value = value;
|
||||
},
|
||||
selectedItem: controller.selectedCity.value,
|
||||
itemBuilder: (item) => Text(
|
||||
item.name ?? 'بدون نام',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.lightGreyDarker),
|
||||
),
|
||||
labelBuilder: (item) => item?.name != null
|
||||
? Text(item!.name!, style: AppFonts.yekan14.copyWith(color: AppColor.textColor))
|
||||
: Text('انتخاب شهر', style: AppFonts.yekan14.copyWith(color: AppColor.textColorLight)),
|
||||
);
|
||||
}, controller.cites);
|
||||
}
|
||||
|
||||
SizedBox _imageCarcasesWidget(bool isOnEdit) {
|
||||
return SizedBox(
|
||||
width: Get.width,
|
||||
height: 370,
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text('بارنامه', style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)),
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return Container(
|
||||
width: Get.width,
|
||||
height: 270,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.lightGreyNormal,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: AppColor.blackLight),
|
||||
),
|
||||
child: Center(
|
||||
child: isOnEdit
|
||||
? Image.network(controller.editImageUrl.value ?? '')
|
||||
: data.value == null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.fromLTRB(30, 10, 10, 30),
|
||||
child: Assets.vec.placeHolderSvg.svg(width: 200.w, height: 150.h),
|
||||
)
|
||||
: Image.file(File(data.value!.path), fit: BoxFit.cover),
|
||||
),
|
||||
);
|
||||
}, controller.selectedImage),
|
||||
),
|
||||
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'گالری',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
onPressed: () async {
|
||||
controller.selectedImage.value = await controller.imagePicker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
imageQuality: 60,
|
||||
maxWidth: 1080,
|
||||
maxHeight: 720,
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
ROutlinedElevated(
|
||||
text: 'دوربین',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
textStyle: AppFonts.yekan20.copyWith(color: AppColor.blueNormal),
|
||||
onPressed: () async {
|
||||
controller.selectedImage.value = await controller.imagePicker.pickImage(
|
||||
source: ImageSource.camera,
|
||||
imageQuality: 60,
|
||||
maxWidth: 1080,
|
||||
maxHeight: 720,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 200,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text('فیلترها', style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
date: controller.fromDateFilter,
|
||||
onChanged: (jalali) => controller.fromDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: dateFilterWidget(
|
||||
isFrom: false,
|
||||
date: controller.toDateFilter,
|
||||
onChanged: (jalali) => controller.toDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RElevated(
|
||||
text: 'اعمال فیلتر',
|
||||
isFullWidth: true,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
onPressed: () {
|
||||
controller.getStewardPurchaseOutOfProvince();
|
||||
Get.back();
|
||||
},
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
import 'package:rasadyar_chicken/data/models/response/bar_information/bar_information.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class HomeLogic extends GetxController {
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
RxnInt totalWeightTodayBars = RxnInt();
|
||||
Rxn<KillHouseDistributionInfo> killHouseDistributionInfo = Rxn<KillHouseDistributionInfo>();
|
||||
Rxn<BarInformation> barInformation = Rxn();
|
||||
|
||||
RxList<Map<String, String?>> inventoryItems = [
|
||||
{'خریدهای دولتی داخل استان': null},
|
||||
{'خریدهای آزاد داخل استان': null},
|
||||
{'وزن خریدهای خارج استان': null},
|
||||
{'کل ورودی به انبار': null},
|
||||
{'کل فروش': null},
|
||||
{'مانده انبار': null},
|
||||
].obs;
|
||||
|
||||
RxList<Map<String, String>> broadcastItems = [
|
||||
{'وزن دولتی': '2،225،256'},
|
||||
{'وزن آزاد': '2،225،256'},
|
||||
{'فروش دولتی': '2،225،256'},
|
||||
{'فروش آزاد': '2،225،256'},
|
||||
{'توزیع داخل استان': '2،225،256'},
|
||||
{'توزیع خارج استان': '2،225،256'},
|
||||
{'قطعه بندی': '2،225،256'},
|
||||
].obs;
|
||||
|
||||
RxBool isExpanded = false.obs;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
refreshData();
|
||||
|
||||
}
|
||||
|
||||
Future<void> refreshData() async {
|
||||
await Future.wait([
|
||||
getGeneralBarsInformation(),
|
||||
getTodayBars(),
|
||||
getDistributionInformation(),
|
||||
rootLogic.getRolesProducts(),
|
||||
rootLogic.getRolesProduct(),
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> getGeneralBarsInformation() async {
|
||||
await safeCall<BarInformation?>(
|
||||
call: () async => await rootLogic.chickenRepository.getGeneralBarInformation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(role: 'Steward'),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
barInformation.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getTodayBars() async {
|
||||
await safeCall<BarInformation?>(
|
||||
call: () async => await rootLogic.chickenRepository.getGeneralBarInformation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
fromDate: DateTime.now(),
|
||||
toDate: DateTime.now(),
|
||||
role: 'Steward',
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
totalWeightTodayBars.value = result.totalBarsWeight?.toInt();
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getDistributionInformation() async {
|
||||
await safeCall<KillHouseDistributionInfo?>(
|
||||
call: () async => await rootLogic.chickenRepository.getKillHouseDistributionInfo(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
killHouseDistributionInfo.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,269 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:rasadyar_chicken/data/data_source/local/chicken_local.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/data/models/local/widely_used_local_model.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_remain_weight/steward_remain_weight.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/steward_sales_info_dashboard/steward_sales_info_dashboard.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart'
|
||||
hide ProductModel;
|
||||
import 'package:rasadyar_chicken/data/repositories/chicken/chicken_repository.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/buy/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/home/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sale/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/segmentation/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||
|
||||
class StewardRootLogic extends GetxController {
|
||||
DateTime? _lastBackPressed;
|
||||
RxInt currentPage = 2.obs;
|
||||
List<Widget> pages = [
|
||||
BuyPage(),
|
||||
SalePage(),
|
||||
HomePage(),
|
||||
SegmentationPage(),
|
||||
ProfilePage(),
|
||||
];
|
||||
|
||||
final defaultRoutes = <int, String>{
|
||||
0: ChickenRoutes.buySteward,
|
||||
1: ChickenRoutes.saleSteward,
|
||||
};
|
||||
RxList<ProductModel> rolesProductsModel = RxList<ProductModel>();
|
||||
Rxn<WidelyUsedLocalModel> widelyUsedList = Rxn<WidelyUsedLocalModel>();
|
||||
Rxn<StewardSalesInfoDashboard> stewardSalesInfoDashboard =
|
||||
Rxn<StewardSalesInfoDashboard>();
|
||||
Rxn<StewardRemainWeight> stewardRemainWeight = Rxn<StewardRemainWeight>();
|
||||
|
||||
late DioRemote dioRemote;
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
late ChickenRepository chickenRepository;
|
||||
late ChickenLocalDataSource localDatasource;
|
||||
|
||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||
RxMap<int, dynamic> inventoryExpandedList = RxMap();
|
||||
Rxn<ProductModel> inventoryModel = Rxn<ProductModel>();
|
||||
RxList<IranProvinceCityModel> provinces = <IranProvinceCityModel>[].obs;
|
||||
|
||||
// Cancel tokens for API calls
|
||||
CancelToken? _inventoryCancelToken;
|
||||
CancelToken? _provincesCancelToken;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
localDatasource = diChicken.get<ChickenLocalDataSource>();
|
||||
chickenRepository = diChicken.get<ChickenRepository>();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
|
||||
if (provinces.isEmpty) {
|
||||
getProvinces();
|
||||
}
|
||||
if (inventoryModel.value == null) {
|
||||
getRolesProduct();
|
||||
}
|
||||
if (rolesProductsModel.isEmpty) {
|
||||
getRolesProducts();
|
||||
}
|
||||
getStewardSaleDashboard();
|
||||
getStewardRemainWeightData();
|
||||
|
||||
if (widelyUsedList.value?.hasInit != true) {
|
||||
//TODO
|
||||
localDatasource.initWidleyUsed().then(
|
||||
(value) => localDatasource.getAllWidely(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// Cancel any ongoing requests when controller is disposed
|
||||
_inventoryCancelToken?.cancel();
|
||||
_provincesCancelToken?.cancel();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
await Future.wait([
|
||||
getRolesProduct(),
|
||||
getRolesProducts(),
|
||||
getStewardSaleDashboard(),
|
||||
getStewardRemainWeightData(),
|
||||
getProvinces(),
|
||||
getStewardRemainWeightData(),
|
||||
]);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
if (inventoryExpandedList.keys.contains(index)) {
|
||||
inventoryExpandedList.remove(index);
|
||||
} else {
|
||||
inventoryExpandedList[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getRolesProduct() async {
|
||||
// Cancel previous request if still running
|
||||
_inventoryCancelToken?.cancel();
|
||||
_inventoryCancelToken = CancelToken();
|
||||
|
||||
await safeCall<List<ProductModel>?>(
|
||||
call: () async => await chickenRepository.getRolesProduct(
|
||||
token: tokenService.accessToken.value!,
|
||||
cancelToken: _inventoryCancelToken,
|
||||
role: 'Steward',
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
inventoryModel.value = result.first;
|
||||
}
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
if (error is DioException && error.type == DioExceptionType.cancel) {
|
||||
// Request was cancelled, ignore the error
|
||||
return;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void rootErrorHandler(DioException error) {
|
||||
handleGeneric(error, () {
|
||||
tokenService.deleteModuleTokens(Module.chicken);
|
||||
});
|
||||
}
|
||||
|
||||
void changePage(int index) {
|
||||
currentPage.value = index;
|
||||
}
|
||||
|
||||
Future<void> getProvinces() async {
|
||||
// Cancel previous request if still running
|
||||
_provincesCancelToken?.cancel();
|
||||
_provincesCancelToken = CancelToken();
|
||||
|
||||
try {
|
||||
final res = await chickenRepository.getProvince(
|
||||
cancelToken: _provincesCancelToken,
|
||||
);
|
||||
if (res != null) {
|
||||
provinces.clear();
|
||||
provinces.value = res;
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is DioException && e.type == DioExceptionType.cancel) {
|
||||
// Request was cancelled, ignore the error
|
||||
return;
|
||||
}
|
||||
provinces.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getRolesProducts() async {
|
||||
safeCall(
|
||||
call: () async => await chickenRepository.getRolesProducts(
|
||||
token: tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(role: 'Steward'),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
rolesProductsModel.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getStewardSaleDashboard() async {
|
||||
safeCall(
|
||||
call: () async => await chickenRepository.getStewardSalesInfoDashboard(
|
||||
token: tokenService.accessToken.value!,
|
||||
queryParameters: buildRawQueryParams(role: 'Steward'),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
stewardSalesInfoDashboard.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getStewardRemainWeightData() async {
|
||||
safeCall(
|
||||
call: () async => await chickenRepository.getStewardRemainWeight(
|
||||
token: tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
stewardRemainWeight.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
int getNestedKey() {
|
||||
switch (currentPage.value) {
|
||||
case 0:
|
||||
return stewardFirstKey;
|
||||
case 1:
|
||||
return stewardSecondKey;
|
||||
case 2:
|
||||
return stewardThirdKey;
|
||||
|
||||
case 3:
|
||||
return stewardFourthKey;
|
||||
|
||||
case 4:
|
||||
return stewardFourthKey;
|
||||
|
||||
default:
|
||||
return stewardThirdKey;
|
||||
}
|
||||
}
|
||||
|
||||
void onPopScopTaped() async {
|
||||
final nestedKeyId = getNestedKey();
|
||||
GlobalKey<NavigatorState>? currentNestedKey = Get.nestedKey(nestedKeyId);
|
||||
|
||||
if (currentNestedKey?.currentState?.canPop() == true) {
|
||||
iLog(currentNestedKey?.currentState?.canPop());
|
||||
iLog(currentNestedKey?.currentContext);
|
||||
currentNestedKey?.currentState?.popUntil((route) => route.isFirst);
|
||||
} else {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isKillHouse(WaitingArrivalModel model) =>
|
||||
model.allocationType?.split("_")[0].toLowerCase() == "killhouse";
|
||||
}
|
||||
@@ -1,691 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/chicken.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class StewardRootPage extends GetView<StewardRootLogic> {
|
||||
StewardRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ObxValue((data) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
isBase: true,
|
||||
onPopScopTaped: controller.onPopScopTaped,
|
||||
child: Stack(
|
||||
children: [
|
||||
IndexedStack(
|
||||
children: [
|
||||
Navigator(
|
||||
key: Get.nestedKey(stewardFirstKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == ChickenRoutes.buySteward,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
Navigator(
|
||||
key: Get.nestedKey(stewardSecondKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => ChickenPages.pages.firstWhere(
|
||||
(e) => e.name == ChickenRoutes.saleSteward,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
Navigator(
|
||||
key: Get.nestedKey(stewardThirdKey),
|
||||
onGenerateRoute: (settings) =>
|
||||
GetPageRoute(page: () => controller.pages[2]),
|
||||
),
|
||||
Navigator(
|
||||
key: Get.nestedKey(stewardFourthKey),
|
||||
onGenerateRoute: (settings) =>
|
||||
GetPageRoute(page: () => controller.pages[3]),
|
||||
),
|
||||
Navigator(
|
||||
key: Get.nestedKey(stewardFifthKey),
|
||||
onGenerateRoute: (settings) =>
|
||||
GetPageRoute(page: () => controller.pages[4]),
|
||||
),
|
||||
],
|
||||
index: data.value,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
child: RBottomNavigation(
|
||||
items: [
|
||||
RBottomNavigationItem(
|
||||
label: 'خرید',
|
||||
icon: Assets.vec.buySvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'فروش',
|
||||
icon: Assets.vec.saleSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 2,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(2);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'قطعه بندی',
|
||||
icon: Assets.vec.convertCubeSvg.path,
|
||||
isSelected: controller.currentPage.value == 3,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(3);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 4,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
stewardSecondKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
Get.nestedKey(
|
||||
stewardFirstKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
|
||||
controller.changePage(4);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.currentPage);
|
||||
}
|
||||
|
||||
Container _todayShipmentWidget() {
|
||||
return Container(
|
||||
height: 70,
|
||||
width: Get.width / 2,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [const Color(0xFFEAEFFF), Colors.white],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Assets.icons.cubeScan.svg(width: 30.w, height: 30),
|
||||
Text(
|
||||
'بارهای امروز',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
'2،225،256',
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
'کیلوگرم',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container _informationLabelCard({
|
||||
required String title,
|
||||
required String description,
|
||||
String unit = 'کیلوگرم',
|
||||
required String iconPath,
|
||||
required Color iconColor,
|
||||
required Color bgDescriptionColor,
|
||||
required Color bgLabelColor,
|
||||
}) {
|
||||
return Container(
|
||||
height: 82,
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Row(
|
||||
children: [
|
||||
// Left side with icon and title
|
||||
Expanded(
|
||||
child: Container(
|
||||
height: 82,
|
||||
decoration: BoxDecoration(
|
||||
color: bgLabelColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(8),
|
||||
bottomRight: Radius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
SvgGenImage.vec(iconPath).svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
|
||||
),
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.mediumGreyDarkActive,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Right side with description and unit
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: bgDescriptionColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(8),
|
||||
bottomLeft: Radius.circular(8),
|
||||
),
|
||||
),
|
||||
child: 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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container _informationIconCard({
|
||||
required String title,
|
||||
required String description,
|
||||
String unit = 'کیلوگرم',
|
||||
required String iconPath,
|
||||
required Color iconColor,
|
||||
required Color bgDescriptionColor,
|
||||
required Color bgLabelColor,
|
||||
}) {
|
||||
return Container(
|
||||
height: 110,
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
child: Container(
|
||||
height: 91,
|
||||
decoration: BoxDecoration(
|
||||
color: bgDescriptionColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.25, color: const Color(0xFFB4B4B4)),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.mediumGreyDarkActive,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
description,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan16.copyWith(
|
||||
color: AppColor.mediumGreyDarkActive,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
unit,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(
|
||||
color: AppColor.mediumGreyDarkActive,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 0,
|
||||
child: Container(
|
||||
width: 32,
|
||||
height: 32,
|
||||
decoration: ShapeDecoration(
|
||||
color: bgLabelColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
side: BorderSide(width: 0.25, color: const Color(0xFFD5D5D5)),
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: SvgGenImage.vec(iconPath).svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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),
|
||||
),
|
||||
),
|
||||
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),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget addWidelyUsed({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(0xFFD9F7F0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Assets.vec.messageAddSvg.svg(
|
||||
width: 40,
|
||||
height: 40,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColor.greenNormal,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'افزودن',
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.greenDarkHover),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/*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 ProductModel 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 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: 1,
|
||||
child: Text(
|
||||
value,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.darkGreyDarkHover,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget broadcastInformationWidget(KillHouseDistributionInfo? model) {
|
||||
return Container(
|
||||
height: 140,
|
||||
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: 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(),
|
||||
),
|
||||
],
|
||||
)
|
||||
: const Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
|
||||
Widget cardWidget({
|
||||
required String title,
|
||||
required String iconPath,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return Container(
|
||||
width: Get.width / 4,
|
||||
height: 130,
|
||||
child: GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Card(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(width: 1, color: AppColor.blueNormal),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SvgGenImage(iconPath).svg(width: 50, height: 50),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/conform_allocation/conform_allocation.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/guild/guild_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/steward_free_bar_dashboard/steward_free_bar_dashboard.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SaleLogic extends GetxController {
|
||||
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel = Rxn<List<AllocatedMadeModel>?>();
|
||||
|
||||
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
|
||||
|
||||
Rxn<StewardFreeBarDashboard> stewardFreeDashboard = Rxn<StewardFreeBarDashboard>();
|
||||
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
|
||||
List<String> routesName = ['فروش'];
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getStewardDashBord();
|
||||
|
||||
}
|
||||
|
||||
Future<void> getAllocatedMade() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getAllocatedMade(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(page: 1, pageSize: 20, search: 'filter', role: 'Steward'),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
allocatedMadeModel.value = result.results;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void checkVerfication() {}
|
||||
|
||||
void confirmAllocation(ConformAllocation allocation) {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocation: allocation.toJson(),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void denyAllocation(String token) {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.denyAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationToken: token,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> confirmAllAllocations() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationTokens: allocatedMadeModel.value?.map((e) => e.key!).toList() ?? [],
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<void> getGuilds() async {}
|
||||
|
||||
Future<void> addSale() async {}
|
||||
|
||||
void setSelectedGuild(GuildModel value) {}
|
||||
|
||||
void setSelectedProduct(ProductModel value) {}
|
||||
|
||||
Future<void> getStewardDashBord() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getStewardDashboard(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
stratDate: DateTime.now().formattedDashedGregorian,
|
||||
endDate: DateTime.now().formattedDashedGregorian,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
stewardFreeDashboard.value = result;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> submitAllocation() async {}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
rootLogic.inventoryExpandedList.clear();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
void onPopScopTaped() async {
|
||||
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null || now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/chicken.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/steward_free_bar_dashboard/steward_free_bar_dashboard.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class SalePage extends GetView<SaleLogic> {
|
||||
SalePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
isBase: true,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 21,
|
||||
children: [
|
||||
GlassMorphismCardIcon(
|
||||
title: 'فروش داخل استان',
|
||||
vecIcon: Assets.vec.map2Svg.path,
|
||||
onTap: () {
|
||||
Get.toNamed(ChickenRoutes.salesInProvinceSteward, id: stewardSecondKey);
|
||||
},
|
||||
),
|
||||
GlassMorphismCardIcon(
|
||||
title: 'فروش خارج استان',
|
||||
vecIcon: Assets.vec.saleOutProvinceSvg.path,
|
||||
onTap: () {
|
||||
Get.toNamed(ChickenRoutes.salesOutOfProvinceSteward, id: stewardSecondKey);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget addSaleOutOfTheProvinceBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text(
|
||||
'ثبت فروش خارج استان',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
RElevated(text: 'ثبت توزیع/ فروش', onPressed: () {}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _typeOuterInfoCard({
|
||||
required String title,
|
||||
required String iconPath,
|
||||
required Color foregroundColor,
|
||||
VoidCallback? onTap,
|
||||
}) {
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
height: 180,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: foregroundColor),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned(
|
||||
top: -41,
|
||||
child: SvgGenImage.vec(iconPath).svg(
|
||||
width: 45,
|
||||
height: 45,
|
||||
colorFilter: ColorFilter.mode(foregroundColor, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
|
||||
Assets.vec.shoppingBasketSvg.svg(
|
||||
width: 55,
|
||||
height: 60,
|
||||
colorFilter: ColorFilter.mode(foregroundColor, BlendMode.srcIn),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppFonts.yekan16Bold.copyWith(color: foregroundColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget summaryOfInformation(StewardFreeBarDashboard? model) {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'خلاصه اطلاعات',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 140,
|
||||
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: model == null
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 10,
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
buildRow('تعداد کل بارها', model.totalQuantity?.toString() ?? '0'),
|
||||
buildRow('تعداد کل', model.totalBars?.toString() ?? '0'),
|
||||
buildRow('وزن کل (کیلوگرم)', model.totalWeight?.toString() ?? '0'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,541 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/conform_allocation/conform_allocation.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/submit_steward_allocation/submit_steward_allocation.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/broadcast_price/broadcast_price.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/guild/guild_model.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/guild_profile/guild_profile.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/steward_remain_weight/steward_remain_weight.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/string_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SalesInProvinceLogic extends GetxController {
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
SaleLogic saleLogic = Get.find<SaleLogic>();
|
||||
RxnString searchedValue = RxnString();
|
||||
RxInt expandedListIndex = (-1).obs;
|
||||
RxList<String> routesName = RxList();
|
||||
Rx<Color> bgConfirmAllColor = AppColor.blueNormal.obs;
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
Timer? _flashingTimer;
|
||||
|
||||
Rx<Resource<PaginationModel<AllocatedMadeModel>>> allocatedList =
|
||||
Resource<PaginationModel<AllocatedMadeModel>>.loading().obs;
|
||||
|
||||
RxList<ProductModel> rolesProductsModel = RxList<ProductModel>();
|
||||
|
||||
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
|
||||
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
Rxn<ProductModel> selectedProductModel = Rxn<ProductModel>();
|
||||
Rxn<GuildModel> selectedGuildModel = Rxn<GuildModel>();
|
||||
Rxn<GuildProfile> guildProfile = Rxn<GuildProfile>();
|
||||
RxInt saleType = 1.obs;
|
||||
RxInt priceType = 2.obs;
|
||||
RxInt quotaType = 1.obs;
|
||||
RxInt weight = 0.obs;
|
||||
RxInt pricePerKilo = 0.obs;
|
||||
RxInt totalCost = 0.obs;
|
||||
RxBool isValid = false.obs;
|
||||
final weightController = TextEditingController();
|
||||
final pricePerKiloController = TextEditingController();
|
||||
final totalCostController = TextEditingController();
|
||||
|
||||
final ScrollController scrollControllerAllocationsMade = ScrollController();
|
||||
final RxInt currentPage = 1.obs;
|
||||
final RxBool addPageAllocationsMade = false.obs;
|
||||
final RxBool hasMoreDataAllocationsMade = true.obs;
|
||||
|
||||
Rxn<BroadcastPrice> broadcastPrice = Rxn<BroadcastPrice>();
|
||||
Rxn<AllocatedMadeModel> selectedAllocationModelForUpdate =
|
||||
Rxn<AllocatedMadeModel>();
|
||||
SubmitStewardAllocation? tmpStewardAllocation;
|
||||
|
||||
Rxn<Jalali> productionDate = Rxn(null);
|
||||
Rxn<int> remainingStock = Rxn(null);
|
||||
Map<String, DayData> freeProductionDateData = {};
|
||||
Map<String, DayData> governmentalProductionDateData = {};
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName.value = [...saleLogic.routesName, 'داخل استان'].toList();
|
||||
getAllocatedMade();
|
||||
getRolesProducts();
|
||||
getGuilds();
|
||||
getGuildProfile();
|
||||
getBroadcastPrice();
|
||||
ever(saleType, (callback) {
|
||||
getGuilds();
|
||||
});
|
||||
|
||||
ever(quotaType, (_) {
|
||||
remainingStock.value = null;
|
||||
productionDate.value = null;
|
||||
});
|
||||
|
||||
debounce(weight, time: Duration(milliseconds: 110), (callback) {
|
||||
totalCost.value = callback * pricePerKilo.value;
|
||||
});
|
||||
|
||||
debounce(pricePerKilo, time: Duration(milliseconds: 100), (callback) {
|
||||
totalCost.value = callback * weight.value;
|
||||
});
|
||||
|
||||
totalCost.listen((data) {
|
||||
totalCostController.text = data.toString().separatedByComma;
|
||||
|
||||
isValid.value =
|
||||
weight.value > 0 &&
|
||||
pricePerKilo.value > 0 &&
|
||||
totalCost.value > 0 &&
|
||||
selectedProductModel.value != null &&
|
||||
selectedGuildModel.value != null;
|
||||
});
|
||||
everAll([
|
||||
totalCost,
|
||||
weight,
|
||||
pricePerKilo,
|
||||
totalCost,
|
||||
selectedProductModel,
|
||||
selectedGuildModel,
|
||||
productionDate,
|
||||
], (callback) => checkVerification());
|
||||
|
||||
scrollControllerAllocationsMade.addListener(() {
|
||||
if (scrollControllerAllocationsMade.position.pixels >=
|
||||
scrollControllerAllocationsMade.position.maxScrollExtent - 100) {
|
||||
addPageAllocationsMade.value = true;
|
||||
getAllocatedMade();
|
||||
}
|
||||
});
|
||||
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getAllocatedMade(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
ever(rootLogic.stewardRemainWeight, (callback) {
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
});
|
||||
}
|
||||
|
||||
void _updateGovernmentalProductionDateData() {
|
||||
List<RemainWeightDay> dates =
|
||||
rootLogic.stewardRemainWeight.value?.governmental ?? [];
|
||||
governmentalProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
void _updateFreeProductionDateData() {
|
||||
var dates = rootLogic.stewardRemainWeight.value?.free ?? [];
|
||||
freeProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
Future<void> getAllocatedMade([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
allocatedList.value =
|
||||
Resource<PaginationModel<AllocatedMadeModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1; // Reset to first page if search value is set
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getAllocatedMade(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
page: currentPage.value,
|
||||
pageSize: 20,
|
||||
search: 'filter',
|
||||
role: 'Steward',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
),
|
||||
),
|
||||
onSuccess: (res) async {
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
allocatedList.value =
|
||||
Resource<PaginationModel<AllocatedMadeModel>>.empty();
|
||||
} else {
|
||||
allocatedList.value =
|
||||
Resource<PaginationModel<AllocatedMadeModel>>.success(
|
||||
PaginationModel<AllocatedMadeModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: isLoadingMore
|
||||
? [
|
||||
...(allocatedList.value.data?.results ?? []),
|
||||
...(res?.results ?? []),
|
||||
]
|
||||
: res?.results ?? [],
|
||||
),
|
||||
);
|
||||
isLoadingMoreAllocationsMade.value = false;
|
||||
if ((allocatedList.value.data?.results?.length ?? 0) > 1) {
|
||||
flashingFabBgColor();
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {
|
||||
isLoadingMoreAllocationsMade.value = false;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void checkVerification() {
|
||||
var hasWeight = quotaType.value == 1
|
||||
? weight.value <=
|
||||
(governmentalProductionDateData[productionDate.value
|
||||
?.formatCompactDate()]
|
||||
?.value ??
|
||||
0)
|
||||
: weight.value <=
|
||||
(freeProductionDateData[productionDate.value?.formatCompactDate()]
|
||||
?.value ??
|
||||
0);
|
||||
|
||||
isValid.value =
|
||||
weight.value > 0 &&
|
||||
pricePerKilo.value > 0 &&
|
||||
totalCost.value > 0 &&
|
||||
hasWeight &&
|
||||
selectedProductModel.value != null &&
|
||||
selectedGuildModel.value != null;
|
||||
}
|
||||
|
||||
void confirmAllocation(ConformAllocation allocation) {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocation: allocation.toJson(),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void denyAllocation(String token) {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.denyAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationToken: token,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> confirmAllAllocations() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationTokens:
|
||||
allocatedList.value.data?.results?.map((e) => e.key!).toList() ??
|
||||
[],
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getRolesProducts() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getRolesProducts(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(role: 'Steward'),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
rolesProductsModel.value = result;
|
||||
selectedProductModel.value = result.first;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getGuilds() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getGuilds(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
//queryParams: {'free': saleType.value == 2 ? true : false},
|
||||
queryParams: {'all': true},
|
||||
role: 'Steward',
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
guildsModel.clear();
|
||||
guildsModel.addAll(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addSale() async {}
|
||||
|
||||
void setSelectedGuild(GuildModel value) {
|
||||
selectedGuildModel.value = value;
|
||||
update();
|
||||
}
|
||||
|
||||
void setSelectedProduct(ProductModel value) {
|
||||
selectedProductModel.value = value;
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> getGuildProfile() async {
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getProfile(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onError: (error, stackTrace) {},
|
||||
onSuccess: (result) {
|
||||
guildProfile.value = result;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void setSubmitData() {
|
||||
tmpStewardAllocation = SubmitStewardAllocation(
|
||||
approvedPriceStatus: priceType.value == 1,
|
||||
allocationType:
|
||||
'${guildProfile.value?.steward == true ? "steward" : "guild"}_${selectedGuildModel.value?.steward == true ? "steward" : "guild"}',
|
||||
sellerType: guildProfile.value?.steward == true ? "Steward" : "Guild",
|
||||
buyerType: selectedGuildModel.value?.steward == true
|
||||
? "Steward"
|
||||
: "Guild",
|
||||
amount: pricePerKilo.value,
|
||||
totalAmount: totalCost.value,
|
||||
weightOfCarcasses: weight.value,
|
||||
sellType: saleType.value == 2 ? "free" : 'exclusive',
|
||||
numberOfCarcasses: 0,
|
||||
productionDate: productionDate.value
|
||||
?.toDateTime()
|
||||
.formattedDashedGregorian,
|
||||
quota: quotaType.value == 1 ? 'governmental' : 'free',
|
||||
guildKey: selectedGuildModel.value?.key,
|
||||
productKey: selectedProductModel.value?.key,
|
||||
date: DateTime.now().formattedDashedGregorian,
|
||||
type: "manual",
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> submitAllocation() async {
|
||||
setSubmitData();
|
||||
|
||||
safeCall(
|
||||
showError: true,
|
||||
call: () async =>
|
||||
await rootLogic.chickenRepository.postSubmitStewardAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: tmpStewardAllocation!,
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
clearForm();
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("ثبت موفق بود"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteAllocation(AllocatedMadeModel model) async {
|
||||
safeCall(
|
||||
call: () async =>
|
||||
await rootLogic.chickenRepository.deleteStewardAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: {'steward_allocation_key': model.key},
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
rootLogic.inventoryExpandedList.clear();
|
||||
stopFlashing();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void setEditData(AllocatedMadeModel item) {
|
||||
selectedAllocationModelForUpdate.value = item;
|
||||
selectedProductModel.value = rolesProductsModel.first;
|
||||
selectedGuildModel.value = GuildModel(guildsName: 'tst');
|
||||
weight.value = item.weightOfCarcasses ?? 0;
|
||||
pricePerKilo.value = item.amount ?? 0;
|
||||
totalCost.value = item.totalAmount ?? 0;
|
||||
weightController.text = weight.value.toString().separatedByComma;
|
||||
pricePerKiloController.text = pricePerKilo.value
|
||||
.toString()
|
||||
.separatedByComma;
|
||||
totalCostController.text = totalCost.value.toString().separatedByComma;
|
||||
isValid.value = true;
|
||||
productionDate.value = item.productionDate.toJalali;
|
||||
}
|
||||
|
||||
void clearForm() {
|
||||
selectedGuildModel.value = null;
|
||||
weight.value = 0;
|
||||
totalCost.value = 0;
|
||||
weightController.clear();
|
||||
if (broadcastPrice.value?.active == false) {
|
||||
pricePerKilo.value = 0;
|
||||
pricePerKiloController.clear();
|
||||
}
|
||||
totalCostController.clear();
|
||||
isValid.value = false;
|
||||
productionDate.value = null;
|
||||
quotaType.value = 1;
|
||||
priceType.value = 2;
|
||||
saleType.value = 2;
|
||||
}
|
||||
|
||||
Future<void> updateAllocation() async {
|
||||
ConformAllocation updatedAllocationModel = ConformAllocation(
|
||||
allocation_key: selectedAllocationModelForUpdate.value?.key,
|
||||
amount: pricePerKilo.value,
|
||||
total_amount: totalCost.value,
|
||||
number_of_carcasses: 0,
|
||||
weight_of_carcasses: weight.value,
|
||||
);
|
||||
|
||||
safeCall(
|
||||
showError: true,
|
||||
call: () async =>
|
||||
await rootLogic.chickenRepository.updateStewardAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: updatedAllocationModel,
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
clearForm();
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("ویرایش موفق بود"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
searchedValue.value = data?.trim();
|
||||
}
|
||||
|
||||
void flashingFabBgColor() {
|
||||
_flashingTimer?.cancel();
|
||||
|
||||
_flashingTimer = Timer.periodic(Duration(seconds: 2), (timer) {
|
||||
if (bgConfirmAllColor.value == AppColor.blueNormal) {
|
||||
bgConfirmAllColor.value = AppColor.blueLightHover;
|
||||
} else {
|
||||
bgConfirmAllColor.value = AppColor.blueNormal;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void stopFlashing() {
|
||||
_flashingTimer?.cancel();
|
||||
_flashingTimer = null;
|
||||
bgConfirmAllColor.value = AppColor.blueNormal; // بازگرداندن به رنگ پیشفرض
|
||||
}
|
||||
|
||||
Steward? getBuyerInformation(AllocatedMadeModel model) {
|
||||
if (model.allocationType?.buyerIsGuild ?? false) {
|
||||
return model.toGuilds;
|
||||
} else {
|
||||
return model.steward;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getBroadcastPrice() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getBroadcastPrice(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
broadcastPrice.value = result;
|
||||
if (broadcastPrice.value?.active == true) {
|
||||
pricePerKilo.value = broadcastPrice.value?.stewardPrice ?? 0;
|
||||
pricePerKiloController.text = pricePerKilo.value
|
||||
.toString()
|
||||
.separatedByComma;
|
||||
priceType.value = 2;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
toggleExpansion();
|
||||
currentPage.value = 1;
|
||||
hasMoreDataAllocationsMade.value = true;
|
||||
await Future.wait([
|
||||
getAllocatedMade(),
|
||||
getRolesProducts(),
|
||||
rootLogic.onRefresh(),
|
||||
]);
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,492 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sales_in_province/widgets/cu_sale_in_provience.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/string_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/inventory/inventory_widget.dart';
|
||||
|
||||
import 'package:rasadyar_core/core.dart' hide modalDatePicker;
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
||||
SalesInProvincePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
backId: stewardSecondKey,
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
onRefresh: controller.onRefresh,
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(filterBottomSheet());
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Column(
|
||||
children: [
|
||||
ObxValue((data) {
|
||||
return InventoryWidget(inventoryModel: data.value!);
|
||||
}, controller.rootLogic.inventoryModel),
|
||||
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
isPaginating: controller.isLoadingMoreAllocationsMade.value,
|
||||
onLoadMore: () async {
|
||||
controller.currentPage.value++;
|
||||
await controller.getAllocatedMade(true);
|
||||
},
|
||||
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,
|
||||
labelIcon: Assets.vec.timerSvg.path,
|
||||
labelIconColor: item.registrationCode == null
|
||||
? AppColor.darkGreyDark
|
||||
: AppColor.error,
|
||||
);
|
||||
}, controller.expandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
);
|
||||
}, controller.allocatedList),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 5,
|
||||
bottom: 95,
|
||||
child: SizedBox(
|
||||
width: Get.width - 30,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
addOrEditBottomSheet(controller),
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
).whenComplete(() {
|
||||
controller.clearForm();
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: (data.value.data?.results?.length ?? 0) > 1,
|
||||
child: AnimatedFab(
|
||||
onPressed: () async {
|
||||
Get.defaultDialog(
|
||||
title: 'تایید یکجا',
|
||||
middleText: 'آیا از تایید تمامی تخصیص ها اطمینان دارید؟',
|
||||
confirm: ElevatedButton(
|
||||
onPressed: () async {
|
||||
await controller.confirmAllAllocations();
|
||||
controller.getAllocatedMade();
|
||||
controller.rootLogic.getRolesProduct();
|
||||
Get.back();
|
||||
},
|
||||
child: Text('تایید'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
),
|
||||
cancel: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: AppColor.error,
|
||||
enableFeedback: true,
|
||||
side: BorderSide(color: AppColor.error, width: 1),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Text('لغو'),
|
||||
),
|
||||
);
|
||||
},
|
||||
message: 'تایید یکجا',
|
||||
icon: Assets.vec.clipboardTaskSvg.svg(width: 40.w, height: 40.h),
|
||||
backgroundColor: controller.bgConfirmAllColor.value,
|
||||
),
|
||||
);
|
||||
}, controller.allocatedList),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(AllocatedMadeModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
controller.getBuyerInformation(item)?.user?.fullname ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
item.createDate?.formattedJalaliDate ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 6,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: item.product?.name?.contains('مرغ گرم') ?? false,
|
||||
child: Assets.vec.hotChickenSvg.svg(
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item.weightOfCarcasses!.separatedByCommaFa.addKg,
|
||||
textAlign: TextAlign.left,
|
||||
textDirection: TextDirection.ltr,
|
||||
style: AppFonts.yekan12Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
item.amount.separatedByCommaFa.addReal,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(width: 8),
|
||||
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.approvedPriceStatus == true
|
||||
? 'دولتی'
|
||||
: item.approvedPriceStatus == false
|
||||
? 'آزاد'
|
||||
: '-',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(
|
||||
color: item.approvedPriceStatus == true
|
||||
? AppColor.blueNormal
|
||||
: AppColor.greenNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(width: 8),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(AllocatedMadeModel item, int index) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.getBuyerInformation(item)?.user?.fullname ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
item.registrationCode == null ? 'در انتظار' : 'در انتظار تایید خریدار',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(
|
||||
color: item.registrationCode == null ? AppColor.darkGreyDark : AppColor.error,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 7),
|
||||
Assets.vec.clockSvg.svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(
|
||||
item.registrationCode == null ? AppColor.darkGreyDark : AppColor.error,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'ندارد',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
buildRow(
|
||||
title: 'تلفن خریدار',
|
||||
value: controller.getBuyerInformation(item)?.user?.mobile ?? 'ندارد',
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
buildRow(title: 'محصول', value: item.product?.name ?? 'ندارد'),
|
||||
|
||||
buildRow(
|
||||
title: 'تاریخ تولید گوشت',
|
||||
value: item.productionDate?.toJalali.formatCompactDate() ?? 'ندارد',
|
||||
),
|
||||
|
||||
buildRow(title: 'نوع تخصیص', value: item.allocationType?.faAllocationType ?? 'ندارد'),
|
||||
buildRow(
|
||||
title: 'نوع فروش',
|
||||
value: (item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
),
|
||||
buildRow(title: 'نوع انبار', value: (item.quota == 'governmental') ? 'دولتی' : 'آزاد'),
|
||||
|
||||
buildRow(
|
||||
title: 'وزن خریداری شده',
|
||||
value: '${item.weightOfCarcasses?.separatedByCommaFa} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'افت وزن(کیلوگرم)',
|
||||
value: item.weightLossOfCarcasses?.toInt().toString() ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلوگرم',
|
||||
titleLabel: (item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
titleLabelStyle: AppFonts.yekan14Bold.copyWith(
|
||||
color: (item.approvedPriceStatus ?? false)
|
||||
? AppColor.blueNormal
|
||||
: AppColor.greenNormal,
|
||||
),
|
||||
value: '${item.amount?.separatedByCommaFa} ریال',
|
||||
),
|
||||
buildRow(title: 'قیمت کل', value: '${item.totalAmount?.separatedByCommaFa} ریال'),
|
||||
|
||||
buildRow(title: 'کداحراز', value: item.registrationCode?.toString() ?? 'ندارد'),
|
||||
buildRow(
|
||||
title: 'وضعیت کد احراز',
|
||||
value: item.systemRegistrationCode == true ? "ارسال شده" : "ارسال نشده",
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: item.registrationCode == null,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'ویرایش',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
controller.setEditData(item);
|
||||
Get.bottomSheet(
|
||||
addOrEditBottomSheet(controller, isEditMode: true),
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
).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(index: index);
|
||||
|
||||
await controller.deleteAllocation(item);
|
||||
},
|
||||
onRefresh: controller.onRefresh,
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 200,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text('فیلترها', style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: timeFilterWidget(
|
||||
controller: controller,
|
||||
date: controller.fromDateFilter,
|
||||
onChanged: (jalali) => controller.fromDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: timeFilterWidget(
|
||||
controller: controller,
|
||||
isFrom: false,
|
||||
date: controller.toDateFilter,
|
||||
onChanged: (jalali) => controller.toDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RElevated(
|
||||
text: 'اعمال فیلتر',
|
||||
isFullWidth: true,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
onPressed: () {
|
||||
controller.getAllocatedMade();
|
||||
Get.back();
|
||||
},
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
GestureDetector timeFilterWidget({
|
||||
required SalesInProvinceLogic controller,
|
||||
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.blueNormal),
|
||||
),
|
||||
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.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
Text(
|
||||
isFrom ? 'از' : 'تا',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return Text(
|
||||
date.value.formatCompactDate(),
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.lightGreyNormalActive),
|
||||
);
|
||||
}, date),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,515 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sales_in_province/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
Widget addOrEditBottomSheet(SalesInProvinceLogic controller, {bool isEditMode = false}) {
|
||||
return BaseBottomSheet(
|
||||
height: Get.height * (isEditMode ? 0.60 : 0.75),
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'${isEditMode ? 'ویرایش' : 'ثبت'} توزیع/ فروش',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
productDropDown(controller),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
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: [
|
||||
const SizedBox(height: 8),
|
||||
ObxValue((data) {
|
||||
return RTextField(
|
||||
controller: TextEditingController(),
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
label: 'تاریخ',
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
modalDatePicker((value) {
|
||||
controller.fromDateFilter.value = value;
|
||||
controller.fromDateFilter.refresh();
|
||||
}),
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
initText: (data.value).formatCompactDate(),
|
||||
);
|
||||
}, controller.fromDateFilter),
|
||||
Visibility(
|
||||
visible: isEditMode == false,
|
||||
child: 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.quotaType.value = 1;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 1),
|
||||
Text('دولتی', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.quotaType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Obx(() {
|
||||
return MonthlyDataCalendar(
|
||||
label: 'تاریخ تولید گوشت',
|
||||
selectedDate: controller.productionDate.value?.formatCompactDate(),
|
||||
onDateSelect: (value) {
|
||||
controller.productionDate.value = value.date;
|
||||
controller.remainingStock.value = value.remainingStock;
|
||||
},
|
||||
dayData: controller.quotaType.value == 1
|
||||
? controller.governmentalProductionDateData
|
||||
: controller.freeProductionDateData,
|
||||
);
|
||||
}),
|
||||
|
||||
Visibility(visible: isEditMode == false, child: guildsDropDown(controller)),
|
||||
|
||||
RTextField(
|
||||
controller: controller.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
autoValidateMode: AutovalidateMode.onUserInteraction,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
validator: (value) {
|
||||
if ((int.tryParse(value?.clearComma ?? '0') ?? 0) >
|
||||
(controller.remainingStock.value ?? 0)) {
|
||||
return 'وزن تخصیصی بیشتر از موجودی انبار است';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (p0) {
|
||||
controller.weight.value = int.tryParse(p0.clearComma) ?? 0;
|
||||
},
|
||||
label: 'وزن لاشه (کیلوگرم)',
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: isEditMode == false,
|
||||
child: Container(
|
||||
height: 58.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.priceType.value,
|
||||
onChanged: (value) {
|
||||
controller.priceType.value = value!;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: (controller.broadcastPrice.value?.active ?? false)
|
||||
? () {
|
||||
controller.priceType.value = 1;
|
||||
}
|
||||
: null,
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(
|
||||
value: 1,
|
||||
enabled: controller.broadcastPrice.value?.active ?? false,
|
||||
),
|
||||
Text(
|
||||
'قیمت مصوب',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color:
|
||||
(controller.broadcastPrice.value?.active ?? false)
|
||||
? AppColor.textColor
|
||||
: AppColor.labelTextColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.priceType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('قیمت آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return RTextField(
|
||||
variant: RTextFieldVariant.noBorder,
|
||||
controller: controller.pricePerKiloController,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
readonly: data.value == 1,
|
||||
onChanged: (p0) {
|
||||
controller.pricePerKilo.value = int.tryParse(p0.clearComma) ?? 0;
|
||||
},
|
||||
keyboardType: TextInputType.number,
|
||||
label: 'قیمت هر کیلو (ريال)',
|
||||
);
|
||||
}, controller.priceType),
|
||||
|
||||
RTextField(
|
||||
variant: RTextFieldVariant.noBorder,
|
||||
enabled: false,
|
||||
keyboardType: TextInputType.number,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
controller: controller.totalCostController,
|
||||
label: 'هزینه کل (ريال)',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 12.h),
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
text: isEditMode ? 'ویرایش' : 'ثبت',
|
||||
isFullWidth: true,
|
||||
textStyle: AppFonts.yekan16.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
height: 40,
|
||||
enabled: data.value,
|
||||
onPressed: isEditMode
|
||||
? () async {
|
||||
await controller.updateAllocation();
|
||||
Get.back();
|
||||
}
|
||||
: () async {
|
||||
await controller.submitAllocation();
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}, controller.isValid),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget guildsDropDown(SalesInProvinceLogic controller) {
|
||||
return Obx(() {
|
||||
final item = controller.selectedGuildModel.value;
|
||||
|
||||
return SearchableDropdown(
|
||||
onChanged: (value) {
|
||||
controller.selectedGuildModel.value = value;
|
||||
},
|
||||
selectedItem: [?item],
|
||||
singleSelect: false,
|
||||
items: controller.guildsModel,
|
||||
hintText: 'انتخاب مباشر/صنف',
|
||||
itemBuilder: (item) => Text(
|
||||
item.user != null
|
||||
? '${item.steward == true ? 'مباشر' : 'صنف'} ${item.user!.fullname} (${item.user!.mobile})'
|
||||
: 'بدون نام',
|
||||
),
|
||||
multiLabelBuilder: (item) => Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight),
|
||||
),
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
item?.user != null
|
||||
? '${item?.steward == true ? 'مباشر' : 'صنف'} ${item?.user!.fullname}'
|
||||
: 'بدون نام',
|
||||
style: AppFonts.yekan14,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
Icon(Icons.close, size: 16, color: AppColor.labelTextColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
onSearch: (query) async {
|
||||
return Future.microtask(() {
|
||||
return RxList(
|
||||
controller.guildsModel
|
||||
.where((element) => element.user?.fullname?.contains(query) ?? false)
|
||||
.toList(),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget productDropDown(SalesInProvinceLogic controller) {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<ProductModel>(
|
||||
items: controller.rolesProductsModel,
|
||||
height: 56,
|
||||
hasDropIcon: false,
|
||||
background: Colors.white,
|
||||
onChanged: (value) {
|
||||
controller.selectedProductModel.value = value;
|
||||
},
|
||||
selectedItem: controller.selectedProductModel.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(),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(visible: data.value != null, child: Text('موجودی: $data'));
|
||||
}, controller.remainingStock),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
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: Jalali.now(),
|
||||
minimumDate: Jalali.now().add(days: -1),
|
||||
maximumDate: Jalali.now(),
|
||||
mode: PersianCupertinoDatePickerMode.date,
|
||||
onDateTimeChanged: (dateTime) {
|
||||
tempPickedDate = dateTime;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget show2StepAddBottomSheet(SalesInProvinceLogic controller) {
|
||||
return BaseBottomSheet(
|
||||
height: Get.height * .39,
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
buildRow(
|
||||
title: 'تاریخ ثبت',
|
||||
value: controller.tmpStewardAllocation?.date?.formattedJalaliDate ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'نام و نام خانوادگی خریدار',
|
||||
value:
|
||||
controller.guildsModel
|
||||
.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey)
|
||||
.user
|
||||
?.fullname ??
|
||||
'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شماره خریدار',
|
||||
value:
|
||||
controller.guildsModel
|
||||
.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey)
|
||||
.user
|
||||
?.mobile ??
|
||||
'ندارد',
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلو',
|
||||
value: '${controller.tmpStewardAllocation?.amount.separatedByCommaFa ?? 0} ریال ',
|
||||
),
|
||||
buildRow(
|
||||
title: 'وزن تخصیصی',
|
||||
value:
|
||||
'${controller.tmpStewardAllocation?.weightOfCarcasses?.toInt().separatedByCommaFa ?? 0} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت کل',
|
||||
value: '${controller.tmpStewardAllocation?.totalAmount.separatedByCommaFa ?? 0} ریال',
|
||||
),
|
||||
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: RElevated(
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
height: 40,
|
||||
text: 'ثبت',
|
||||
textStyle: AppFonts.yekan18.copyWith(color: Colors.white),
|
||||
onPressed: () async {
|
||||
await controller.submitAllocation();
|
||||
Get
|
||||
..back()
|
||||
..back();
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ROutlinedElevated(
|
||||
height: 40,
|
||||
borderColor: AppColor.error,
|
||||
text: ' بازگشت',
|
||||
textStyle: AppFonts.yekan18.copyWith(color: AppColor.error),
|
||||
onPressed: () {
|
||||
Get
|
||||
..back()
|
||||
..back();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1,382 +0,0 @@
|
||||
import 'package:flutter/material.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/broadcast_price/broadcast_price.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/data/models/response/steward_remain_weight/steward_remain_weight.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sales_out_of_province_buyers/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sales_out_of_province_sales_list/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SalesOutOfProvinceLogic extends GetxController {
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
|
||||
SaleLogic saleLogic = Get.find<SaleLogic>();
|
||||
|
||||
SalesOutOfProvinceSalesListLogic saleListLogic = Get.find<SalesOutOfProvinceSalesListLogic>();
|
||||
|
||||
SalesOutOfProvinceBuyersLogic buyerLogic = Get.find<SalesOutOfProvinceBuyersLogic>();
|
||||
|
||||
RxBool isExpanded = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxBool isSaleSubmitButtonEnabled = false.obs;
|
||||
RxInt expandedListIndex = (-1).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();
|
||||
Rxn<BroadcastPrice> broadcastPrice = Rxn<BroadcastPrice>();
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
TextEditingController quarantineCodeController = TextEditingController();
|
||||
TextEditingController saleWeightController = TextEditingController();
|
||||
TextEditingController saleCountController = TextEditingController();
|
||||
TextEditingController pricePerKiloController = TextEditingController();
|
||||
TextEditingController totalCostController = TextEditingController();
|
||||
TextEditingController otpCodeSell = TextEditingController();
|
||||
Rx<Jalali> saleDate = Jalali.now().obs;
|
||||
String? key;
|
||||
RxInt pricePerKilo = 0.obs;
|
||||
RxInt totalCost = 0.obs;
|
||||
RxInt weight = 0.obs;
|
||||
RxString otpCode = ''.obs;
|
||||
|
||||
Rx<Resource<PaginationModel<StewardFreeSaleBar>>> salesList =
|
||||
Resource<PaginationModel<StewardFreeSaleBar>>.loading().obs;
|
||||
|
||||
Rxn<ProductModel> selectedProduct = Rxn();
|
||||
Rxn<OutProvinceCarcassesBuyer> selectedBuyer = Rxn();
|
||||
|
||||
RxInt saleType = 2.obs;
|
||||
RxInt quotaType = 1.obs;
|
||||
Rxn<Jalali> productionDate = Rxn();
|
||||
Rxn<int> remainingStock = Rxn(null);
|
||||
Map<String, DayData> freeProductionDateData = {};
|
||||
Map<String, DayData> governmentalProductionDateData = {};
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName.value = [...saleLogic.routesName, 'خارج استان'].toList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getOutProvinceSales();
|
||||
getBroadcastPrice();
|
||||
selectedProduct.value = rootLogic.rolesProductsModel.first;
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getOutProvinceSales(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
setupListeners();
|
||||
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
ever(rootLogic.stewardRemainWeight, (callback) {
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
});
|
||||
ever(quotaType, (_) {
|
||||
remainingStock.value = null;
|
||||
productionDate.value = null;
|
||||
});
|
||||
debounce(pricePerKilo, time: Duration(milliseconds: 100), (callback) {
|
||||
totalCost.value = callback * (weight.value);
|
||||
});
|
||||
|
||||
ever(totalCost, (callback) {
|
||||
totalCostController.text = callback.separatedByComma;
|
||||
});
|
||||
}
|
||||
|
||||
void _updateGovernmentalProductionDateData() {
|
||||
List<RemainWeightDay> dates = rootLogic.stewardRemainWeight.value?.governmental ?? [];
|
||||
governmentalProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
void _updateFreeProductionDateData() {
|
||||
var dates = rootLogic.stewardRemainWeight.value?.free ?? [];
|
||||
freeProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
void setSearchValue(String? value) {
|
||||
searchedValue.value = value?.trim();
|
||||
}
|
||||
|
||||
void submitFilter() {
|
||||
fromDateFilter.value = fromDateFilter.value;
|
||||
toDateFilter.value = toDateFilter.value;
|
||||
getOutProvinceSales();
|
||||
}
|
||||
|
||||
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);
|
||||
saleWeightController.addListener(() {
|
||||
checkSalesFormValid();
|
||||
weight.value = int.parse(saleWeightController.text.clearComma);
|
||||
var res = (weight / selectedProduct.value!.weightAverage!.toInt()).round();
|
||||
saleCountController.text = res.separatedByComma;
|
||||
});
|
||||
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 = rootLogic.rolesProductsModel.first;
|
||||
key = item.key;
|
||||
saleType.value = item.saleType == 'free' ? 2 : 1;
|
||||
quotaType.value = item.quota == 'governmental' ? 1 : 2;
|
||||
isSaleSubmitButtonEnabled.value = true;
|
||||
productionDate.value = item.productionDate.toJalali;
|
||||
pricePerKiloController.text = pricePerKilo.value.toString().separatedByComma;
|
||||
totalCostController.text = totalCost.value.toString().separatedByComma;
|
||||
}
|
||||
|
||||
Future<void> deleteStewardPurchaseOutOfProvince(String key) async {
|
||||
await safeCall(
|
||||
call: () => rootLogic.chickenRepository.deleteOutProvinceStewardFreeBar(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
key: key,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> createSale() async {
|
||||
bool res = false;
|
||||
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
|
||||
buyerKey: selectedBuyer.value?.key,
|
||||
numberOfCarcasses: int.tryParse(saleCountController.text.clearComma),
|
||||
weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma),
|
||||
date: saleDate.value.toDateTime().formattedDashedGregorian,
|
||||
clearanceCode: quarantineCodeController.text,
|
||||
productKey: selectedProduct.value?.key,
|
||||
saleType: saleType.value == 2 ? 'free' : 'exclusive',
|
||||
quota: quotaType.value == 1 ? 'governmental' : 'free',
|
||||
productionDate: productionDate.value?.toDateTime().formattedDashedGregorian,
|
||||
);
|
||||
await safeCall(
|
||||
showError: true,
|
||||
call: () => rootLogic.chickenRepository.createOutProvinceStewardFreeBar(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
body: requestBody,
|
||||
),
|
||||
onSuccess: (_) {
|
||||
res = true;
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("عملیات با موفقیت انجام شد"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
void clearSaleForm() {
|
||||
quarantineCodeController.clear();
|
||||
saleWeightController.clear();
|
||||
saleDate.value = Jalali.now();
|
||||
productionDate.value = null;
|
||||
saleType.value = 2;
|
||||
quotaType.value = 2;
|
||||
selectedBuyer.value = null;
|
||||
}
|
||||
|
||||
Future<bool> editSale() async {
|
||||
bool res = false;
|
||||
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
|
||||
numberOfCarcasses: int.tryParse(saleCountController.text.clearComma),
|
||||
weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma),
|
||||
date: saleDate.value.toDateTime().formattedDashedGregorian,
|
||||
clearanceCode: quarantineCodeController.text,
|
||||
saleType: saleType.value == 2 ? 'free' : 'exclusive',
|
||||
quota: quotaType.value == 1 ? 'governmental' : 'free',
|
||||
key: key,
|
||||
);
|
||||
await safeCall(
|
||||
call: () => rootLogic.chickenRepository.updateOutProvinceStewardFreeBar(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
body: requestBody,
|
||||
),
|
||||
onSuccess: (_) {
|
||||
res = true;
|
||||
onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("عملیات با موفقیت انجام شد"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
Future sendSaleOtpCode(StewardFreeSaleBar item) async {
|
||||
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
|
||||
buyerKey: item.buyer?.key,
|
||||
buyerName: item.buyer?.fullname,
|
||||
buyerMobile: item.buyer?.mobile,
|
||||
numberOfCarcasses: item.numberOfCarcasses,
|
||||
weightOfCarcasses: item.weightOfCarcasses?.toInt(),
|
||||
date: item.date,
|
||||
clearanceCode: item.clearanceCode,
|
||||
registerCode: otpCode.value,
|
||||
saleType: item.saleType,
|
||||
quota: item.quota,
|
||||
role: "Steward",
|
||||
key: item.key,
|
||||
city: item.city,
|
||||
province: item.province,
|
||||
);
|
||||
await safeCall(
|
||||
showError: true,
|
||||
call: () => rootLogic.chickenRepository.updateOutProvinceStewardFreeBar(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
body: requestBody,
|
||||
),
|
||||
onSuccess: (_) {
|
||||
onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("عملیات با موفقیت انجام شد"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void resetSubmitForm() {
|
||||
selectedCity.value = null;
|
||||
|
||||
key = null;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
toggleExpansion();
|
||||
currentPage.value = 1;
|
||||
resetSubmitForm();
|
||||
clearSaleForm();
|
||||
await rootLogic.onRefresh();
|
||||
await getOutProvinceSales();
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getBroadcastPrice() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getBroadcastPrice(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
broadcastPrice.value = result;
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void setSaleDate(Jalali value) {
|
||||
saleDate.value = value;
|
||||
saleDate.refresh();
|
||||
dateErrorDialog();
|
||||
}
|
||||
|
||||
void setProductionDate(DayInfo value) {
|
||||
productionDate.value = value.date;
|
||||
remainingStock.value = value.remainingStock;
|
||||
dateErrorDialog();
|
||||
}
|
||||
|
||||
void dateErrorDialog() {
|
||||
if ((productionDate.value?.distanceTo(saleDate.value) ?? 0) >= 1) {
|
||||
saleDate.value = Jalali.now();
|
||||
Future.delayed(
|
||||
Duration(milliseconds: 300),
|
||||
() => defaultShowErrorMessage("تاریخ تولید نمی تواند قبل از تاریخ فروش باشد"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,225 +0,0 @@
|
||||
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/steward/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sales_out_of_province/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SalesOutOfProvinceBuyersLogic extends GetxController {
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
|
||||
SaleLogic get saleLogic => Get.find<SaleLogic>();
|
||||
|
||||
SalesOutOfProvinceLogic get saleOutOfProvince => Get.find<SalesOutOfProvinceLogic>();
|
||||
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedListIndex = (-1).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;
|
||||
|
||||
RxList<String> routesName = RxList();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName.value = [...saleLogic.routesName, 'خریداران'].toList();
|
||||
getOutProvinceCarcassesBuyer();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
|
||||
selectedProvince.listen((p0) => getCites());
|
||||
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getOutProvinceCarcassesBuyer(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
|
||||
setupListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
buyerNameController.dispose();
|
||||
buyerLastNameController.dispose();
|
||||
buyerPhoneController.dispose();
|
||||
buyerUnitNameController.dispose();
|
||||
selectedCity.value = null;
|
||||
selectedProvince.value = null;
|
||||
|
||||
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',
|
||||
);
|
||||
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;
|
||||
}
|
||||
|
||||
void setSearchValue(String? value) {
|
||||
searchedValue.value = value?.trim();
|
||||
}
|
||||
|
||||
void submitFilter() {
|
||||
fromDateFilter.value = fromDateFilter.value;
|
||||
toDateFilter.value = toDateFilter.value;
|
||||
getOutProvinceCarcassesBuyer();
|
||||
}
|
||||
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await rootLogic.onRefresh();
|
||||
await getOutProvinceCarcassesBuyer();
|
||||
}
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
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/utils/nested_keys_utils.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 SalesOutOfProvinceBuyersPage extends GetView<SalesOutOfProvinceBuyersLogic> {
|
||||
const SalesOutOfProvinceBuyersPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
backId: stewardSecondKey,
|
||||
onRefresh: controller.onRefresh,
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
filteringWidget: filterBottomSheet(),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: Get.width,
|
||||
height: 39,
|
||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.greenLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.textColor, width: 0.5),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'لیست خریداران خارج از استان',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkHover),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
onLoadMore: () async => controller.getOutProvinceCarcassesBuyer(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),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.userRaduisSvg.path,
|
||||
);
|
||||
}, controller.expandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
);
|
||||
}, controller.buyerList),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 100,
|
||||
child: RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
addOrEditBuyerBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).whenComplete(() => controller.resetSubmitForm());
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget addOrEditBuyerBottomSheet([bool isOnEdit = false]) {
|
||||
return BaseBottomSheet(
|
||||
height: 600,
|
||||
child: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
isOnEdit ? 'ویرایش خریدار' : 'افزودن خریدار',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
|
||||
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: [_provinceWidget(), _cityWidget()]),
|
||||
),
|
||||
|
||||
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: [
|
||||
RTextField(
|
||||
controller: controller.buyerNameController,
|
||||
label: 'نام خریدار',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.buyerLastNameController,
|
||||
label: 'نام خانوادگی خریدار',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.buyerPhoneController,
|
||||
label: 'تلفن خریدار',
|
||||
keyboardType: TextInputType.phone,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
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.buyerUnitNameController,
|
||||
label: 'نام واحد',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
),
|
||||
|
||||
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 = 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);
|
||||
}
|
||||
|
||||
Padding itemListWidget(OutProvinceCarcassesBuyer item) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 8),
|
||||
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(OutProvinceCarcassesBuyer item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
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.separatedByCommaFa}',
|
||||
),
|
||||
buildRow(
|
||||
title: 'حجم تقریبی',
|
||||
value: '${item.requestsInfo?.totalQuantity.separatedByCommaFa}',
|
||||
valueLabel: 'قطعه',
|
||||
),
|
||||
buildRow(
|
||||
title: 'وزن',
|
||||
value: '${item.requestsInfo?.totalWeight.separatedByCommaFa}',
|
||||
valueLabel: 'کیلوگرم',
|
||||
),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'ویرایش',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
controller.setEditDataBuyer(item);
|
||||
Get.bottomSheet(
|
||||
addOrEditBuyerBottomSheet(true),
|
||||
isScrollControlled: true,
|
||||
).whenComplete(() => controller.resetSubmitForm());
|
||||
},
|
||||
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() => filterBottomSheetWidget(
|
||||
fromDate: controller.fromDateFilter,
|
||||
onChangedFromDate: (jalali) => controller.fromDateFilter.value = jalali,
|
||||
toDate: controller.toDateFilter,
|
||||
onChangedToDate: (jalali) => controller.toDateFilter.value = jalali,
|
||||
onSubmit: () => controller.submitFilter(),
|
||||
);
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
import 'package:flutter/material.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/steward/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/sale/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/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 {
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
|
||||
SaleLogic saleLogic = Get.find<SaleLogic>();
|
||||
|
||||
SalesOutOfProvinceBuyersLogic buyerLogic = Get.find<SalesOutOfProvinceBuyersLogic>();
|
||||
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
RxBool isExpanded = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxBool isSaleSubmitButtonEnabled = false.obs;
|
||||
RxInt expandedListIndex = (-1).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();
|
||||
|
||||
|
||||
|
||||
RxInt saleType = 1.obs;
|
||||
RxInt quotaType = 1.obs;
|
||||
|
||||
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
TextEditingController quarantineCodeController = TextEditingController();
|
||||
TextEditingController saleWeightController = TextEditingController();
|
||||
TextEditingController saleCountController = 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();
|
||||
|
||||
selectedProduct.value = rootLogic.rolesProductsModel.first;
|
||||
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() {
|
||||
|
||||
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 = rootLogic.rolesProductsModel.first;
|
||||
key = item.key;
|
||||
isSaleSubmitButtonEnabled.value = true;
|
||||
}
|
||||
|
||||
Future<void> deleteStewardPurchaseOutOfProvince(String key) async {
|
||||
//todo
|
||||
/* await safeCall(
|
||||
call: () => rootLogic.chickenRepository
|
||||
.editStewardPurchasesOutSideOfTheProvince(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
stewardFreeBarKey: key,
|
||||
),
|
||||
);*/
|
||||
}
|
||||
|
||||
Future<bool> createSale() async {
|
||||
bool res = false;
|
||||
var tmpWight = int.tryParse(saleWeightController.text.clearComma);
|
||||
var tmpCount = (tmpWight! / selectedProduct.value!.weightAverage!).round();
|
||||
|
||||
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
|
||||
buyerKey: selectedBuyer.value?.key,
|
||||
numberOfCarcasses: tmpCount,
|
||||
weightOfCarcasses: tmpWight,
|
||||
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;
|
||||
}
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,498 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
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/routes/routes.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),
|
||||
|
||||
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,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item, index),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.timerSvg.path,
|
||||
labelIconColor: AppColor.yellowNormal2,
|
||||
);
|
||||
}, controller.expandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
);
|
||||
}, controller.salesList),
|
||||
floatingActionButton: Row(
|
||||
children: [
|
||||
RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
addOrEditSaleBottomSheet(),
|
||||
ignoreSafeArea: false,
|
||||
isScrollControlled: true,
|
||||
).whenComplete(() {
|
||||
controller.clearSaleForm();
|
||||
});
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
RFab(
|
||||
icon: Icon(CupertinoIcons.person_add_solid, color: Colors.white, size: 35.w),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
onPressed: () {
|
||||
Get.toNamed(ChickenRoutes.salesOutOfProvinceBuyerSteward, id: 1);
|
||||
},
|
||||
),
|
||||
SizedBox(width: 25),
|
||||
],
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(StewardFreeSaleBar item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text(
|
||||
item.date?.formattedJalaliDate ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.buyer?.fullname ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
item.buyer?.mobile ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
item.buyer?.unitName ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
Text(
|
||||
'${item.weightOfCarcasses?.separatedByCommaFa ?? 0}KG',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(StewardFreeSaleBar item, int index) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${item.province}-${item.city}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(
|
||||
item.date?.toJalali.formatter.wN ?? 'ندارد',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.y}',
|
||||
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
buildRow(title: 'مشخصات خریدار', value: item.buyer?.fullname ?? 'ندارد'),
|
||||
buildRow(title: 'تلفن خریدار', value: item.buyer?.mobile ?? 'ندارد'),
|
||||
buildRow(title: 'نام واحد', value: item.buyer?.unitName ?? 'ندارد'),
|
||||
buildRow(title: 'وزن لاشه', value: '${item.weightOfCarcasses?.separatedByCommaFa}'),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'ویرایش',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
controller.setEditDataSales(item);
|
||||
Get.bottomSheet(
|
||||
addOrEditSaleBottomSheet(true),
|
||||
isScrollControlled: true,
|
||||
).whenComplete(() {
|
||||
controller.resetSubmitForm();
|
||||
});
|
||||
},
|
||||
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.deleteStewardPurchaseOutOfProvince(item.key!);
|
||||
},
|
||||
onRefresh: () => controller.getOutProvinceSales(),
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget addOrEditSaleBottomSheet([bool isOnEdit = false]) {
|
||||
return BaseBottomSheet(
|
||||
height: 500.h,
|
||||
child: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
isOnEdit ? 'ویرایش فروش' : 'افزودن فروش',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
_productDropDown(),
|
||||
|
||||
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: [
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: timeFilterWidget(
|
||||
date: controller.saleDate,
|
||||
onChanged: (jalali) => controller.saleDate.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
_buyerWidget(),
|
||||
RTextField(
|
||||
controller: controller.saleWeightController,
|
||||
label: 'وزن لاشه',
|
||||
keyboardType: TextInputType.number,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
|
||||
validator: (value) {
|
||||
if (value == null) {
|
||||
return 'لطفاً وزن لاشه را وارد کنید';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
RTextField(
|
||||
controller: controller.saleCountController,
|
||||
label: 'حجم تقریبی(قطعه)',
|
||||
keyboardType: TextInputType.number,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
|
||||
validator: (value) {
|
||||
if (value == null) {
|
||||
return 'لطفاً وزن لاشه را وارد کنید';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
|
||||
RTextField(
|
||||
controller: controller.quarantineCodeController,
|
||||
label: 'کد قرنطینه',
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
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.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 _productDropDown() {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<ProductModel>(
|
||||
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}',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
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: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: AppColor.darkGreyLight),
|
||||
),
|
||||
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;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,309 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/broadcast_price/broadcast_price.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/data/models/response/steward_remain_weight/steward_remain_weight.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SegmentationLogic extends GetxController {
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
|
||||
RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
|
||||
late List<String> routesName;
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
RxBool isExpanded = false.obs;
|
||||
|
||||
RxInt expandedListIndex = (-1).obs;
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
RxInt segmentType = 1.obs;
|
||||
RxInt priceType = 2.obs;
|
||||
RxInt quotaType = 2.obs;
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
TextEditingController weightController = TextEditingController(text: '0');
|
||||
RxBool isSubmitButtonEnabled = false.obs;
|
||||
Rxn<GuildModel> selectedGuildModel = Rxn<GuildModel>();
|
||||
Rxn<ProductModel> selectedProduct = Rxn<ProductModel>();
|
||||
Rxn<SegmentationModel> selectedSegment = Rxn<SegmentationModel>();
|
||||
Rxn<BroadcastPrice> broadcastPrice = Rxn<BroadcastPrice>();
|
||||
Rx<Resource<PaginationModel<SegmentationModel>>> segmentationList =
|
||||
Resource<PaginationModel<SegmentationModel>>.loading().obs;
|
||||
|
||||
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
|
||||
Rx<Jalali> saleDate = Jalali.now().obs;
|
||||
RxInt weight = 0.obs;
|
||||
Rxn<Jalali> productionDate = Rxn(null);
|
||||
Rxn<int> remainingStock = Rxn(null);
|
||||
Map<String, DayData> freeProductionDateData = {};
|
||||
Map<String, DayData> governmentalProductionDateData = {};
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName = ['قطعهبندی'].toList();
|
||||
once(rootLogic.rolesProductsModel, (callback) => selectedProduct.value = callback.first);
|
||||
getAllSegmentation();
|
||||
getGuilds();
|
||||
|
||||
ever(quotaType, (_) {
|
||||
remainingStock.value = null;
|
||||
productionDate.value = null;
|
||||
});
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
ever(rootLogic.stewardRemainWeight, (callback) {
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
});
|
||||
}
|
||||
|
||||
void _updateGovernmentalProductionDateData() {
|
||||
List<RemainWeightDay> dates = rootLogic.stewardRemainWeight.value?.governmental ?? [];
|
||||
governmentalProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
void _updateFreeProductionDateData() {
|
||||
var dates = rootLogic.stewardRemainWeight.value?.free ?? [];
|
||||
freeProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
setUpListener();
|
||||
}
|
||||
|
||||
|
||||
void setSearchValue(String? value) {
|
||||
searchedValue.value = value?.trim();
|
||||
}
|
||||
|
||||
void setUpListener() {
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getAllSegmentation(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
|
||||
everAll([selectedSegment, quotaType, priceType], (_) {
|
||||
validateForm();
|
||||
});
|
||||
|
||||
weightController.addListener(() => validateForm());
|
||||
}
|
||||
|
||||
void setEditData(SegmentationModel item) {
|
||||
selectedSegment.value = item;
|
||||
weightController.text = item.weight.toString();
|
||||
}
|
||||
|
||||
void clearForm() {
|
||||
weightController.text = '0';
|
||||
selectedSegment.value = null;
|
||||
selectedGuildModel.value = null;
|
||||
productionDate.value = null;
|
||||
segmentType.value = 1;
|
||||
priceType.value = 2;
|
||||
quotaType.value = 1;
|
||||
remainingStock.value = null;
|
||||
}
|
||||
|
||||
void validateForm() {
|
||||
var weight = int.tryParse(weightController.text.trim().clearComma) ?? 0;
|
||||
var hasWeight = (remainingStock.value ?? 0) > weight;
|
||||
isSubmitButtonEnabled.value =
|
||||
selectedProduct.value != null &&
|
||||
weightController.text.isNotEmpty &&
|
||||
hasWeight &&
|
||||
productionDate.value != null &&
|
||||
weight > 0 &&
|
||||
(segmentType.value == 1 || (segmentType.value == 2 && selectedGuildModel.value != null));
|
||||
}
|
||||
|
||||
Future<void> getAllSegmentation([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
segmentationList.value = Resource<PaginationModel<SegmentationModel>>.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(
|
||||
showError: true,
|
||||
call: () async => await rootLogic.chickenRepository.getSegmentation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
pageSize: 20,
|
||||
page: currentPage.value,
|
||||
search: 'filter',
|
||||
role: 'Steward',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
),
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
if ((result?.count ?? 0) == 0) {
|
||||
segmentationList.value = Resource<PaginationModel<SegmentationModel>>.empty();
|
||||
} else {
|
||||
segmentationList.value = Resource<PaginationModel<SegmentationModel>>.success(
|
||||
PaginationModel<SegmentationModel>(
|
||||
count: result?.count ?? 0,
|
||||
next: result?.next,
|
||||
previous: result?.previous,
|
||||
results: [
|
||||
...(segmentationList.value.data?.results ?? []),
|
||||
...(result?.results ?? []),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
isLoadingMoreAllocationsMade.value = false;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteSegmentation(String key) async {
|
||||
await safeCall(
|
||||
showError: true,
|
||||
showSuccess: true,
|
||||
call: () => rootLogic.chickenRepository.deleteSegmentation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
key: key,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> editSegment() async {
|
||||
var res = true;
|
||||
safeCall(
|
||||
showError: true,
|
||||
call: () async => await rootLogic.chickenRepository.editSegmentation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
model: SegmentationModel(
|
||||
key: selectedSegment.value?.key,
|
||||
weight: int.tryParse(weightController.text.clearComma) ?? 0,
|
||||
productionDate: productionDate.value?.toDateTime().formattedDashedGregorian,
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
res = true;
|
||||
onRefresh();
|
||||
},
|
||||
onError: (error, stacktrace) {
|
||||
res = false;
|
||||
},
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<bool> createSegment() async {
|
||||
var res = true;
|
||||
SegmentationModel segmentationModel = SegmentationModel(
|
||||
productKey: selectedProduct.value?.key,
|
||||
weight: int.tryParse(weightController.text.clearComma) ?? 0,
|
||||
saleType: priceType.value == 1 ? 'governmental' : 'free',
|
||||
quota: quotaType.value == 1 ? 'governmental' : 'free',
|
||||
);
|
||||
if (segmentType.value == 2) {
|
||||
segmentationModel = segmentationModel.copyWith(guildKey: selectedGuildModel.value?.key);
|
||||
}
|
||||
segmentationModel = segmentationModel.copyWith(
|
||||
productionDate: productionDate.value?.toDateTime().formattedDashedGregorian,
|
||||
);
|
||||
await safeCall(
|
||||
showError: true,
|
||||
call: () async => await rootLogic.chickenRepository.createSegmentation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
model: segmentationModel,
|
||||
),
|
||||
onSuccess: (result) async {
|
||||
res = true;
|
||||
isSubmitButtonEnabled.value = false;
|
||||
onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("قطعهبندی با موفقیت ثبت شد!"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
onError: (error, stacktrace) {
|
||||
res = false;
|
||||
},
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<void> getGuilds() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getGuilds(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(queryParams: {'all': true}, role: 'Steward'),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
guildsModel.clear();
|
||||
guildsModel.addAll(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
toggleExpansion();
|
||||
currentPage.value = 1;
|
||||
await rootLogic.onRefresh();
|
||||
await getAllSegmentation();
|
||||
await getBroadcastPrice();
|
||||
_updateFreeProductionDateData();
|
||||
_updateGovernmentalProductionDateData();
|
||||
}
|
||||
|
||||
Future<void> getBroadcastPrice() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getBroadcastPrice(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
broadcastPrice.value = result;
|
||||
if (broadcastPrice.value?.active == true) {
|
||||
priceType.value = 2;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/segmentation_model/segmentation_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/segmentation/widgets/cu_bottom_sheet.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<SegmentationLogic> {
|
||||
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(controller),
|
||||
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(),
|
||||
);
|
||||
|
||||
Row 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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container 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(controller, isOnEdit: 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,395 +0,0 @@
|
||||
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/presentation/pages/steward/segmentation/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
Widget addOrEditBottomSheet(SegmentationLogic controller, {bool isOnEdit = false}) {
|
||||
return BaseBottomSheet(
|
||||
height: isOnEdit ? 350.h : 600.h,
|
||||
child: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
isOnEdit ? 'ویرایش قطعهبندی' : 'افزودن قطعهبندی',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
_productDropDown(controller),
|
||||
Visibility(
|
||||
visible: isOnEdit == false,
|
||||
child: 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.quotaType.value = 1;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 1),
|
||||
Text('دولتی', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.quotaType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Obx(() {
|
||||
return MonthlyDataCalendar(
|
||||
label: 'تاریخ تولید گوشت',
|
||||
selectedDate: controller.productionDate.value?.formatCompactDate(),
|
||||
onDateSelect: (value) {
|
||||
controller.productionDate.value = value.date;
|
||||
controller.remainingStock.value = value.remainingStock;
|
||||
},
|
||||
dayData: controller.quotaType.value == 1
|
||||
? controller.governmentalProductionDateData
|
||||
: controller.freeProductionDateData,
|
||||
);
|
||||
}),
|
||||
|
||||
RTextField(
|
||||
controller: controller.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
autoValidateMode: AutovalidateMode.onUserInteraction,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
|
||||
validator: (value) {
|
||||
if ((int.tryParse(value?.clearComma ?? '0') ?? 0) >
|
||||
(controller.remainingStock.value ?? 0)) {
|
||||
return 'وزن تخصیصی بیشتر از موجودی انبار است';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (p0) {
|
||||
controller.weight.value = int.tryParse(p0.clearComma) ?? 0;
|
||||
},
|
||||
label: 'وزن لاشه (کیلوگرم)',
|
||||
),
|
||||
Visibility(
|
||||
visible: isOnEdit == false,
|
||||
child: Container(
|
||||
height: 58.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.priceType.value,
|
||||
onChanged: (value) {
|
||||
controller.priceType.value = value!;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: (controller.broadcastPrice.value?.active ?? false)
|
||||
? () {
|
||||
controller.priceType.value = 1;
|
||||
}
|
||||
: null,
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(
|
||||
value: 1,
|
||||
enabled: controller.broadcastPrice.value?.active ?? false,
|
||||
),
|
||||
Text(
|
||||
'قیمت مصوب',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: (controller.broadcastPrice.value?.active ?? false)
|
||||
? AppColor.textColor
|
||||
: AppColor.labelTextColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.priceType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('قیمت آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
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.priceType),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: data.value == 2,
|
||||
child: guildsDropDown(controller),
|
||||
);
|
||||
}, controller.segmentType),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
submitButtonWidget(controller, isOnEdit: isOnEdit),
|
||||
|
||||
SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget submitButtonWidget(SegmentationLogic controller, {bool isOnEdit = false}) {
|
||||
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(SegmentationLogic controller) {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<ProductModel>(
|
||||
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(),
|
||||
ObxValue((data) {
|
||||
return Visibility(visible: data.value != null, child: Text('موجودی: $data'));
|
||||
}, controller.remainingStock),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget guildsDropDown(SegmentationLogic controller) {
|
||||
return Obx(() {
|
||||
final item = controller.selectedGuildModel.value;
|
||||
return OverlayDropdownWidget<GuildModel>(
|
||||
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(SegmentationLogic controller, ValueChanged<Jalali> onDateSelected) {
|
||||
Jalali currentDate = Jalali.now();
|
||||
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,
|
||||
maximumDate: currentDate.addDays(3),
|
||||
minimumDate: currentDate.toDateTime().subtract(Duration(days: 1)).toString().toJalali,
|
||||
maximumYear: currentDate.year,
|
||||
minimumYear: currentDate.year,
|
||||
onDateTimeChanged: (dateTime) {
|
||||
tempPickedDate = dateTime;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
export 'buy/logic.dart';
|
||||
export 'buy/view.dart';
|
||||
export 'buy_in_province/logic.dart';
|
||||
export 'buy_in_province/view.dart';
|
||||
export 'buy_in_province_all/logic.dart';
|
||||
export 'buy_in_province_all/view.dart';
|
||||
export 'buy_in_province_waiting/logic.dart';
|
||||
export 'buy_in_province_waiting/view.dart';
|
||||
export 'buy_out_of_province/logic.dart';
|
||||
export 'buy_out_of_province/view.dart';
|
||||
export 'home/logic.dart';
|
||||
export 'home/view.dart';
|
||||
export 'root/logic.dart';
|
||||
export 'root/view.dart';
|
||||
export 'sale/logic.dart';
|
||||
export 'sale/view.dart';
|
||||
export 'sales_in_province/logic.dart';
|
||||
export 'sales_in_province/view.dart';
|
||||
export 'sales_out_of_province/logic.dart';
|
||||
export 'sales_out_of_province/view.dart';
|
||||
export 'sales_out_of_province_buyers/logic.dart';
|
||||
export 'sales_out_of_province_buyers/view.dart';
|
||||
export 'sales_out_of_province_sales_list/logic.dart';
|
||||
export 'sales_out_of_province_sales_list/view.dart';
|
||||
export 'segmentation/logic.dart';
|
||||
export 'segmentation/view.dart';
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/profile/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/common/profile/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class GlobalBinding extends Bindings {
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/auth/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/auth/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/role/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/role/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/action/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/action/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/root/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/submit_request/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/submit_request/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_farm_inspection/poultry_farm_inspection.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/active_hatching/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/farm/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/farm/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/genocide/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/genocide/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/killing_registration/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/killing_registration/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/poultry_action/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/poultry_action/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/poultry_science/root/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/steward/steward.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/kill_house/warehouse_and_distribution/warehouse_and_distribution.dart'
|
||||
import 'package:rasadyar_chicken/features/common/auth/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/common/auth/view.dart';
|
||||
import 'package:rasadyar_chicken/features/common/role/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/common/role/view.dart';
|
||||
import 'package:rasadyar_chicken/features/kill_house/action/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/kill_house/action/view.dart';
|
||||
import 'package:rasadyar_chicken/features/kill_house/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/kill_house/root/view.dart';
|
||||
import 'package:rasadyar_chicken/features/kill_house/submit_request/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/kill_house/submit_request/view.dart';
|
||||
import 'package:rasadyar_chicken/features/kill_house/warehouse_and_distribution/buy_in_province_entered/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_farm_inspection/poultry_farm_inspection.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/active_hatching/view.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/farm/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/farm/view.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/genocide/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/genocide/view.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/killing_registration/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/killing_registration/view.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/poultry_action/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/poultry_action/view.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/root/view.dart';
|
||||
import 'package:rasadyar_chicken/features/steward/steward.dart';
|
||||
import 'package:rasadyar_chicken/features/kill_house/warehouse_and_distribution/warehouse_and_distribution.dart'
|
||||
as warehouse;
|
||||
import 'package:rasadyar_chicken/presentation/routes/global_binding.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
@@ -408,7 +409,7 @@ sealed class ChickenPages {
|
||||
() => warehouse.WarehouseAndDistributionBuyInProvinceWaitingLogic(),
|
||||
);
|
||||
Get.lazyPut(
|
||||
() => warehouse.WarehouseAndDistributionBuyInProvinceAllLogic(),
|
||||
() => warehouse.WarehouseAndDistributionBuyInProvinceEnteredLogic(),
|
||||
);
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/pages/common/auth/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/common/auth/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user