Compare commits

10 Commits

Author SHA1 Message Date
b7b203ee51 refactor: update changeUserRole method to accept named parameters for improved clarity and modify ProfilePage to utilize new method signature 2025-12-30 09:40:15 +03:30
71123c3520 refactor: enhance AuthLogic to handle user roles and improve navigation based on role selection; format code for better readability in ProfilePage 2025-12-30 09:16:07 +03:30
9e2e7845c8 feat: integrate GService into various root logic classes and log user roles during initialization 2025-12-29 16:44:36 +03:30
4a96dbe2b8 chore: update app version to 1.9.0, change Flutter build mode to debug, and add changes field to app info model for update dialogs 2025-12-29 16:23:19 +03:30
b290094164 chore: update Flutter build mode to release and increment version number in pubspec.yaml to 1.9.0 2025-12-29 14:40:25 +03:30
f830e7d76d chore: update version number in pubspec.yaml to 1.3.43+39 2025-12-29 14:27:31 +03:30
9910de4ed8 feat: integrate city poultry feature by adding routes, DI setup, and updating UI components to reflect new data handling and localization changes 2025-12-29 14:26:12 +03:30
edde363b6d chore: change Flutter build mode to debug in local.properties, add strVersion observable in SplashLogic, and update splash view layout to display version information 2025-12-29 13:02:57 +03:30
ed113d8702 chore: change Flutter build mode from debug to release in local.properties 2025-12-29 12:07:20 +03:30
7d6be4f3f4 chore: update version number in pubspec.yaml and local.properties to 1.3.42+38 2025-12-29 11:38:51 +03:30
64 changed files with 2499 additions and 167 deletions

View File

@@ -1,5 +1,5 @@
sdk.dir=C:\\Users\\Housh11\\AppData\\Local\\Android\\sdk
flutter.sdk=C:\\src\\flutter
flutter.buildMode=debug
flutter.versionName=1.3.41
flutter.versionCode=37
flutter.versionName=1.3.43
flutter.versionCode=39

View File

@@ -0,0 +1,10 @@
<svg width="49" height="39" viewBox="0 0 49 39" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.4876 30.2057C24.5116 30.2057 30.2057 24.5116 30.2057 17.4876C30.2057 10.4636 24.5116 4.76953 17.4876 4.76953C10.4636 4.76953 4.76953 10.4636 4.76953 17.4876C4.76953 24.5116 10.4636 30.2057 17.4876 30.2057Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M33.3852 33.3842L26.4697 26.4688" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M24.0771 14.8029C23.0086 13.7947 21.8333 14.4501 20.9292 15.1325C20.1072 15.7413 19.0757 15.8847 18.7963 15.7878C18.5538 15.5552 18.3853 14.6556 18.2292 13.9925C18.0155 12.965 17.7442 11.6194 16.9511 10.6966L16.9799 10.6656C17.0471 10.5856 17.0969 10.494 17.1265 10.3959C17.1562 10.2977 17.1651 10.1951 17.1527 10.0937C17.1403 9.99234 17.1068 9.89428 17.0543 9.80512C17.0017 9.71596 16.931 9.63743 16.8463 9.57404C16.7616 9.51064 16.6644 9.46361 16.5605 9.43564C16.4565 9.40766 16.3476 9.39928 16.2402 9.41098C16.1328 9.42269 16.0289 9.45424 15.9344 9.50384C15.8399 9.55344 15.7567 9.62011 15.6895 9.70006V9.53332C15.6895 9.32764 15.6029 9.13039 15.4487 8.98495C15.2946 8.83952 15.0855 8.75781 14.8676 8.75781C14.6496 8.75781 14.4405 8.83952 14.2864 8.98495C14.1322 9.13039 14.0456 9.32764 14.0456 9.53332V9.68455L14.0004 9.62638C13.868 9.46287 13.6722 9.35569 13.456 9.32842C13.2398 9.30115 13.021 9.35603 12.8477 9.48097C12.6744 9.60592 12.5608 9.79071 12.5319 9.99469C12.503 10.1987 12.5612 10.4051 12.6936 10.5686L12.7224 10.6035C12.5089 10.8628 12.3486 11.1573 12.2498 11.4721H11.9909C11.7729 11.4721 11.5638 11.5538 11.4097 11.6992C11.2555 11.8447 11.1689 12.0419 11.1689 12.2476C11.1689 12.4533 11.2555 12.6505 11.4097 12.796C11.5638 12.9414 11.7729 13.0231 11.9909 13.0231H12.6977C13.1456 13.4419 13.7785 13.8529 13.7785 14.357C13.7785 14.5664 13.5771 14.8107 13.2484 15.1907C12.3301 16.1026 11.8207 17.314 11.8265 18.5719C11.8265 20.8984 13.3552 22.019 14.8347 23.0931C15.9977 23.9384 16.573 24.5899 17.7442 24.8613V26.2068H17.3333C17.1153 26.2068 16.9062 26.2885 16.7521 26.4339C16.598 26.5794 16.5114 26.7766 16.5114 26.9823C16.5114 27.188 16.598 27.3852 16.7521 27.5307C16.9062 27.6761 17.1153 27.7578 17.3333 27.7578H19.3881C19.6061 27.7578 19.8151 27.6761 19.9692 27.5307C20.1234 27.3852 20.21 27.188 20.21 26.9823C20.21 26.7766 20.1234 26.5794 19.9692 26.4339C19.8151 26.2885 19.6061 26.2068 19.3881 26.2068V24.8458C20.4902 24.6063 21.4789 24.0329 22.2031 23.2133C23.6785 21.3599 23.5305 21.0148 24.2579 20.2974C24.6334 19.9627 24.9157 19.5459 25.0798 19.0837C25.3962 18.2501 24.825 15.5047 24.0771 14.8029ZM23.5346 18.6068C23.4449 18.8468 23.2905 19.0606 23.0867 19.2272C22.7339 19.5461 22.4419 19.9199 22.2237 20.3323C21.8341 21.0174 21.3875 21.6721 20.8881 22.2905C20.5892 22.6159 20.2252 22.8825 19.8168 23.0748C19.4085 23.2671 18.9639 23.3814 18.5086 23.4111C17.5963 23.4111 17.0374 22.7403 15.8415 21.8601C14.4689 20.8596 13.4744 20.1384 13.4744 18.5641C13.4747 17.6661 13.8514 16.8047 14.5223 16.1678C14.9662 15.656 15.4265 15.1286 15.4265 14.3531C15.4265 13.2635 14.6045 12.5733 14.0867 12.1196C14.0045 12.0499 13.9018 11.9607 13.8278 11.8947C13.87 11.7237 13.9674 11.5692 14.1065 11.4526C14.2456 11.3359 14.4196 11.2628 14.6045 11.2433C15.7963 11.2433 16.1744 12.1429 16.6182 14.2911C16.8566 15.4543 17.0621 16.447 17.7648 17.0054C18.7264 17.7615 20.7442 17.2652 21.9565 16.3501C22.6059 15.8615 22.8606 15.8537 22.9017 15.8886C23.1976 16.2415 23.6415 18.1376 23.5346 18.6029V18.6068Z" fill="white"/>
<path d="M19.128 19.1849C18.9796 19.3766 18.8011 19.4699 18.6209 19.4501C18.0798 19.4501 17.3842 18.4182 17.2017 18.055C17.0839 17.8567 16.9297 17.7504 16.771 17.7582C16.6123 17.766 16.4613 17.8873 16.3493 18.0969C16.2372 18.3066 16.1727 18.5886 16.1691 18.8844C16.1655 19.1803 16.223 19.4675 16.3298 19.6865C16.4566 19.8998 17.4707 21.756 18.6209 21.756C19.1215 21.7853 19.6091 21.4575 19.9845 20.8394C20.0429 20.7321 20.0893 20.6043 20.121 20.4632C20.1526 20.3222 20.1689 20.1708 20.1689 20.0179C20.1689 19.865 20.1526 19.7137 20.121 19.5726C20.0893 19.4316 20.0429 19.3037 19.9845 19.1964C19.8701 18.9888 19.7171 18.8716 19.5575 18.8695C19.3978 18.8673 19.244 18.9804 19.128 19.1849Z" fill="white"/>
<path d="M44.5688 28.3654H37.9374C35.434 28.3654 34 26.8065 34 24.0853V15.2997C34 12.4613 35.3263 11.0195 37.9374 11.0195C38.2773 11.0195 38.5591 11.3259 38.5591 11.6953C38.5591 12.0558 38.6917 12.3982 38.9238 12.6505C39.1559 12.9028 39.4709 13.047 39.8025 13.047H42.7037C43.3918 13.047 43.9471 12.4432 43.9471 11.6953C43.9471 11.3259 44.229 11.0195 44.5688 11.0195C47.1799 11.0195 48.5062 12.4613 48.5062 15.2997V24.0853C48.5062 26.8065 47.0722 28.3654 44.5688 28.3654ZM37.3986 12.3892C36.0889 12.5063 35.2434 13.1461 35.2434 15.2997V24.0853C35.2434 26.0857 36.0972 27.0138 37.9374 27.0138H44.5688C46.409 27.0138 47.2628 26.0857 47.2628 24.0853V15.2997C47.2628 13.1461 46.4174 12.5153 45.1077 12.3892C44.8258 13.5426 43.8559 14.3986 42.7037 14.3986H39.8025C39.1394 14.3986 38.5177 14.1193 38.0452 13.6056C37.7302 13.2632 37.5146 12.8487 37.3986 12.3892Z" fill="white" stroke="white" stroke-width="0.25"/>
<path d="M42.7039 14.4065H39.8027C39.1396 14.4065 38.5179 14.1272 38.0454 13.6136C37.5729 13.0999 37.3159 12.4241 37.3159 11.7033C37.3159 10.2165 38.435 9 39.8027 9H42.7039C43.3671 9 43.9888 9.27934 44.4613 9.79296C44.9338 10.3066 45.1907 10.9824 45.1907 11.7033C45.1907 13.19 44.0717 14.4065 42.7039 14.4065ZM39.8027 10.3516C39.1147 10.3516 38.5593 10.9554 38.5593 11.7033C38.5593 12.0637 38.6919 12.4061 38.924 12.6584C39.1561 12.9107 39.4711 13.0549 39.8027 13.0549H42.7039C43.392 13.0549 43.9473 12.4512 43.9473 11.7033C43.9473 11.3428 43.8147 11.0004 43.5826 10.7481C43.3505 10.4958 43.0355 10.3516 42.7039 10.3516H39.8027Z" fill="white"/>
<path d="M41.2533 20.2501H37.9376C37.5978 20.2501 37.3159 19.9437 37.3159 19.5743C37.3159 19.2048 37.5978 18.8984 37.9376 18.8984H41.2533C41.5932 18.8984 41.875 19.2048 41.875 19.5743C41.875 19.9437 41.5932 20.2501 41.2533 20.2501Z" fill="white"/>
<path d="M44.569 23.8555H37.9376C37.5978 23.8555 37.3159 23.5492 37.3159 23.1797C37.3159 22.8103 37.5978 22.5039 37.9376 22.5039H44.569C44.9089 22.5039 45.1907 22.8103 45.1907 23.1797C45.1907 23.5492 44.9089 23.8555 44.569 23.8555Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

View File

@@ -19,6 +19,7 @@ abstract class Info with _$Info {
String? minVersion,
String? module,
bool? required,
List<String>? changes,
}) = _Info;
factory Info.fromJson(Map<String, dynamic> json) => _$InfoFromJson(json);

View File

@@ -308,7 +308,7 @@ $InfoCopyWith<$Res>? get info {
/// @nodoc
mixin _$Info {
String? get version; String? get minVersion; String? get module; bool? get required;
String? get version; String? get minVersion; String? get module; bool? get required; List<String>? get changes;
/// Create a copy of Info
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -321,16 +321,16 @@ $InfoCopyWith<Info> get copyWith => _$InfoCopyWithImpl<Info>(this as Info, _$ide
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is Info&&(identical(other.version, version) || other.version == version)&&(identical(other.minVersion, minVersion) || other.minVersion == minVersion)&&(identical(other.module, module) || other.module == module)&&(identical(other.required, required) || other.required == required));
return identical(this, other) || (other.runtimeType == runtimeType&&other is Info&&(identical(other.version, version) || other.version == version)&&(identical(other.minVersion, minVersion) || other.minVersion == minVersion)&&(identical(other.module, module) || other.module == module)&&(identical(other.required, required) || other.required == required)&&const DeepCollectionEquality().equals(other.changes, changes));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,version,minVersion,module,required);
int get hashCode => Object.hash(runtimeType,version,minVersion,module,required,const DeepCollectionEquality().hash(changes));
@override
String toString() {
return 'Info(version: $version, minVersion: $minVersion, module: $module, required: $required)';
return 'Info(version: $version, minVersion: $minVersion, module: $module, required: $required, changes: $changes)';
}
@@ -341,7 +341,7 @@ abstract mixin class $InfoCopyWith<$Res> {
factory $InfoCopyWith(Info value, $Res Function(Info) _then) = _$InfoCopyWithImpl;
@useResult
$Res call({
String? version, String? minVersion, String? module, bool? required
String? version, String? minVersion, String? module, bool? required, List<String>? changes
});
@@ -358,13 +358,14 @@ class _$InfoCopyWithImpl<$Res>
/// Create a copy of Info
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? version = freezed,Object? minVersion = freezed,Object? module = freezed,Object? required = freezed,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? version = freezed,Object? minVersion = freezed,Object? module = freezed,Object? required = freezed,Object? changes = freezed,}) {
return _then(_self.copyWith(
version: freezed == version ? _self.version : version // ignore: cast_nullable_to_non_nullable
as String?,minVersion: freezed == minVersion ? _self.minVersion : minVersion // ignore: cast_nullable_to_non_nullable
as String?,module: freezed == module ? _self.module : module // ignore: cast_nullable_to_non_nullable
as String?,required: freezed == required ? _self.required : required // ignore: cast_nullable_to_non_nullable
as bool?,
as bool?,changes: freezed == changes ? _self.changes : changes // ignore: cast_nullable_to_non_nullable
as List<String>?,
));
}
@@ -449,10 +450,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? version, String? minVersion, String? module, bool? required)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? version, String? minVersion, String? module, bool? required, List<String>? changes)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Info() when $default != null:
return $default(_that.version,_that.minVersion,_that.module,_that.required);case _:
return $default(_that.version,_that.minVersion,_that.module,_that.required,_that.changes);case _:
return orElse();
}
@@ -470,10 +471,10 @@ return $default(_that.version,_that.minVersion,_that.module,_that.required);case
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? version, String? minVersion, String? module, bool? required) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? version, String? minVersion, String? module, bool? required, List<String>? changes) $default,) {final _that = this;
switch (_that) {
case _Info():
return $default(_that.version,_that.minVersion,_that.module,_that.required);case _:
return $default(_that.version,_that.minVersion,_that.module,_that.required,_that.changes);case _:
throw StateError('Unexpected subclass');
}
@@ -490,10 +491,10 @@ return $default(_that.version,_that.minVersion,_that.module,_that.required);case
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? version, String? minVersion, String? module, bool? required)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? version, String? minVersion, String? module, bool? required, List<String>? changes)? $default,) {final _that = this;
switch (_that) {
case _Info() when $default != null:
return $default(_that.version,_that.minVersion,_that.module,_that.required);case _:
return $default(_that.version,_that.minVersion,_that.module,_that.required,_that.changes);case _:
return null;
}
@@ -505,13 +506,22 @@ return $default(_that.version,_that.minVersion,_that.module,_that.required);case
@JsonSerializable()
class _Info implements Info {
const _Info({this.version, this.minVersion, this.module, this.required});
const _Info({this.version, this.minVersion, this.module, this.required, final List<String>? changes}): _changes = changes;
factory _Info.fromJson(Map<String, dynamic> json) => _$InfoFromJson(json);
@override final String? version;
@override final String? minVersion;
@override final String? module;
@override final bool? required;
final List<String>? _changes;
@override List<String>? get changes {
final value = _changes;
if (value == null) return null;
if (_changes is EqualUnmodifiableListView) return _changes;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value);
}
/// Create a copy of Info
/// with the given fields replaced by the non-null parameter values.
@@ -526,16 +536,16 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Info&&(identical(other.version, version) || other.version == version)&&(identical(other.minVersion, minVersion) || other.minVersion == minVersion)&&(identical(other.module, module) || other.module == module)&&(identical(other.required, required) || other.required == required));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Info&&(identical(other.version, version) || other.version == version)&&(identical(other.minVersion, minVersion) || other.minVersion == minVersion)&&(identical(other.module, module) || other.module == module)&&(identical(other.required, required) || other.required == required)&&const DeepCollectionEquality().equals(other._changes, _changes));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,version,minVersion,module,required);
int get hashCode => Object.hash(runtimeType,version,minVersion,module,required,const DeepCollectionEquality().hash(_changes));
@override
String toString() {
return 'Info(version: $version, minVersion: $minVersion, module: $module, required: $required)';
return 'Info(version: $version, minVersion: $minVersion, module: $module, required: $required, changes: $changes)';
}
@@ -546,7 +556,7 @@ abstract mixin class _$InfoCopyWith<$Res> implements $InfoCopyWith<$Res> {
factory _$InfoCopyWith(_Info value, $Res Function(_Info) _then) = __$InfoCopyWithImpl;
@override @useResult
$Res call({
String? version, String? minVersion, String? module, bool? required
String? version, String? minVersion, String? module, bool? required, List<String>? changes
});
@@ -563,13 +573,14 @@ class __$InfoCopyWithImpl<$Res>
/// Create a copy of Info
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? version = freezed,Object? minVersion = freezed,Object? module = freezed,Object? required = freezed,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? version = freezed,Object? minVersion = freezed,Object? module = freezed,Object? required = freezed,Object? changes = freezed,}) {
return _then(_Info(
version: freezed == version ? _self.version : version // ignore: cast_nullable_to_non_nullable
as String?,minVersion: freezed == minVersion ? _self.minVersion : minVersion // ignore: cast_nullable_to_non_nullable
as String?,module: freezed == module ? _self.module : module // ignore: cast_nullable_to_non_nullable
as String?,required: freezed == required ? _self.required : required // ignore: cast_nullable_to_non_nullable
as bool?,
as bool?,changes: freezed == changes ? _self._changes : changes // ignore: cast_nullable_to_non_nullable
as List<String>?,
));
}

View File

@@ -27,6 +27,9 @@ _Info _$InfoFromJson(Map<String, dynamic> json) => _Info(
minVersion: json['minVersion'] as String?,
module: json['module'] as String?,
required: json['required'] as bool?,
changes: (json['changes'] as List<dynamic>?)
?.map((e) => e as String)
.toList(),
);
Map<String, dynamic> _$InfoToJson(_Info instance) => <String, dynamic>{
@@ -34,4 +37,5 @@ Map<String, dynamic> _$InfoToJson(_Info instance) => <String, dynamic>{
'minVersion': instance.minVersion,
'module': instance.module,
'required': instance.required,
'changes': instance.changes,
};

View File

@@ -14,6 +14,7 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
RxBool hasUpdated = false.obs;
RxBool onUpdateDownload = false.obs;
RxDouble percent = 0.0.obs;
RxString strVersion = ''.obs;
final RxnString _updateFilePath = RxnString();
final platform = MethodChannel('apk_installer');
final Dio _dio = Dio();
@@ -69,6 +70,7 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
onConfirm: () async {
await fileDownload();
},
changes: appInfoModel?.info?.changes,
);
} else if (!data && Get.isDialogOpen == true) {
Get.back();
@@ -170,8 +172,6 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
if (target != null) {
var mFuns = getFunctionsList(target.functions);
await Future.wait(mFuns ?? []);
iLog("target.route ===>${target.route!}");
Get.offAndToNamed(target.route!);
}
} catch (e, st) {
@@ -190,7 +190,9 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
Future<bool> checkVersion() async {
try {
final info = await PackageInfo.fromPlatform();
int version = info.version.versionNumber;
strVersion.value = info.version;
int version = strVersion.value.versionNumber;
var res = await _dio.get(
"https://rsibackend.rasadyar.com/app/rasadyar-app-info/",
);

View File

@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'logic.dart';
class SplashPage extends GetView<SplashLogic> {
@@ -11,36 +10,51 @@ class SplashPage extends GetView<SplashLogic> {
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.blueDarker,
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Spacer(),
Center(
child: Stack(
alignment: Alignment.center,
children: [
ObxValue((data) {
return ScaleTransition(
scale: data.value!,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 1),
child: Assets.images.innerSplash.image(
width: 190,
height: 190,
),
),
);
}, controller.scaleAnimation),
ObxValue((data) {
return ScaleTransition(
scale: data.value!,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 1),
child: Assets.images.innerSplash.image(
width: 190,
height: 190,
)
),
);
}, controller.scaleAnimation),
ObxValue((data) {
return RotationTransition(
turns: data.value!,
ObxValue((data) {
return RotationTransition(
turns: data.value!,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 1),
child: Assets.images.outterSplash.image()
),
);
}, controller.rotationAnimation),
],
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 1),
child: Assets.images.outterSplash.image(),
),
);
}, controller.rotationAnimation),
],
),
),
Spacer(),
ObxValue((data) {
return Text(
data.value,
style: AppFonts.yekan16.copyWith(
color: Colors.white.withAlpha(120),
),
);
}, controller.strVersion),
SizedBox(height: 30.h),
],
),
);
}

View File

@@ -1,4 +1,5 @@
import 'package:rasadyar_chicken/features/city_jahad/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/features/poultry_science/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/features/province_inspector/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/features/province_operator/presentation/routes/routes.dart';
@@ -149,7 +150,7 @@ Map<String, String?> getFaUserRoleWithOnTap(String? role) {
case "Dispenser":
return {"پخش کننده": null};
case "CityPoultry":
return {"طیور شهرستان": null};
return {"طیور شهرستان": CityPoultryRoutes.initCityPoultry};
case "ParentCompany":
return {"شرکت مادر": null};
case "ColdHouseSteward":

View File

@@ -10,6 +10,7 @@ import 'package:rasadyar_chicken/features/steward/data/di/steward_di.dart';
import 'package:rasadyar_chicken/features/province_operator/data/di/province_operator_di.dart';
import 'package:rasadyar_chicken/features/province_inspector/data/di/province_inspector_di.dart';
import 'package:rasadyar_chicken/features/city_jahad/data/di/city_jahad_di.dart';
import 'package:rasadyar_chicken/features/city_poultry/data/di/city_poultry_di.dart';
import 'package:rasadyar_chicken/features/vet_farm/data/di/vet_farm_di.dart';
import 'package:rasadyar_chicken/features/super_admin/data/di/super_admin_di.dart';
import 'package:rasadyar_chicken/features/province_supervisor/data/di/province_supervisor_di.dart';
@@ -74,6 +75,9 @@ Future<void> setupChickenDI() async {
// Setup city_jahad feature DI
await setupCityJahadDI(diChicken, dioRemote);
// Setup city_poultry feature DI
await setupCityPoultryDI(diChicken, dioRemote);
// Setup vet_farm feature DI
await setupVetFarmDI(diChicken, dioRemote);
@@ -138,6 +142,7 @@ Future<void> newSetupAuthDI(String newUrl) async {
await setupProvinceOperatorDI(diChicken, dioRemote);
await setupProvinceInspectorDI(diChicken, dioRemote);
await setupCityJahadDI(diChicken, dioRemote);
await setupCityPoultryDI(diChicken, dioRemote);
await setupVetFarmDI(diChicken, dioRemote);
await setupSuperAdminDI(diChicken, dioRemote);
await setupProvinceSupervisorDI(diChicken, dioRemote);

View File

@@ -193,12 +193,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
spacing: 3,
children: [
Text(
item.poultry?.user?.fullname ?? 'N/A',
item.poultry?.user?.fullname ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
Text(
item.poultry?.user?.mobile ?? 'N/A',
item.poultry?.user?.mobile ?? 'ندارد',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
@@ -213,12 +213,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
item.poultry?.unitName ?? 'N/A',
item.poultry?.unitName ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
item.poultry?.licenceNumber ?? 'N/A',
item.licenceNumber ?? 'ندارد',
textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),

View File

@@ -23,7 +23,7 @@ class CityJahadHomeLogic extends GetxController {
CityJahadActionItem(
title: "بازرسی مزارع طیور",
route: CityJahadRoutes.newInspectionCityJahad,
icon: Assets.vec.activeFramSvg.path,
icon: Assets.vec.inspectionPoultrySvg.path,
),
].obs;
}

View File

@@ -14,6 +14,7 @@ enum ErrorLocationType { serviceDisabled, permissionDenied, none }
class CityJahadRootLogic extends GetxController {
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late CityJahadRepository cityJahadRepository;
@@ -45,6 +46,7 @@ class CityJahadRootLogic extends GetxController {
void onInit() {
super.onInit();
cityJahadRepository = diChicken.get<CityJahadRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
void toggleExpanded(int index) {

View File

@@ -0,0 +1,4 @@
export 'data/di/city_poultry_di.dart';
export 'presentation/routes/routes.dart';
export 'presentation/routes/pages.dart';

View File

@@ -0,0 +1,16 @@
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
import 'package:rasadyar_core/core.dart';
abstract class CityPoultryRemoteDataSource {
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
required String token,
Map<String, dynamic>? queryParameters,
});
Future<void> submitInspection({
required String token,
required SubmitInspectionResponse request,
});
}

View File

@@ -0,0 +1,40 @@
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
import 'package:rasadyar_chicken/features/city_poultry/data/datasources/remote/city_poultry_remote_data_source.dart';
import 'package:rasadyar_core/core.dart';
class CityPoultryRemoteDataSourceImpl implements CityPoultryRemoteDataSource {
final DioRemote _httpClient;
CityPoultryRemoteDataSourceImpl(this._httpClient);
@override
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
required String token,
Map<String, dynamic>? queryParameters,
}) async {
var res = await _httpClient.get(
'/poultry_science_report/',
headers: {'Authorization': 'Bearer $token'},
queryParameters: queryParameters,
fromJson: (json) => PaginationModel<PoultryScienceReport>.fromJson(
json,
(json) => PoultryScienceReport.fromJson(json as Map<String, dynamic>),
),
);
return res.data;
}
@override
Future<void> submitInspection({
required String token,
required SubmitInspectionResponse request,
}) async {
await _httpClient.post(
'/poultry_science_report/',
headers: {'Authorization': 'Bearer $token'},
data: request.toJson(),
);
}
}

View File

@@ -0,0 +1,36 @@
import 'package:rasadyar_chicken/features/city_poultry/data/datasources/remote/city_poultry_remote_data_source.dart';
import 'package:rasadyar_chicken/features/city_poultry/data/datasources/remote/city_poultry_remote_data_source_impl.dart';
import 'package:rasadyar_chicken/features/city_poultry/data/repositories/city_poultry_repository.dart';
import 'package:rasadyar_chicken/features/city_poultry/data/repositories/city_poultry_repository_impl.dart';
import 'package:rasadyar_core/core.dart';
/// Setup dependency injection for city_poultry feature
Future<void> setupCityPoultryDI(GetIt di, DioRemote dioRemote) async {
di.registerLazySingleton<CityPoultryRemoteDataSource>(
() => CityPoultryRemoteDataSourceImpl(dioRemote),
);
di.registerLazySingleton<CityPoultryRepository>(
() => CityPoultryRepositoryImpl(di.get<CityPoultryRemoteDataSource>()),
);
}
/// Re-register city_poultry dependencies (used when base URL changes)
Future<void> reRegisterCityPoultryDI(GetIt di, DioRemote dioRemote) async {
await reRegister(di, () => CityPoultryRemoteDataSourceImpl(dioRemote));
await reRegister(
di,
() => CityPoultryRepositoryImpl(di.get<CityPoultryRemoteDataSource>()),
);
}
/// Helper function to re-register a dependency
Future<void> reRegister<T extends Object>(
GetIt di,
T Function() factory,
) async {
if (di.isRegistered<T>()) {
await di.unregister<T>();
}
di.registerLazySingleton<T>(factory);
}

View File

@@ -0,0 +1,16 @@
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
import 'package:rasadyar_core/core.dart';
abstract class CityPoultryRepository {
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
required String token,
Map<String, dynamic>? queryParameters,
});
Future<void> submitInspection({
required String token,
required SubmitInspectionResponse request,
});
}

View File

@@ -0,0 +1,31 @@
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
import 'package:rasadyar_chicken/features/city_poultry/data/datasources/remote/city_poultry_remote_data_source.dart';
import 'package:rasadyar_chicken/features/city_poultry/data/repositories/city_poultry_repository.dart';
import 'package:rasadyar_core/core.dart';
class CityPoultryRepositoryImpl implements CityPoultryRepository {
final CityPoultryRemoteDataSource _remote;
CityPoultryRepositoryImpl(this._remote);
@override
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
required String token,
Map<String, dynamic>? queryParameters,
}) async {
return await _remote.getSubmitInspectionList(
token: token,
queryParameters: queryParameters,
);
}
@override
Future<void> submitInspection({
required String token,
required SubmitInspectionResponse request,
}) async {
return await _remote.submitInspection(token: token, request: request);
}
}

View File

@@ -0,0 +1,101 @@
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/hatching/hatching_models.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/repositories/poultry_science_repository.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/root/logic.dart';
import 'package:rasadyar_core/core.dart';
class ActiveHatchingLogic extends GetxController {
CityPoultryRootLogic rootLogic = Get.find<CityPoultryRootLogic>();
BaseLogic baseLogic = Get.find<BaseLogic>();
late PoultryScienceRepository poultryScienceRepository;
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 onInit() {
super.onInit();
poultryScienceRepository = diChicken.get<PoultryScienceRepository>();
}
@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 poultryScienceRepository.getHatchingPoultry(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
queryParams: {'type': 'hatching'},
role: 'CityPoultry',
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();
}
}

View File

@@ -0,0 +1,236 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/hatching/hatching_models.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/active_hatching/logic.dart';
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet.dart';
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet_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: cityPoultryActionKey,
routes: controller.routesName,
onSearchChanged: (data) {
controller.searchedValue.value = data;
controller.getHatchingList();
},
child: 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,
),
),
RElevated(
height: 40.h,
isFullWidth: true,
onPressed: () {
Get.find<CreateInspectionBottomSheetLogic>().setHatchingModel(
item,
);
Get.bottomSheet(
CreateInspectionBottomSheet(),
isScrollControlled: true,
ignoreSafeArea: false,
).then((value) {
if (Get.isRegistered<CreateInspectionBottomSheetLogic>()) {
Get.find<CreateInspectionBottomSheetLogic>().clearForm();
}
});
},
child: Text('ثبت بازرسی'),
),
],
),
);
}
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 ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
Text(
item.poultry?.user?.mobile ?? 'ندارد',
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 ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
item.licenceNumber ?? 'ندارد',
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),
),
),
],
);
}
}

View File

@@ -0,0 +1,29 @@
import 'package:rasadyar_chicken/features/city_poultry/presentation/routes/routes.dart';
import 'package:rasadyar_core/core.dart';
class CityPoultryActionItem {
final String title;
final String route;
final String icon;
CityPoultryActionItem({
required this.title,
required this.route,
required this.icon,
});
}
class CityPoultryHomeLogic extends GetxController {
RxList<CityPoultryActionItem> items = [
CityPoultryActionItem(
title: "جوجه ریزی فعال",
route: CityPoultryRoutes.activeHatchingCityPoultry,
icon: Assets.vec.activeFramSvg.path,
),
CityPoultryActionItem(
title: "بازرسی مزارع طیور",
route: CityPoultryRoutes.newInspectionCityPoultry,
icon: Assets.vec.inspectionPoultrySvg.path,
),
].obs;
}

View File

@@ -0,0 +1,47 @@
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 CityPoultryHomePage extends GetView<CityPoultryHomeLogic> {
CityPoultryHomePage({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: cityPoultryActionKey);
},
);
},
);
}, controller.items);
}
}

View File

@@ -0,0 +1,160 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/root/logic.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
import 'package:rasadyar_core/core.dart';
class NewInspectionLogic extends GetxController {
BaseLogic baseLogic = Get.find<BaseLogic>();
Rx<Resource<PaginationModel<PoultryScienceReport>>> submitInspectionList =
Resource<PaginationModel<PoultryScienceReport>>.loading().obs;
CityPoultryRootLogic rootLogic = Get.find<CityPoultryRootLogic>();
final RxBool isLoadingMoreAllocationsMade = false.obs;
RxInt currentPage = 1.obs;
RxInt expandedIndex = RxInt(-1);
RxList<XFile> pickedImages = <XFile>[].obs;
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();
getReport();
}
@override
void onClose() {
super.onClose();
baseLogic.clearSearch();
}
Future<void> getReport([bool isLoadingMore = false]) async {
if (isLoadingMore) {
isLoadingMoreAllocationsMade.value = true;
} else {
submitInspectionList.value =
Resource<PaginationModel<PoultryScienceReport>>.loading();
}
if (searchedValue.value != null &&
searchedValue.value!.trim().isNotEmpty &&
currentPage.value > 1) {
currentPage.value = 1;
}
safeCall(
call: () async =>
await rootLogic.cityPoultryRepository.getSubmitInspectionList(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
role: 'CityPoultry',
pageSize: 50,
search: 'filter',
page: currentPage.value,
),
),
onSuccess: (res) {
if ((res?.count ?? 0) == 0) {
submitInspectionList.value =
Resource<PaginationModel<PoultryScienceReport>>.empty();
} else {
submitInspectionList.value =
Resource<PaginationModel<PoultryScienceReport>>.success(
PaginationModel<PoultryScienceReport>(
count: res?.count ?? 0,
next: res?.next,
previous: res?.previous,
results: [
...(submitInspectionList.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 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;
}
void setSearchValue(String? data) {
dLog('Search Value: $data');
searchedValue.value = data?.trim();
getReport();
}
Future<void> onRefresh() async {
currentPage.value = 1;
await getReport();
}
String getStatus(PoultryScienceReport item) {
final status = item.reportInformation?.inspectionStatus ?? item.state;
if (status == null || status.isEmpty) {
return 'در حال بررسی';
}
return status;
}
Color getStatusColor(PoultryScienceReport item) {
final status = item.reportInformation?.inspectionStatus ?? item.state;
if (status == null || status.isEmpty) {
return AppColor.yellowNormal;
}
// می‌توانید منطق رنگ را بر اساس inspectionStatus تنظیم کنید
return AppColor.greenNormal;
}
}

View File

@@ -0,0 +1,100 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
import 'package:rasadyar_chicken/features/city_poultry/data/repositories/city_poultry_repository.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/routes/pages.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/features/common/presentation/page/profile/view.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 CityPoultryRootLogic extends GetxController {
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late CityPoultryRepository cityPoultryRepository;
RxList<ErrorLocationType> errorLocationType = RxList();
RxMap<int, dynamic> homeExpandedList = RxMap();
DateTime? _lastBackPressed;
RxInt currentPage = 0.obs;
final pages = [
Navigator(
key: Get.nestedKey(cityPoultryActionKey),
onGenerateRoute: (settings) {
final page = CityPoultryPages.pages.firstWhere(
(e) => e.name == settings.name,
orElse: () => CityPoultryPages.pages.firstWhere(
(e) => e.name == CityPoultryRoutes.homeCityPoultry,
),
);
return buildRouteFromGetPage(page);
},
),
ProfilePage(),
];
@override
void onInit() {
super.onInit();
cityPoultryRepository = diChicken.get<CityPoultryRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
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;
}
void popBackTaped() async {
final nestedKey = Get.nestedKey(cityPoultryActionKey);
final currentRoute = Get.routing.current;
final isInternalRoute =
currentRoute == CityPoultryRoutes.activeHatchingCityPoultry ||
currentRoute == CityPoultryRoutes.newInspectionCityPoultry ||
currentRoute == CityPoultryRoutes.actionCityPoultry;
if (isInternalRoute) {
Get.back(id: cityPoultryActionKey);
return;
}
// اگر در صفحه home هستیم، منطق خروج از اپ را اجرا کن
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();
}
}
}

View File

@@ -0,0 +1,59 @@
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 CityPoultryRootPage extends GetView<CityPoultryRootLogic> {
const CityPoultryRootPage({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.homeSvg.path,
isSelected: controller.currentPage.value == 0,
onTap: () {
Get.nestedKey(
cityPoultryActionKey,
)?.currentState?.popUntil((route) => route.isFirst);
controller.changePage(0);
},
),
RBottomNavigationItem(
label: 'پروفایل',
icon: Assets.vec.profileCircleSvg.path,
isSelected: controller.currentPage.value == 1,
onTap: () {
Get.nestedKey(
cityPoultryActionKey,
)?.currentState?.popUntil((route) => route.isFirst);
controller.changePage(1);
},
),
],
),
),
],
);
}, controller.currentPage),
);
}
}

View File

@@ -0,0 +1,67 @@
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/home/logic.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/home/view.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/root/logic.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/root/view.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/active_hatching/logic.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/active_hatching/view.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/new_inspection/logic.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/pages/new_inspection/view.dart';
import 'package:rasadyar_chicken/features/city_poultry/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet_logic.dart';
import 'package:rasadyar_chicken/presentation/routes/global_binding.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
import 'package:rasadyar_core/core.dart';
class CityPoultryPages {
CityPoultryPages._();
static List<GetPage> get pages => [
GetPage(
name: CityPoultryRoutes.initCityPoultry,
page: () => CityPoultryRootPage(),
middlewares: [AuthMiddleware()],
bindings: [
GlobalBinding(),
BindingsBuilder(() {
Get.lazyPut(() => ChickenBaseLogic(), fenix: true);
Get.lazyPut(() => CityPoultryRootLogic());
Get.lazyPut(() => CityPoultryHomeLogic());
}),
],
),
GetPage(
name: CityPoultryRoutes.homeCityPoultry,
page: () => CityPoultryHomePage(),
middlewares: [AuthMiddleware()],
binding: BindingsBuilder(() {
Get.put(CityPoultryHomeLogic());
Get.lazyPut(() => ChickenBaseLogic());
}),
),
GetPage(
name: CityPoultryRoutes.activeHatchingCityPoultry,
page: () => ActiveHatchingPage(),
middlewares: [AuthMiddleware()],
bindings: [
GlobalBinding(),
BindingsBuilder(() {
Get.lazyPut(() => ActiveHatchingLogic());
Get.lazyPut(() => CreateInspectionBottomSheetLogic());
}),
],
),
GetPage(
name: CityPoultryRoutes.newInspectionCityPoultry,
page: () => NewInspectionPage(),
middlewares: [AuthMiddleware()],
bindings: [
GlobalBinding(),
BindingsBuilder(() {
Get.lazyPut(() => NewInspectionLogic());
}),
],
),
];
}

View File

@@ -0,0 +1,11 @@
sealed class CityPoultryRoutes {
CityPoultryRoutes._();
static const _base = '/chicken/cityPoultry';
static const initCityPoultry = '$_base/';
static const homeCityPoultry = '$_base/home';
static const actionCityPoultry = '$_base/action';
static const activeHatchingCityPoultry = '$_base/activeHatching';
static const newInspectionCityPoultry = '$_base/newInspection';
}

View File

@@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/data/common/dio_error_handler.dart';
import 'package:rasadyar_chicken/data/common/fa_user_role.dart';
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
import 'package:rasadyar_chicken/features/common/data/model/response/user_info/user_info_model.dart';
import 'package:rasadyar_chicken/features/common/data/model/response/user_profile_model/user_profile_model.dart';
@@ -123,7 +124,6 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin {
},
),
onSuccess: (result) async {
var tmpRoles = result?.role?.where((element) {
final allowedRoles = {
'poultryscience',
@@ -131,6 +131,7 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin {
'killhouse',
'provinceinspector',
'cityjahad',
'citypoultry',
'jahad',
'vetfarm',
'provincesupervisor',
@@ -141,8 +142,8 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin {
return allowedRoles.contains(lowerElement);
}).toList();
if (tmpRoles != null && tmpRoles.isNotEmpty ) {
await gService.saveSelectedModule(_module);
if (tmpRoles != null && tmpRoles.isNotEmpty) {
await gService.saveSelectedModule(_module);
await tokenStorageService.saveModule(_module);
await tokenStorageService.saveAccessToken(
_module,
@@ -168,8 +169,19 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin {
"device_name": deviceName.value,
},
);
if (tmpRoles.length == 1) {
var tmpRoute = getFaUserRoleWithOnTap(tmpRoles.first).values.first;
Get.offAndToNamed(CommonRoutes.role);
await gService.saveRole(Module.chicken, tmpRoles.first);
await gService.saveRoute(
Module.chicken,
tmpRoute ?? CommonRoutes.role,
);
Get.offAndToNamed(tmpRoute ?? CommonRoutes.role);
} else {
Get.offAndToNamed(CommonRoutes.role);
}
} else {
Get.snackbar(
'با احترام ',

View File

@@ -173,11 +173,14 @@ class ProfileLogic extends GetxController {
retryNewPasswordController.clear();
}
Future<void> changeUserRole(String newRole) async {
dLog(newRole);
await gService.saveRoute(Module.chicken, newRole);
Future<void> changeUserRole({
required String route,
required String role,
}) async {
await gService.saveRoute(Module.chicken, route);
await gService.saveRole(Module.chicken, role);
Get.offAllNamed(newRole);
Get.offAllNamed(route);
}
void scrollToSelectedItem(

View File

@@ -32,7 +32,11 @@ class ProfilePage extends GetView<ProfileLogic> {
return Container(
width: 128.w,
height: 128.h,
child: Center(child: CupertinoActivityIndicator(color: AppColor.greenNormal)),
child: Center(
child: CupertinoActivityIndicator(
color: AppColor.greenNormal,
),
),
);
}
@@ -57,7 +61,9 @@ class ProfilePage extends GetView<ProfileLogic> {
child: data.value.data?.image != null
? CircleAvatar(
radius: 64.w,
backgroundImage: NetworkImage(data.value.data!.image!),
backgroundImage: NetworkImage(
data.value.data!.image!,
),
)
: Icon(Icons.person, size: 64.w),
),
@@ -129,16 +135,25 @@ class ProfilePage extends GetView<ProfileLogic> {
}, controller.userProfile),
GestureDetector(
onTap: () {
Get.bottomSheet(changePasswordBottomSheet(), isScrollControlled: true);
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),
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)),
border: Border.all(
width: 1,
color: const Color(0xFFD6D6D6),
),
),
child: Row(
spacing: 6,
@@ -146,12 +161,17 @@ class ProfilePage extends GetView<ProfileLogic> {
Assets.vec.lockSvg.svg(
width: 24.w,
height: 24.h,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
colorFilter: ColorFilter.mode(
AppColor.blueNormal,
BlendMode.srcIn,
),
),
Text(
'تغییر رمز عبور',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
style: AppFonts.yekan14.copyWith(
color: AppColor.blueNormal,
),
),
],
),
@@ -159,16 +179,25 @@ class ProfilePage extends GetView<ProfileLogic> {
),
GestureDetector(
onTap: () {
Get.bottomSheet(exitBottomSheet(), isScrollControlled: true);
Get.bottomSheet(
exitBottomSheet(),
isScrollControlled: true,
);
},
child: Container(
height: 47.h,
margin: EdgeInsets.symmetric(horizontal: 8),
padding: EdgeInsets.symmetric(horizontal: 11.h, 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)),
border: Border.all(
width: 1,
color: const Color(0xFFD6D6D6),
),
),
child: Row(
spacing: 6,
@@ -176,12 +205,17 @@ class ProfilePage extends GetView<ProfileLogic> {
Assets.vec.logoutSvg.svg(
width: 24.w,
height: 24.h,
colorFilter: ColorFilter.mode(AppColor.redNormal, BlendMode.srcIn),
colorFilter: ColorFilter.mode(
AppColor.redNormal,
BlendMode.srcIn,
),
),
Text(
'خروج',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.redNormal),
style: AppFonts.yekan14.copyWith(
color: AppColor.redNormal,
),
),
],
),
@@ -219,7 +253,10 @@ class ProfilePage extends GetView<ProfileLogic> {
child: ObxValue(
(val) => Container(
height: val.value ? 320.h : 47.h,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: val.value ? 8 : 0),
margin: EdgeInsets.symmetric(
horizontal: 8,
vertical: val.value ? 8 : 0,
),
padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h),
decoration: BoxDecoration(
color: Colors.white,
@@ -244,14 +281,20 @@ class ProfilePage extends GetView<ProfileLogic> {
child: Assets.vec.editSvg.svg(
width: 24.w,
height: 24.h,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
colorFilter: ColorFilter.mode(
AppColor.blueNormal,
BlendMode.srcIn,
),
),
),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8.0,
),
child: Column(
children: [
itemList(
@@ -278,7 +321,10 @@ class ProfilePage extends GetView<ProfileLogic> {
),
itemList(
title: 'تاریخ تولد',
content: item.birthday?.toJalali.formatCompactDate() ?? 'نامشخص',
content:
item.birthday?.toJalali
.formatCompactDate() ??
'نامشخص',
icon: Assets.vec.calendarSvg.path,
),
//todo
@@ -299,7 +345,12 @@ class ProfilePage extends GetView<ProfileLogic> {
)
: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [Icon(CupertinoIcons.chevron_down, color: AppColor.iconColor)],
children: [
Icon(
CupertinoIcons.chevron_down,
color: AppColor.iconColor,
),
],
),
),
controller.isUserInformationOpen,
@@ -340,7 +391,10 @@ class ProfilePage extends GetView<ProfileLogic> {
child: ObxValue(
(val) => Container(
height: val.value ? 320.h : 47.h,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: val.value ? 12 : 0),
margin: EdgeInsets.symmetric(
horizontal: 8,
vertical: val.value ? 12 : 0,
),
padding: EdgeInsets.symmetric(horizontal: 11.h),
decoration: BoxDecoration(
color: Colors.white,
@@ -365,14 +419,20 @@ class ProfilePage extends GetView<ProfileLogic> {
child: Assets.vec.editSvg.svg(
width: 24.w,
height: 24.h,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
colorFilter: ColorFilter.mode(
AppColor.blueNormal,
BlendMode.srcIn,
),
),
),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8.0,
),
child: Column(
spacing: 2,
children: [
@@ -389,7 +449,8 @@ class ProfilePage extends GetView<ProfileLogic> {
),
itemList(
title: 'شماره ثبت',
content: item.unitRegistrationNumber ?? 'نامشخص',
content:
item.unitRegistrationNumber ?? 'نامشخص',
visible: item.unitName != null,
),
@@ -414,7 +475,10 @@ class ProfilePage extends GetView<ProfileLogic> {
content: item.city ?? 'نامشخص',
visible: item.unitName != null,
),
itemList(title: 'آدرس', content: item.unitAddress ?? 'نامشخص'),
itemList(
title: 'آدرس',
content: item.unitAddress ?? 'نامشخص',
),
],
),
),
@@ -422,7 +486,12 @@ class ProfilePage extends GetView<ProfileLogic> {
)
: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [Icon(CupertinoIcons.chevron_down, color: AppColor.iconColor)],
children: [
Icon(
CupertinoIcons.chevron_down,
color: AppColor.iconColor,
),
],
),
),
controller.isUnitInformationOpen,
@@ -480,12 +549,21 @@ class ProfilePage extends GetView<ProfileLogic> {
child: SvgGenImage.vec(icon).svg(
width: 20.w,
height: 20.h,
colorFilter: ColorFilter.mode(AppColor.textColor, BlendMode.srcIn),
colorFilter: ColorFilter.mode(
AppColor.textColor,
BlendMode.srcIn,
),
),
),
Text(title, style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
Text(
title,
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
),
Spacer(),
Text(content, style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
Text(
content,
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
),
],
),
),
@@ -512,7 +590,9 @@ class ProfilePage extends GetView<ProfileLogic> {
padding: EdgeInsets.all(6),
decoration: ShapeDecoration(
color: cardColor ?? AppColor.blueLight,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: Container(
padding: EdgeInsets.all(4),
@@ -523,7 +603,8 @@ class ProfilePage extends GetView<ProfileLogic> {
child: SvgGenImage.vec(icon).svg(
width: 40.w,
height: 40.h,
colorFilter: color ?? ColorFilter.mode(Colors.white, BlendMode.srcIn),
colorFilter:
color ?? ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
),
),
@@ -547,7 +628,9 @@ class ProfilePage extends GetView<ProfileLogic> {
children: [
Text(
'ویرایش اطلاعات هویتی',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover),
style: AppFonts.yekan16Bold.copyWith(
color: AppColor.darkGreyDarkHover,
),
),
Container(
@@ -619,7 +702,9 @@ class ProfilePage extends GetView<ProfileLogic> {
children: [
Text(
'عکس پروفایل',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
style: AppFonts.yekan16Bold.copyWith(
color: AppColor.blueNormal,
),
),
ObxValue((data) {
return Container(
@@ -628,17 +713,29 @@ class ProfilePage extends GetView<ProfileLogic> {
decoration: BoxDecoration(
color: AppColor.lightGreyNormal,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 1, color: AppColor.blackLight),
border: Border.all(
width: 1,
color: AppColor.blackLight,
),
),
child: Center(
child: data.value == null
? Padding(
padding: const EdgeInsets.fromLTRB(30, 10, 10, 30),
padding: const EdgeInsets.fromLTRB(
30,
10,
10,
30,
),
child: Image.network(
controller.userProfile.value.data?.image ?? '',
controller.userProfile.value.data?.image ??
'',
),
)
: Image.file(File(data.value!.path), fit: BoxFit.cover),
: Image.file(
File(data.value!.path),
fit: BoxFit.cover,
),
),
);
}, controller.selectedImage),
@@ -651,14 +748,18 @@ class ProfilePage extends GetView<ProfileLogic> {
text: 'گالری',
width: 150.w,
height: 40.h,
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
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,
);
controller.selectedImage.value = await controller
.imagePicker
.pickImage(
source: ImageSource.gallery,
imageQuality: 60,
maxWidth: 1080,
maxHeight: 720,
);
},
),
SizedBox(width: 16),
@@ -666,14 +767,18 @@ class ProfilePage extends GetView<ProfileLogic> {
text: 'دوربین',
width: 150.w,
height: 40.h,
textStyle: AppFonts.yekan20.copyWith(color: AppColor.blueNormal),
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,
);
controller.selectedImage.value = await controller
.imagePicker
.pickImage(
source: ImageSource.camera,
imageQuality: 60,
maxWidth: 1080,
maxHeight: 720,
);
},
),
],
@@ -724,7 +829,9 @@ class ProfilePage extends GetView<ProfileLogic> {
children: [
Text(
'تغییر رمز عبور',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover),
style: AppFonts.yekan16Bold.copyWith(
color: AppColor.darkGreyDarkHover,
),
),
SizedBox(),
RTextField(
@@ -736,7 +843,8 @@ class ProfilePage extends GetView<ProfileLogic> {
validator: (value) {
if (value == null || value.isEmpty) {
return 'رمز عبور را وارد کنید';
} else if (controller.userProfile.value.data?.password != value) {
} else if (controller.userProfile.value.data?.password !=
value) {
return 'رمز عبور صحیح نیست';
}
return null;
@@ -820,7 +928,10 @@ class ProfilePage extends GetView<ProfileLogic> {
child: Column(
spacing: 8,
children: [
Text('خروج', style: AppFonts.yekan16Bold.copyWith(color: AppColor.error)),
Text(
'خروج',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.error),
),
SizedBox(),
Text(
'آیا مطمئن هستید که می‌خواهید از حساب کاربری خود خارج شوید؟',
@@ -840,7 +951,9 @@ class ProfilePage extends GetView<ProfileLogic> {
backgroundColor: AppColor.error,
onPressed: () async {
await Future.wait([
controller.tokenService.deleteModuleTokens(Module.chicken),
controller.tokenService.deleteModuleTokens(
Module.chicken,
),
controller.gService.clearSelectedModule(),
]).then((value) async {
await removeChickenDI();
@@ -884,11 +997,16 @@ class ProfilePage extends GetView<ProfileLogic> {
children: List.generate(item?.length ?? 0, (index) {
Map tmpRole = getFaUserRoleWithOnTap(item?[index]);
return CustomChip(
isSelected: controller.gService.getRoute(Module.chicken) == tmpRole.values.first,
isSelected:
controller.gService.getRoute(Module.chicken) ==
tmpRole.values.first,
title: tmpRole.keys.first,
index: index,
onTap: (int p1) {
controller.changeUserRole(tmpRole.values.first);
controller.changeUserRole(
route: tmpRole.values.first,
role: item?[index] ?? '',
);
},
);
}),

View File

@@ -70,7 +70,6 @@ class RolePage extends GetView<RoleLogic> {
Module.chicken,
route,
);
await controller.gService.saveRole(
Module.chicken,
data[index],

View File

@@ -175,12 +175,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
spacing: 3,
children: [
Text(
item.poultry?.user?.fullname ?? 'N/A',
item.poultry?.user?.fullname ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
Text(
item.poultry?.user?.mobile ?? 'N/A',
item.poultry?.user?.mobile ?? 'ندارد',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
@@ -195,12 +195,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
item.poultry?.unitName ?? 'N/Aaq',
item.poultry?.unitName ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
item.poultry?.licenceNumber ?? 'N/A',
item.licenceNumber ?? 'ندارد',
textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),

View File

@@ -23,7 +23,7 @@ class JahadHomeLogic extends GetxController {
JahadActionItem(
title: "بازرسی مزارع طیور",
route: JahadRoutes.newInspectionJahad,
icon: Assets.vec.activeFramSvg.path,
icon: Assets.vec.inspectionPoultrySvg.path,
),
].obs;
}

View File

@@ -15,6 +15,7 @@ enum ErrorLocationType { serviceDisabled, permissionDenied, none }
class JahadRootLogic extends GetxController {
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late JahadRepository jahadRepository;
@@ -45,6 +46,7 @@ class JahadRootLogic extends GetxController {
void onInit() {
super.onInit();
jahadRepository = diChicken.get<JahadRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
void toggleExpanded(int index) {

View File

@@ -12,6 +12,7 @@ class KillHouseRootLogic extends GetxController {
RxInt currentPage = 1.obs;
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late KillHouseRepository killHouseRepository;
@@ -19,6 +20,7 @@ class KillHouseRootLogic extends GetxController {
void onInit() {
super.onInit();
killHouseRepository = diChicken.get<KillHouseRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
final pages = [

View File

@@ -30,6 +30,7 @@ class WarehouseAndDistributionRootLogic extends GetxController {
late DioRemote dioRemote;
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
RxInt currentPage = 2.obs;
List<Widget> pages = [
@@ -68,6 +69,7 @@ class WarehouseAndDistributionRootLogic extends GetxController {
super.onInit();
killHouseRepository = diChicken.get<KillHouseRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
@override

View File

@@ -193,12 +193,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
spacing: 3,
children: [
Text(
item.poultry?.user?.fullname ?? 'N/A',
item.poultry?.user?.fullname ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
Text(
item.poultry?.user?.mobile ?? 'N/A',
item.poultry?.user?.mobile ?? 'ندارد',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
@@ -213,12 +213,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
item.poultry?.unitName ?? 'N/Aaq',
item.poultry?.unitName ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
item.poultry?.licenceNumber ?? 'N/A',
item.licenceNumber ?? 'ندارد',
textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),

View File

@@ -40,7 +40,7 @@ class PoultryActionLogic extends GetxController {
PoultryActionItem(
title: "بازرسی مزارع طیور",
route: PoultryScienceRoutes.newInspectionPoultryScience,
icon: Assets.vec.activeFramSvg.path,
icon: Assets.vec.inspectionPoultrySvg.path,
),
].obs;
}

View File

@@ -15,6 +15,7 @@ enum ErrorLocationType { serviceDisabled, permissionDenied, none }
class PoultryScienceRootLogic extends GetxController {
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late PoultryScienceRepository poultryRepository;
@@ -46,6 +47,7 @@ class PoultryScienceRootLogic extends GetxController {
void onInit() {
super.onInit();
poultryRepository = diChicken.get<PoultryScienceRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
void toggleExpanded(int index) {

View File

@@ -193,12 +193,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
spacing: 3,
children: [
Text(
item.poultry?.user?.fullname ?? 'N/A',
item.poultry?.user?.fullname ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
Text(
item.poultry?.user?.mobile ?? 'N/A',
item.poultry?.user?.mobile ?? 'ندارد',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
@@ -213,12 +213,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
item.poultry?.unitName ?? 'N/Aaq',
item.poultry?.unitName ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
item.poultry?.licenceNumber ?? 'N/A',
item.licenceNumber ?? 'ندارد',
textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),

View File

@@ -24,7 +24,7 @@ class ProvinceInspectorHomeLogic extends GetxController {
ProvinceInspectorActionItem(
title: "بازرسی مزارع طیور",
route: ProvinceInspectorRoutes.newInspectionProvinceInspector,
icon: Assets.vec.activeFramSvg.path,
icon: Assets.vec.inspectionPoultrySvg.path,
),
].obs;
}

View File

@@ -14,6 +14,7 @@ enum ErrorLocationType { serviceDisabled, permissionDenied, none }
class ProvinceInspectorRootLogic extends GetxController {
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late ProvinceInspectorRepository provinceInspectorRepository;
@@ -45,6 +46,7 @@ class ProvinceInspectorRootLogic extends GetxController {
void onInit() {
super.onInit();
provinceInspectorRepository = diChicken.get<ProvinceInspectorRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
void toggleExpanded(int index) {

View File

@@ -193,12 +193,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
spacing: 3,
children: [
Text(
item.poultry?.user?.fullname ?? 'N/A',
item.poultry?.user?.fullname ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
Text(
item.poultry?.user?.mobile ?? 'N/A',
item.poultry?.user?.mobile ?? 'ندارد',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
@@ -213,12 +213,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
item.poultry?.unitName ?? 'N/Aaq',
item.poultry?.unitName ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
item.poultry?.licenceNumber ?? 'N/A',
item.licenceNumber ?? 'ندارد',
textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),

View File

@@ -24,7 +24,7 @@ class ProvinceOperatorHomeLogic extends GetxController {
ProvinceOperatorHomeItem(
title: "بازرسی مزارع طیور",
route: ProvinceOperatorRoutes.newInspectionProvinceOperator,
icon: Assets.vec.activeFramSvg.path,
icon: Assets.vec.inspectionPoultrySvg.path,
),
].obs;
}

View File

@@ -13,6 +13,7 @@ enum ErrorLocationType { serviceDisabled, permissionDenied, none }
class ProvinceOperatorRootLogic extends GetxController {
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late ProvinceOperatorRepository provinceOperatorRepository;
@@ -44,6 +45,7 @@ class ProvinceOperatorRootLogic extends GetxController {
void onInit() {
super.onInit();
provinceOperatorRepository = diChicken.get<ProvinceOperatorRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
void toggleExpanded(int index) {

View File

@@ -193,12 +193,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
spacing: 3,
children: [
Text(
item.poultry?.user?.fullname ?? 'N/A',
item.poultry?.user?.fullname ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
Text(
item.poultry?.user?.mobile ?? 'N/A',
item.poultry?.user?.mobile ?? 'ندارد',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
@@ -213,12 +213,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
item.poultry?.unitName ?? 'N/Aaq',
item.poultry?.unitName ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
item.poultry?.licenceNumber ?? 'N/A',
item.licenceNumber ?? 'ندارد',
textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),

View File

@@ -24,7 +24,7 @@ class ProvinceSupervisorHomeLogic extends GetxController {
ProvinceSupervisorActionItem(
title: "بازرسی مزارع طیور",
route: ProvinceSupervisorRoutes.newInspectionProvinceSupervisor,
icon: Assets.vec.activeFramSvg.path,
icon: Assets.vec.inspectionPoultrySvg.path,
),
].obs;
}

View File

@@ -14,6 +14,7 @@ enum ErrorLocationType { serviceDisabled, permissionDenied, none }
class ProvinceSupervisorRootLogic extends GetxController {
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late ProvinceSupervisorRepository provinceSupervisorRepository;
@@ -46,6 +47,7 @@ class ProvinceSupervisorRootLogic extends GetxController {
super.onInit();
provinceSupervisorRepository = diChicken
.get<ProvinceSupervisorRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
void toggleExpanded(int index) {

View File

@@ -42,6 +42,7 @@ class StewardRootLogic extends GetxController {
late DioRemote dioRemote;
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late CommonRepository commonRepository;
late StewardRepository stewardRepository;
late ChickenLocalDataSource localDatasource;
@@ -61,6 +62,7 @@ class StewardRootLogic extends GetxController {
localDatasource = diChicken.get<ChickenLocalDataSource>();
commonRepository = diChicken.get<CommonRepository>();
stewardRepository = diChicken.get<StewardRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
@override

View File

@@ -193,12 +193,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
spacing: 3,
children: [
Text(
item.poultry?.user?.fullname ?? 'N/A',
item.poultry?.user?.fullname ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
Text(
item.poultry?.user?.mobile ?? 'N/A',
item.poultry?.user?.mobile ?? 'ندارد',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
@@ -213,12 +213,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
item.poultry?.unitName ?? 'N/Aaq',
item.poultry?.unitName ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
item.poultry?.licenceNumber ?? 'N/A',
item.licenceNumber ?? 'ندارد',
textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),

View File

@@ -20,7 +20,7 @@ class SuperAdminHomeLogic extends GetxController {
SuperAdminHomeItem(
title: "بازرسی مزارع طیور",
route: SuperAdminRoutes.newInspectionSuperAdmin,
icon: Assets.vec.activeFramSvg.path,
icon: Assets.vec.inspectionPoultrySvg.path,
),
].obs;
}

View File

@@ -14,6 +14,7 @@ enum ErrorLocationType { serviceDisabled, permissionDenied, none }
class SuperAdminRootLogic extends GetxController {
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late SuperAdminRepository superAdminRepository;
@@ -45,6 +46,7 @@ class SuperAdminRootLogic extends GetxController {
void onInit() {
super.onInit();
superAdminRepository = diChicken.get<SuperAdminRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
void toggleExpanded(int index) {

View File

@@ -193,12 +193,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
spacing: 3,
children: [
Text(
item.poultry?.user?.fullname ?? 'N/A',
item.poultry?.user?.fullname ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
Text(
item.poultry?.user?.mobile ?? 'N/A',
item.poultry?.user?.mobile ?? 'ندارد',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
@@ -213,12 +213,12 @@ class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
item.poultry?.unitName ?? 'N/Aaq',
item.poultry?.unitName ?? 'ندارد',
textAlign: TextAlign.start,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
item.poultry?.licenceNumber ?? 'N/A',
item.licenceNumber ?? 'ندارد',
textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),

View File

@@ -19,7 +19,7 @@ class VetFarmHomeLogic extends GetxController {
VetFarmHomeItem(
title: "بازرسی مزارع طیور",
route: VetFarmRoutes.newInspectionVetFarm,
icon: Assets.vec.activeFramSvg.path,
icon: Assets.vec.inspectionPoultrySvg.path,
),
].obs;
}

View File

@@ -14,6 +14,7 @@ enum ErrorLocationType { serviceDisabled, permissionDenied, none }
class VetFarmRootLogic extends GetxController {
var tokenService = Get.find<TokenStorageService>();
var gService = Get.find<GService>();
late VetFarmRepository vetFarmRepository;
@@ -45,6 +46,7 @@ class VetFarmRootLogic extends GetxController {
void onInit() {
super.onInit();
vetFarmRepository = diChicken.get<VetFarmRepository>();
fLog('gService: ${gService.getRole(Module.chicken)}');
}
void toggleExpanded(int index) {

View File

@@ -1,3 +1,4 @@
import 'package:rasadyar_chicken/features/city_poultry/presentation/routes/pages.dart';
import 'package:rasadyar_chicken/features/common/common.dart';
import 'package:rasadyar_chicken/features/kill_house/action/logic.dart';
import 'package:rasadyar_chicken/features/kill_house/action/view.dart';
@@ -66,6 +67,10 @@ sealed class ChickenPages {
...JahadPages.pages,
//endregion
//region City Poultry Pages
...CityPoultryPages.pages,
//endregion
//region Poultry Farm Inspection
GetPage(
name: ChickenRoutes.poultryFarmInspectionHome,

View File

@@ -41,6 +41,11 @@ const int cityJahadActionKey = 112;
//endregion
//region city poultry Keys
const int cityPoultryActionKey = 117;
//endregion
//region vet farm Keys
const int vetFarmActionKey = 113;

View File

@@ -1,6 +1,6 @@
name: rasadyar_chicken
description: A starting point for Dart libraries or applications.
version: 1.8.0
version: 1.9.0
environment:
sdk: ^3.10.0

View File

@@ -229,6 +229,9 @@ class $AssetsIconsGen {
/// File path: assets/icons/inspection.svg
SvgGenImage get inspection => const SvgGenImage('assets/icons/inspection.svg');
/// File path: assets/icons/inspection_poultry.svg
SvgGenImage get inspectionPoultry => const SvgGenImage('assets/icons/inspection_poultry.svg');
/// File path: assets/icons/key.svg
SvgGenImage get key => const SvgGenImage('assets/icons/key.svg');
@@ -456,6 +459,7 @@ class $AssetsIconsGen {
information,
inside,
inspection,
inspectionPoultry,
key,
liveStock,
lock,
@@ -748,6 +752,9 @@ class $AssetsVecGen {
/// File path: assets/vec/inspection.svg.vec
SvgGenImage get inspectionSvg => const SvgGenImage.vec('assets/vec/inspection.svg.vec');
/// File path: assets/vec/inspection_poultry.svg.vec
SvgGenImage get inspectionPoultrySvg => const SvgGenImage.vec('assets/vec/inspection_poultry.svg.vec');
/// File path: assets/vec/key.svg.vec
SvgGenImage get keySvg => const SvgGenImage.vec('assets/vec/key.svg.vec');
@@ -975,6 +982,7 @@ class $AssetsVecGen {
informationSvg,
insideSvg,
inspectionSvg,
inspectionPoultrySvg,
keySvg,
liveStockSvg,
lockSvg,

View File

@@ -1,13 +1,35 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
Future<void> requiredUpdateDialog({required Future<void> Function() onConfirm}) async {
Future<void> requiredUpdateDialog({
required Future<void> Function() onConfirm,
required List<String>? changes,
}) async {
await Get.defaultDialog(
barrierDismissible: false,
onWillPop: () async => false,
title: 'بروزرسانی',
middleText: 'برای استفاده از امکانات برنامه لطفا برنامه را بروز رسانی نمایید.',
content: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8.h,
children:
changes
?.map(
(e) => Text(
e,
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
),
)
.toList() ??
[],
),
),
middleText:
'برای استفاده از امکانات برنامه لطفا برنامه را بروز رسانی نمایید.',
confirm: RElevated(
height: 40.h,
width: 150.w,
@@ -28,12 +50,15 @@ Future<void> requiredUpdateDialog({required Future<void> Function() onConfirm})
);
}
Future<void> optionalUpdateDialog({required Future<void> Function() onConfirm}) async {
Future<void> optionalUpdateDialog({
required Future<void> Function() onConfirm,
}) async {
await Get.defaultDialog(
barrierDismissible: false,
onWillPop: () async => false,
title: 'بروزرسانی',
middleText: 'برای استفاده از امکانات جدید برنامه می توانید آن را بروزرسانی نمایید.',
middleText:
'برای استفاده از امکانات جدید برنامه می توانید آن را بروزرسانی نمایید.',
confirm: RElevated(
height: 40.h,
width: 150.w,

View File

@@ -1394,7 +1394,7 @@ packages:
path: "packages/chicken"
relative: true
source: path
version: "1.8.0"
version: "1.9.0"
rasadyar_core:
dependency: "direct main"
description:

View File

@@ -1,7 +1,7 @@
name: rasadyar_app
description: "A new Flutter project."
publish_to: "none"
version: 1.3.41+37
version: 1.3.43+39
environment:
sdk: ^3.10.0