From d2e74e66271ef1a3f3a683eb68c564880333d82d Mon Sep 17 00:00:00 2001 From: "mr.mojtaba" Date: Sat, 6 Sep 2025 17:22:19 +0330 Subject: [PATCH] feat : home page --- lib/presentation/pages/splash/logic.dart | 2 + .../poultry_science_remote.dart | 8 + .../poultry_science_remote_imp.dart | 25 + packages/chicken/lib/data/di/chicken_di.dart | 19 + .../local/widely_used_local_model.g.dart | 4 +- .../home_poultry_science_model.dart | 21 + .../home_poultry_science_model.freezed.dart | 298 ++++++++ .../home_poultry_science_model.g.dart | 33 + .../chicken/chicken_repository.dart | 7 + .../poultry_science_repository.dart | 8 + .../poultry_science_repository_imp.dart | 17 + .../pages/poultry_science/home/logic.dart | 30 + .../pages/poultry_science/home/view.dart | 608 +++++++++++++++++ .../pages/poultry_science/profile/logic.dart | 148 ++++ .../pages/poultry_science/profile/view.dart | 637 ++++++++++++++++++ .../pages/poultry_science/root/logic.dart | 71 ++ .../pages/poultry_science/root/view.dart | 128 ++++ .../lib/presentation/routes/pages.dart | 22 + 18 files changed, 2084 insertions(+), 2 deletions(-) create mode 100644 packages/chicken/lib/data/data_source/remote/poultry_science/poultry_science_remote.dart create mode 100644 packages/chicken/lib/data/data_source/remote/poultry_science/poultry_science_remote_imp.dart create mode 100644 packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart create mode 100644 packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.freezed.dart create mode 100644 packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.g.dart create mode 100644 packages/chicken/lib/data/repositories/poultry_science/poultry_science_repository.dart create mode 100644 packages/chicken/lib/data/repositories/poultry_science/poultry_science_repository_imp.dart create mode 100644 packages/chicken/lib/presentation/pages/poultry_science/home/logic.dart create mode 100644 packages/chicken/lib/presentation/pages/poultry_science/home/view.dart create mode 100644 packages/chicken/lib/presentation/pages/poultry_science/profile/logic.dart create mode 100644 packages/chicken/lib/presentation/pages/poultry_science/profile/view.dart create mode 100644 packages/chicken/lib/presentation/pages/poultry_science/root/logic.dart create mode 100644 packages/chicken/lib/presentation/pages/poultry_science/root/view.dart diff --git a/lib/presentation/pages/splash/logic.dart b/lib/presentation/pages/splash/logic.dart index 2d501cd..d6fc2db 100644 --- a/lib/presentation/pages/splash/logic.dart +++ b/lib/presentation/pages/splash/logic.dart @@ -164,6 +164,8 @@ 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) { diff --git a/packages/chicken/lib/data/data_source/remote/poultry_science/poultry_science_remote.dart b/packages/chicken/lib/data/data_source/remote/poultry_science/poultry_science_remote.dart new file mode 100644 index 0000000..5ba1715 --- /dev/null +++ b/packages/chicken/lib/data/data_source/remote/poultry_science/poultry_science_remote.dart @@ -0,0 +1,8 @@ +import 'package:rasadyar_chicken/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart'; + +abstract class PoultryScienceRemoteDatasource { + Future getHomePoultryScience({ + required String token, + required String type, + }); +} diff --git a/packages/chicken/lib/data/data_source/remote/poultry_science/poultry_science_remote_imp.dart b/packages/chicken/lib/data/data_source/remote/poultry_science/poultry_science_remote_imp.dart new file mode 100644 index 0000000..3366c71 --- /dev/null +++ b/packages/chicken/lib/data/data_source/remote/poultry_science/poultry_science_remote_imp.dart @@ -0,0 +1,25 @@ +import 'package:rasadyar_chicken/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart'; +import 'package:rasadyar_core/core.dart'; + +import 'poultry_science_remote.dart'; + +class PoultryScienceRemoteDatasourceImp implements PoultryScienceRemoteDatasource { + final DioRemote _httpClient; + + PoultryScienceRemoteDatasourceImp(this._httpClient); + + @override + Future getHomePoultryScience({ + required String token, + required String type, + }) async { + var res = await _httpClient.get( + 'poultry_and_hatching_for_poultry_science/', + queryParameters: {'type': type}, + headers: {'Authorization': 'Bearer $token'}, + fromJson: (json) => HomePoultryScienceModel.fromJson(json), + ); + + return res.data; + } +} diff --git a/packages/chicken/lib/data/di/chicken_di.dart b/packages/chicken/lib/data/di/chicken_di.dart index 6b74db6..67602d2 100644 --- a/packages/chicken/lib/data/di/chicken_di.dart +++ b/packages/chicken/lib/data/di/chicken_di.dart @@ -6,10 +6,14 @@ import 'package:rasadyar_chicken/data/data_source/remote/auth/auth_remote.dart'; import 'package:rasadyar_chicken/data/data_source/remote/auth/auth_remote_imp.dart'; import 'package:rasadyar_chicken/data/data_source/remote/chicken/chicken_remote.dart'; import 'package:rasadyar_chicken/data/data_source/remote/chicken/chicken_remote_imp.dart'; +import 'package:rasadyar_chicken/data/data_source/remote/poultry_science/poultry_science_remote.dart'; +import 'package:rasadyar_chicken/data/data_source/remote/poultry_science/poultry_science_remote_imp.dart'; import 'package:rasadyar_chicken/data/repositories/auth/auth_repository.dart'; import 'package:rasadyar_chicken/data/repositories/auth/auth_repository_imp.dart'; import 'package:rasadyar_chicken/data/repositories/chicken/chicken_repository.dart'; import 'package:rasadyar_chicken/data/repositories/chicken/chicken_repository_imp.dart'; +import 'package:rasadyar_chicken/data/repositories/poultry_science/poultry_science_repository.dart'; +import 'package:rasadyar_chicken/data/repositories/poultry_science/poultry_science_repository_imp.dart'; import 'package:rasadyar_core/core.dart'; GetIt diChicken = GetIt.asNewInstance(); @@ -67,6 +71,14 @@ Future setupChickenDI() async { local: diChicken.get(), ), ); + + diChicken.registerLazySingleton( + () => PoultryScienceRemoteDatasourceImp(diChicken.get()), + ); + + diChicken.registerLazySingleton( + () => PoultryScienceRepositoryImp(diChicken.get()), + ); } Future newSetupAuthDI(String newUrl) async { @@ -117,6 +129,13 @@ Future newSetupAuthDI(String newUrl) async { local: diChicken.get(), ), ); + + await reRegister( + () => PoultryScienceRemoteDatasourceImp(dioRemote), + ); + await reRegister( + () => PoultryScienceRepositoryImp(diChicken.get()), + ); } Future reRegister(T Function() factory) async { diff --git a/packages/chicken/lib/data/models/local/widely_used_local_model.g.dart b/packages/chicken/lib/data/models/local/widely_used_local_model.g.dart index 271c009..b4170ee 100644 --- a/packages/chicken/lib/data/models/local/widely_used_local_model.g.dart +++ b/packages/chicken/lib/data/models/local/widely_used_local_model.g.dart @@ -8,7 +8,7 @@ part of 'widely_used_local_model.dart'; class WidelyUsedLocalModelAdapter extends TypeAdapter { @override - final typeId = 2; + final typeId = 4; @override WidelyUsedLocalModel read(BinaryReader reader) { @@ -45,7 +45,7 @@ class WidelyUsedLocalModelAdapter extends TypeAdapter { class WidelyUsedLocalItemAdapter extends TypeAdapter { @override - final typeId = 3; + final typeId = 5; @override WidelyUsedLocalItem read(BinaryReader reader) { diff --git a/packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart b/packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart new file mode 100644 index 0000000..5502295 --- /dev/null +++ b/packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart @@ -0,0 +1,21 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'home_poultry_science_model.freezed.dart'; +part 'home_poultry_science_model.g.dart'; + +@freezed +abstract class HomePoultryScienceModel with _$HomePoultryScienceModel { + const factory HomePoultryScienceModel({ + int? farmCount, + int? hatchingCount, + int? hatchingQuantity, + int? hatchingLeftOver, + int? hatchingLosses, + int? hatchingKilledQuantity, + int? hatchingMaxAge, + int? hatchingMinAge, + }) = _HomePoultryScienceModel; + + factory HomePoultryScienceModel.fromJson(Map json) => + _$HomePoultryScienceModelFromJson(json); +} diff --git a/packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.freezed.dart b/packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.freezed.dart new file mode 100644 index 0000000..85b59b0 --- /dev/null +++ b/packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.freezed.dart @@ -0,0 +1,298 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'home_poultry_science_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$HomePoultryScienceModel { + + int? get farmCount; int? get hatchingCount; int? get hatchingQuantity; int? get hatchingLeftOver; int? get hatchingLosses; int? get hatchingKilledQuantity; int? get hatchingMaxAge; int? get hatchingMinAge; +/// Create a copy of HomePoultryScienceModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$HomePoultryScienceModelCopyWith get copyWith => _$HomePoultryScienceModelCopyWithImpl(this as HomePoultryScienceModel, _$identity); + + /// Serializes this HomePoultryScienceModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is HomePoultryScienceModel&&(identical(other.farmCount, farmCount) || other.farmCount == farmCount)&&(identical(other.hatchingCount, hatchingCount) || other.hatchingCount == hatchingCount)&&(identical(other.hatchingQuantity, hatchingQuantity) || other.hatchingQuantity == hatchingQuantity)&&(identical(other.hatchingLeftOver, hatchingLeftOver) || other.hatchingLeftOver == hatchingLeftOver)&&(identical(other.hatchingLosses, hatchingLosses) || other.hatchingLosses == hatchingLosses)&&(identical(other.hatchingKilledQuantity, hatchingKilledQuantity) || other.hatchingKilledQuantity == hatchingKilledQuantity)&&(identical(other.hatchingMaxAge, hatchingMaxAge) || other.hatchingMaxAge == hatchingMaxAge)&&(identical(other.hatchingMinAge, hatchingMinAge) || other.hatchingMinAge == hatchingMinAge)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,farmCount,hatchingCount,hatchingQuantity,hatchingLeftOver,hatchingLosses,hatchingKilledQuantity,hatchingMaxAge,hatchingMinAge); + +@override +String toString() { + return 'HomePoultryScienceModel(farmCount: $farmCount, hatchingCount: $hatchingCount, hatchingQuantity: $hatchingQuantity, hatchingLeftOver: $hatchingLeftOver, hatchingLosses: $hatchingLosses, hatchingKilledQuantity: $hatchingKilledQuantity, hatchingMaxAge: $hatchingMaxAge, hatchingMinAge: $hatchingMinAge)'; +} + + +} + +/// @nodoc +abstract mixin class $HomePoultryScienceModelCopyWith<$Res> { + factory $HomePoultryScienceModelCopyWith(HomePoultryScienceModel value, $Res Function(HomePoultryScienceModel) _then) = _$HomePoultryScienceModelCopyWithImpl; +@useResult +$Res call({ + int? farmCount, int? hatchingCount, int? hatchingQuantity, int? hatchingLeftOver, int? hatchingLosses, int? hatchingKilledQuantity, int? hatchingMaxAge, int? hatchingMinAge +}); + + + + +} +/// @nodoc +class _$HomePoultryScienceModelCopyWithImpl<$Res> + implements $HomePoultryScienceModelCopyWith<$Res> { + _$HomePoultryScienceModelCopyWithImpl(this._self, this._then); + + final HomePoultryScienceModel _self; + final $Res Function(HomePoultryScienceModel) _then; + +/// Create a copy of HomePoultryScienceModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? farmCount = freezed,Object? hatchingCount = freezed,Object? hatchingQuantity = freezed,Object? hatchingLeftOver = freezed,Object? hatchingLosses = freezed,Object? hatchingKilledQuantity = freezed,Object? hatchingMaxAge = freezed,Object? hatchingMinAge = freezed,}) { + return _then(_self.copyWith( +farmCount: freezed == farmCount ? _self.farmCount : farmCount // ignore: cast_nullable_to_non_nullable +as int?,hatchingCount: freezed == hatchingCount ? _self.hatchingCount : hatchingCount // ignore: cast_nullable_to_non_nullable +as int?,hatchingQuantity: freezed == hatchingQuantity ? _self.hatchingQuantity : hatchingQuantity // ignore: cast_nullable_to_non_nullable +as int?,hatchingLeftOver: freezed == hatchingLeftOver ? _self.hatchingLeftOver : hatchingLeftOver // ignore: cast_nullable_to_non_nullable +as int?,hatchingLosses: freezed == hatchingLosses ? _self.hatchingLosses : hatchingLosses // ignore: cast_nullable_to_non_nullable +as int?,hatchingKilledQuantity: freezed == hatchingKilledQuantity ? _self.hatchingKilledQuantity : hatchingKilledQuantity // ignore: cast_nullable_to_non_nullable +as int?,hatchingMaxAge: freezed == hatchingMaxAge ? _self.hatchingMaxAge : hatchingMaxAge // ignore: cast_nullable_to_non_nullable +as int?,hatchingMinAge: freezed == hatchingMinAge ? _self.hatchingMinAge : hatchingMinAge // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [HomePoultryScienceModel]. +extension HomePoultryScienceModelPatterns on HomePoultryScienceModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _HomePoultryScienceModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _HomePoultryScienceModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _HomePoultryScienceModel value) $default,){ +final _that = this; +switch (_that) { +case _HomePoultryScienceModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _HomePoultryScienceModel value)? $default,){ +final _that = this; +switch (_that) { +case _HomePoultryScienceModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int? farmCount, int? hatchingCount, int? hatchingQuantity, int? hatchingLeftOver, int? hatchingLosses, int? hatchingKilledQuantity, int? hatchingMaxAge, int? hatchingMinAge)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _HomePoultryScienceModel() when $default != null: +return $default(_that.farmCount,_that.hatchingCount,_that.hatchingQuantity,_that.hatchingLeftOver,_that.hatchingLosses,_that.hatchingKilledQuantity,_that.hatchingMaxAge,_that.hatchingMinAge);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int? farmCount, int? hatchingCount, int? hatchingQuantity, int? hatchingLeftOver, int? hatchingLosses, int? hatchingKilledQuantity, int? hatchingMaxAge, int? hatchingMinAge) $default,) {final _that = this; +switch (_that) { +case _HomePoultryScienceModel(): +return $default(_that.farmCount,_that.hatchingCount,_that.hatchingQuantity,_that.hatchingLeftOver,_that.hatchingLosses,_that.hatchingKilledQuantity,_that.hatchingMaxAge,_that.hatchingMinAge);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int? farmCount, int? hatchingCount, int? hatchingQuantity, int? hatchingLeftOver, int? hatchingLosses, int? hatchingKilledQuantity, int? hatchingMaxAge, int? hatchingMinAge)? $default,) {final _that = this; +switch (_that) { +case _HomePoultryScienceModel() when $default != null: +return $default(_that.farmCount,_that.hatchingCount,_that.hatchingQuantity,_that.hatchingLeftOver,_that.hatchingLosses,_that.hatchingKilledQuantity,_that.hatchingMaxAge,_that.hatchingMinAge);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _HomePoultryScienceModel implements HomePoultryScienceModel { + const _HomePoultryScienceModel({this.farmCount, this.hatchingCount, this.hatchingQuantity, this.hatchingLeftOver, this.hatchingLosses, this.hatchingKilledQuantity, this.hatchingMaxAge, this.hatchingMinAge}); + factory _HomePoultryScienceModel.fromJson(Map json) => _$HomePoultryScienceModelFromJson(json); + +@override final int? farmCount; +@override final int? hatchingCount; +@override final int? hatchingQuantity; +@override final int? hatchingLeftOver; +@override final int? hatchingLosses; +@override final int? hatchingKilledQuantity; +@override final int? hatchingMaxAge; +@override final int? hatchingMinAge; + +/// Create a copy of HomePoultryScienceModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$HomePoultryScienceModelCopyWith<_HomePoultryScienceModel> get copyWith => __$HomePoultryScienceModelCopyWithImpl<_HomePoultryScienceModel>(this, _$identity); + +@override +Map toJson() { + return _$HomePoultryScienceModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _HomePoultryScienceModel&&(identical(other.farmCount, farmCount) || other.farmCount == farmCount)&&(identical(other.hatchingCount, hatchingCount) || other.hatchingCount == hatchingCount)&&(identical(other.hatchingQuantity, hatchingQuantity) || other.hatchingQuantity == hatchingQuantity)&&(identical(other.hatchingLeftOver, hatchingLeftOver) || other.hatchingLeftOver == hatchingLeftOver)&&(identical(other.hatchingLosses, hatchingLosses) || other.hatchingLosses == hatchingLosses)&&(identical(other.hatchingKilledQuantity, hatchingKilledQuantity) || other.hatchingKilledQuantity == hatchingKilledQuantity)&&(identical(other.hatchingMaxAge, hatchingMaxAge) || other.hatchingMaxAge == hatchingMaxAge)&&(identical(other.hatchingMinAge, hatchingMinAge) || other.hatchingMinAge == hatchingMinAge)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,farmCount,hatchingCount,hatchingQuantity,hatchingLeftOver,hatchingLosses,hatchingKilledQuantity,hatchingMaxAge,hatchingMinAge); + +@override +String toString() { + return 'HomePoultryScienceModel(farmCount: $farmCount, hatchingCount: $hatchingCount, hatchingQuantity: $hatchingQuantity, hatchingLeftOver: $hatchingLeftOver, hatchingLosses: $hatchingLosses, hatchingKilledQuantity: $hatchingKilledQuantity, hatchingMaxAge: $hatchingMaxAge, hatchingMinAge: $hatchingMinAge)'; +} + + +} + +/// @nodoc +abstract mixin class _$HomePoultryScienceModelCopyWith<$Res> implements $HomePoultryScienceModelCopyWith<$Res> { + factory _$HomePoultryScienceModelCopyWith(_HomePoultryScienceModel value, $Res Function(_HomePoultryScienceModel) _then) = __$HomePoultryScienceModelCopyWithImpl; +@override @useResult +$Res call({ + int? farmCount, int? hatchingCount, int? hatchingQuantity, int? hatchingLeftOver, int? hatchingLosses, int? hatchingKilledQuantity, int? hatchingMaxAge, int? hatchingMinAge +}); + + + + +} +/// @nodoc +class __$HomePoultryScienceModelCopyWithImpl<$Res> + implements _$HomePoultryScienceModelCopyWith<$Res> { + __$HomePoultryScienceModelCopyWithImpl(this._self, this._then); + + final _HomePoultryScienceModel _self; + final $Res Function(_HomePoultryScienceModel) _then; + +/// Create a copy of HomePoultryScienceModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? farmCount = freezed,Object? hatchingCount = freezed,Object? hatchingQuantity = freezed,Object? hatchingLeftOver = freezed,Object? hatchingLosses = freezed,Object? hatchingKilledQuantity = freezed,Object? hatchingMaxAge = freezed,Object? hatchingMinAge = freezed,}) { + return _then(_HomePoultryScienceModel( +farmCount: freezed == farmCount ? _self.farmCount : farmCount // ignore: cast_nullable_to_non_nullable +as int?,hatchingCount: freezed == hatchingCount ? _self.hatchingCount : hatchingCount // ignore: cast_nullable_to_non_nullable +as int?,hatchingQuantity: freezed == hatchingQuantity ? _self.hatchingQuantity : hatchingQuantity // ignore: cast_nullable_to_non_nullable +as int?,hatchingLeftOver: freezed == hatchingLeftOver ? _self.hatchingLeftOver : hatchingLeftOver // ignore: cast_nullable_to_non_nullable +as int?,hatchingLosses: freezed == hatchingLosses ? _self.hatchingLosses : hatchingLosses // ignore: cast_nullable_to_non_nullable +as int?,hatchingKilledQuantity: freezed == hatchingKilledQuantity ? _self.hatchingKilledQuantity : hatchingKilledQuantity // ignore: cast_nullable_to_non_nullable +as int?,hatchingMaxAge: freezed == hatchingMaxAge ? _self.hatchingMaxAge : hatchingMaxAge // ignore: cast_nullable_to_non_nullable +as int?,hatchingMinAge: freezed == hatchingMinAge ? _self.hatchingMinAge : hatchingMinAge // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + + +} + +// dart format on diff --git a/packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.g.dart b/packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.g.dart new file mode 100644 index 0000000..0adfc1e --- /dev/null +++ b/packages/chicken/lib/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.g.dart @@ -0,0 +1,33 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'home_poultry_science_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_HomePoultryScienceModel _$HomePoultryScienceModelFromJson( + Map json, +) => _HomePoultryScienceModel( + farmCount: (json['farm_count'] as num?)?.toInt(), + hatchingCount: (json['hatching_count'] as num?)?.toInt(), + hatchingQuantity: (json['hatching_quantity'] as num?)?.toInt(), + hatchingLeftOver: (json['hatching_left_over'] as num?)?.toInt(), + hatchingLosses: (json['hatching_losses'] as num?)?.toInt(), + hatchingKilledQuantity: (json['hatching_killed_quantity'] as num?)?.toInt(), + hatchingMaxAge: (json['hatching_max_age'] as num?)?.toInt(), + hatchingMinAge: (json['hatching_min_age'] as num?)?.toInt(), +); + +Map _$HomePoultryScienceModelToJson( + _HomePoultryScienceModel instance, +) => { + 'farm_count': instance.farmCount, + 'hatching_count': instance.hatchingCount, + 'hatching_quantity': instance.hatchingQuantity, + 'hatching_left_over': instance.hatchingLeftOver, + 'hatching_losses': instance.hatchingLosses, + 'hatching_killed_quantity': instance.hatchingKilledQuantity, + 'hatching_max_age': instance.hatchingMaxAge, + 'hatching_min_age': instance.hatchingMinAge, +}; diff --git a/packages/chicken/lib/data/repositories/chicken/chicken_repository.dart b/packages/chicken/lib/data/repositories/chicken/chicken_repository.dart index 62b4404..1d57de4 100644 --- a/packages/chicken/lib/data/repositories/chicken/chicken_repository.dart +++ b/packages/chicken/lib/data/repositories/chicken/chicken_repository.dart @@ -27,6 +27,8 @@ import '../../models/request/create_steward_free_bar/create_steward_free_bar.dar abstract class ChickenRepository { //region Remote + + //region Steward Future?> getInventory({required String token, CancelToken? cancelToken}); Future getKillHouseDistributionInfo({required String token}); @@ -156,6 +158,11 @@ abstract class ChickenRepository { Future deleteSegmentation({required String token, required String key}); + //endregion + + + + //endregion //region local diff --git a/packages/chicken/lib/data/repositories/poultry_science/poultry_science_repository.dart b/packages/chicken/lib/data/repositories/poultry_science/poultry_science_repository.dart new file mode 100644 index 0000000..f1e3a58 --- /dev/null +++ b/packages/chicken/lib/data/repositories/poultry_science/poultry_science_repository.dart @@ -0,0 +1,8 @@ +import 'package:rasadyar_chicken/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart'; + +abstract class PoultryScienceRepository { + Future getHomePoultryScience({ + required String token, + required String type, + }); +} diff --git a/packages/chicken/lib/data/repositories/poultry_science/poultry_science_repository_imp.dart b/packages/chicken/lib/data/repositories/poultry_science/poultry_science_repository_imp.dart new file mode 100644 index 0000000..f306bdb --- /dev/null +++ b/packages/chicken/lib/data/repositories/poultry_science/poultry_science_repository_imp.dart @@ -0,0 +1,17 @@ +import 'package:rasadyar_chicken/data/data_source/remote/poultry_science/poultry_science_remote.dart'; +import 'package:rasadyar_chicken/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart'; +import 'poultry_science_repository.dart'; + +class PoultryScienceRepositoryImp implements PoultryScienceRepository { + final PoultryScienceRemoteDatasource datasource; + + PoultryScienceRepositoryImp(this.datasource); + + @override + Future getHomePoultryScience({ + required String token, + required String type, + }) async => await datasource.getHomePoultryScience(token: token, type: type); + + +} diff --git a/packages/chicken/lib/presentation/pages/poultry_science/home/logic.dart b/packages/chicken/lib/presentation/pages/poultry_science/home/logic.dart new file mode 100644 index 0000000..ccad0eb --- /dev/null +++ b/packages/chicken/lib/presentation/pages/poultry_science/home/logic.dart @@ -0,0 +1,30 @@ +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'; + +class PoultryScienceHomeLogic extends GetxController { + PoultryScienceRootLogic rootLogic = Get.find(); + Rxn homeInformation = Rxn(); + RxBool isExpanded = false.obs; + + @override + void onReady() { + super.onReady(); + getHomePoultryHatching(); + } + + Future getHomePoultryHatching() async { + await safeCall( + call: () async => await rootLogic.poultryRepository.getHomePoultryScience( + token: rootLogic.tokenService.accessToken.value!, + type: 'home', + ), + onSuccess: (result) { + if (result != null) { + homeInformation.value = result; + } + }, + onError: (error, stackTrace) {}, + ); + } +} diff --git a/packages/chicken/lib/presentation/pages/poultry_science/home/view.dart b/packages/chicken/lib/presentation/pages/poultry_science/home/view.dart new file mode 100644 index 0000000..8f354ac --- /dev/null +++ b/packages/chicken/lib/presentation/pages/poultry_science/home/view.dart @@ -0,0 +1,608 @@ +import 'package:flutter/cupertino.dart' hide LinearGradient; +import 'package:flutter/material.dart'; +import 'package:rasadyar_chicken/data/models/response/inventory/inventory_model.dart'; +import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart'; +import 'package:rasadyar_chicken/presentation/widget/app_bar.dart'; +import 'package:rasadyar_chicken/presentation/widget/steward/widely_used/view.dart'; +import 'package:rasadyar_core/core.dart'; + +import 'logic.dart'; + +class PoultryScienceHomePage extends GetView { + const PoultryScienceHomePage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.bgLight, + appBar: chickenAppBar(hasBack: false, hasFilter: false, hasSearch: false), + body: SingleChildScrollView( + physics: BouncingScrollPhysics(), + child: Column( + spacing: 8, + children: [ + InkWell( + onTap: () { + controller.isExpanded.value = !controller.isExpanded.value; + }, + child: Card( + margin: EdgeInsetsGeometry.all(6), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(width: 0.50, color: const Color(0xFFA9A9A9)), + ), + + child: ObxValue((data) { + return AnimatedSize( + duration: Duration(milliseconds: 300), + child: data.value + ? Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + spacing: 8, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 40, + height: 40, + decoration: ShapeDecoration( + image: DecorationImage( + image: AssetImage(Assets.images.chicken.path), + fit: BoxFit.cover, + ), + shape: RoundedRectangleBorder( + side: BorderSide( + width: 0.25, + color: const Color(0xFFB0B0B0), + ), + borderRadius: BorderRadius.circular(4), + ), + ), + ), + 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), + _todayShipmentWidget(), + Row( + children: [ + Text( + 'اطلاعات جوجه ریزی', + textAlign: TextAlign.right, + style: AppFonts.yekan16, + ), + ], + ), + _inventoryWidget(), + killsShipment(), + ageWidget(), + ], + ), + ) + : Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + spacing: 8, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 40, + height: 40, + decoration: ShapeDecoration( + image: DecorationImage( + image: AssetImage(Assets.images.chicken.path), + fit: BoxFit.cover, + ), + shape: RoundedRectangleBorder( + side: BorderSide( + width: 0.25, + color: const Color(0xFFB0B0B0), + ), + borderRadius: BorderRadius.circular(4), + ), + ), + ), + Text( + 'مرغ گرم', + textAlign: TextAlign.right, + style: AppFonts.yekan16.copyWith( + color: AppColor.darkGreyDarkActive, + ), + ), + Spacer(), + Icon(CupertinoIcons.chevron_down, size: 18), + ], + ), + _todayShipmentWidget(), + _inventoryWidget(), + ], + ), + ), + ); + }, controller.isExpanded), + ), + ), + + WidelyUsedWidget(), + SizedBox(height: 20), + ], + ), + ), + ); + } + + Widget ageWidget() { + return Padding( + padding: const EdgeInsets.fromLTRB(0, 8, 0, 13), + child: ObxValue((data) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 8, + children: [ + _informationIconCard( + title: 'کمترین سن جوجه ریزیط', + isLoading: data.value == null, + description: data.value?.hatchingMinAge.separatedByComma ?? '0', + iconPath: Assets.vec.truckSvg.path, + iconColor: const Color.fromRGBO(85, 97, 93, 1), + bgDescriptionColor: const Color(0xFFE6FAF5), + bgLabelColor: const Color(0xFFB0EFDF), + ), + _informationIconCard( + title: 'بیشترین سن جوجه ریزی', + description: data.value?.hatchingMaxAge?.separatedByComma ?? '0', + iconPath: Assets.vec.convertCubeSvg.path, + iconColor: const Color(0xFF6F6164), + bgDescriptionColor: const Color(0xFFEDDCE0), + bgLabelColor: const Color(0xFFE0BCC5), + ), + ], + ); + }, controller.homeInformation), + ); + } + + Widget killsShipment() { + return Padding( + padding: const EdgeInsets.fromLTRB(0, 8, 0, 13), + child: ObxValue((data) { + return Row( + spacing: 8, + children: [ + Expanded( + child: _informationLabelCard( + title: 'تلفات', + isLoading: data.value == null, + description: data.value?.hatchingLosses?.separatedByComma ?? '0', + iconPath: Assets.vec.a3dCubeSquareSvg.path, + iconColor: const Color(0xFF6C5D60), + bgDescriptionColor: const Color(0xFFEDDCE0), + bgLabelColor: const Color(0xFFDDC0C7), + ), + ), + Expanded( + child: _informationLabelCard( + title: 'حجم کشتار شده', + isLoading: data.value == null, + description: data.value?.hatchingKilledQuantity.separatedByComma ?? '0', + iconPath: Assets.vec.cubeSearchSvg.path, + iconColor: Color(0xFF2D5FFF), + bgLabelColor: const Color(0xFFAFCBFF), + bgDescriptionColor: const Color(0xFFCEDFFF), + ), + ), + ], + ); + }, controller.homeInformation), + ); + } + + Widget _inventoryWidget() { + return ObxValue((data) { + return Padding( + padding: const EdgeInsets.fromLTRB(0, 10, 0, 13), + child: Row( + spacing: 8, + children: [ + Expanded( + child: _informationLabelCard( + title: 'حجم جوجه ریزی', + isLoading: data.value == null, + unit: 'قطعه', + description: data.value?.hatchingQuantity.separatedByComma ?? '0', + iconPath: Assets.vec.cubeSearchSvg.path, + iconColor: const Color(0xFF426060), + bgDescriptionColor: const Color(0xFFC7DFE0), + bgLabelColor: const Color(0xFFA5D1D2), + ), + ), + Expanded( + child: _informationLabelCard( + title: 'مانده در سالن', + unit: 'قطعه', + isLoading: data.value == null, + description: data.value?.hatchingLeftOver.separatedByComma ?? '0', + iconPath: Assets.vec.cubeRotateSvg.path, + iconColor: Color(0xFF5C4D64), + bgLabelColor: Color(0xFFC8B8D1), + bgDescriptionColor: Color(0xFFDAD4DD), + ), + ), + ], + ), + ); + }, controller.homeInformation); + } + + Widget _todayShipmentWidget() { + return Padding( + padding: const EdgeInsets.fromLTRB(0, 10, 0, 13), + child: Row( + spacing: 8, + children: [ + Expanded( + child: ObxValue( + (data) => _informationLabelCard( + title: 'کل فارم ها', + titleColor: AppColor.blueNormal, + isLoading: data.value == null, + description: data.value?.farmCount?.separatedByComma ?? '0', + iconPath: Assets.vec.cubeSearchSvg.path, + iconColor: AppColor.blueNormal, + bgDescriptionColor: Colors.white, + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [AppColor.blueLight, Colors.white], + ), + ), + controller.homeInformation, + ), + ), + + Expanded( + child: ObxValue((data) { + return _informationLabelCard( + title: 'تعداد جوجه ریزی ها', + isLoading: data.value == null, + description: data.value?.hatchingCount.separatedByComma ?? '0', + iconPath: Assets.vec.cubeWattingSvg.path, + bgDescriptionColor: Colors.white, + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [const Color(0xFFFFE7BB), Colors.white], + ), + ); + }, controller.homeInformation), + ), + ], + ), + ); + } + + Container _informationLabelCard({ + required String title, + required String description, + required String iconPath, + required Color bgDescriptionColor, + String unit = 'کیلوگرم', + bool isLoading = false, + Color? iconColor, + Color? titleColor, + Color? bgLabelColor, + LinearGradient? gradient, + }) { + 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: gradient == null ? bgLabelColor : null, + borderRadius: BorderRadius.only( + topRight: Radius.circular(8), + bottomRight: Radius.circular(8), + ), + gradient: gradient, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 4, + children: [ + SvgGenImage.vec(iconPath).svg( + width: 24, + height: 24, + colorFilter: iconColor != null + ? ColorFilter.mode(iconColor, BlendMode.srcIn) + : null, + ), + Text( + title, + textAlign: TextAlign.right, + style: AppFonts.yekan14.copyWith( + color: titleColor ?? 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: isLoading + ? Center(child: CupertinoActivityIndicator()) + : Column( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 4, + children: [ + Text( + description, + textAlign: TextAlign.right, + style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkActive), + ), + Text( + unit, + textAlign: TextAlign.center, + style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyDarkActive), + ), + ], + ), + ), + ), + ], + ), + ); + } + + Container _informationIconCard({ + required String title, + required String description, + String? unit, + bool isLoading = false, + required String iconPath, + required Color iconColor, + required Color bgDescriptionColor, + required Color bgLabelColor, + }) { + return Container( + height: 80.h, + width: 145.w, + 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), + ), + + isLoading + ? Center(child: CupertinoActivityIndicator()) + : Text( + description, + textAlign: TextAlign.right, + style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkActive), + ), + + Visibility( + visible: unit != null, + child: 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 inventoryItem({ + required bool isExpanded, + required int index, + required InventoryModel model, + }) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 8, + children: [ + buildRow('نام محصول', model.name ?? ''), + Visibility( + visible: isExpanded, + child: Column( + spacing: 8, + children: [ + buildRow('وزن خریدهای دولتی داخل استان (کیلوگرم)', '0326598653'), + buildRow( + 'وزن خریدهای آزاد داخل استان (کیلوگرم)', + model.receiveFreeCarcassesWeight.toString(), + ), + buildRow( + 'وزن خریدهای خارج استان (کیلوگرم)', + model.freeBuyingCarcassesWeight.toString(), + ), + buildRow( + 'کل ورودی به انبار (کیلوگرم)', + model.totalFreeBarsCarcassesWeight.toString(), + ), + buildRow('کل فروش (کیلوگرم)', model.realAllocatedWeight.toString()), + buildRow('مانده انبار (کیلوگرم)', model.totalRemainWeight.toString()), + ], + ), + ), + ], + ); + } + + Widget 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), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/packages/chicken/lib/presentation/pages/poultry_science/profile/logic.dart b/packages/chicken/lib/presentation/pages/poultry_science/profile/logic.dart new file mode 100644 index 0000000..ac1e84e --- /dev/null +++ b/packages/chicken/lib/presentation/pages/poultry_science/profile/logic.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.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/presentation/pages/poultry_science/root/logic.dart'; +import 'package:rasadyar_core/core.dart'; + +class PoultryScienceProfileLogic extends GetxController { + PoultryScienceRootLogic rootLogic = Get.find(); + RxInt selectedInformationType = 0.obs; + Rxn birthDate = Rxn(); + + Rx> userProfile = Rx>(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 cites = [].obs; + Rxn selectedProvince = Rxn(); + Rxn selectedCity = Rxn(); + + GlobalKey formKey = GlobalKey(); + ImagePicker imagePicker = ImagePicker(); + Rxn selectedImage = Rxn(); + RxnString _base64Image = RxnString(); + RxBool isOnLoading = 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(); + 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, + ); + }); + } + + @override + void onClose() { + super.onClose(); + } + + Future getUserProfile() async { + userProfile.value = Resource.loading(); + await safeCall( + call: () async => await rootLogic.chickenRepository.getUserProfile( + token: rootLogic.tokenService.accessToken.value!, + ), + onSuccess: (result) { + if (result != null) { + userProfile.value = Resource.success(result); + } + }, + onError: (error, stackTrace) {}, + ); + } + + Future getCites() async { + await safeCall( + call: () => + rootLogic.chickenRepository.getCity(provinceName: selectedProvince.value?.name ?? ''), + onSuccess: (result) { + if (result != null && result.isNotEmpty) { + cites.value = result; + } + }, + ); + } + + Future 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 rootLogic.chickenRepository.updateUserProfile( + token: rootLogic.tokenService.accessToken.value!, + userProfile: userProfile, + ), + onSuccess: (result) { + isOnLoading.value = false; + }, + onError: (error, stackTrace) { + isOnLoading.value = false; + }, + ); + } + + Future updatePassword() async { + if (formKey.currentState?.validate() ?? false) { + ChangePasswordRequestModel model = ChangePasswordRequestModel( + username: userProfile.value.data?.mobile, + password: newPasswordController.text, + ); + + await safeCall( + call: () async => await rootLogic.chickenRepository.updatePassword( + token: rootLogic.tokenService.accessToken.value!, + model: model, + ), + ); + } + } + + void clearPasswordForm() { + oldPasswordController.clear(); + newPasswordController.clear(); + retryNewPasswordController.clear(); + } +} diff --git a/packages/chicken/lib/presentation/pages/poultry_science/profile/view.dart b/packages/chicken/lib/presentation/pages/poultry_science/profile/view.dart new file mode 100644 index 0000000..b0f9ef6 --- /dev/null +++ b/packages/chicken/lib/presentation/pages/poultry_science/profile/view.dart @@ -0,0 +1,637 @@ +import 'dart:io'; + +import 'package:flutter/cupertino.dart' hide Image; +import 'package:flutter/material.dart'; +import 'package:rasadyar_chicken/chicken.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_core/core.dart'; + +import 'logic.dart'; + +class PoultryScienceProfilePage extends GetView { + const PoultryScienceProfilePage({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + spacing: 30, + children: [ + Expanded( + flex: 1, + 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: CircleAvatar( + radius: 64.w, + backgroundImage: NetworkImage(data.value.data!.image!), + ), + ), + ); + }, controller.userProfile), + ], + ), + ), + ), + Expanded( + flex: 3, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 16, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10), + child: userProfileInformation(), + ), + ), + + Center( + child: Wrap( + alignment: WrapAlignment.center, + spacing: 20, + runSpacing: 10, + children: [ + cardActionWidget( + title: 'تغییر رمز عبور', + selected: true, + onPressed: () { + Get.bottomSheet(changePasswordBottomSheet(), isScrollControlled: true); + }, + icon: Assets.vec.lockSvg.path, + ), + cardActionWidget( + title: 'خروج', + selected: true, + color: ColorFilter.mode(Colors.redAccent, BlendMode.srcIn), + cardColor: Color(0xFFEFEFEF), + textColor: AppColor.redDarkerText, + onPressed: () { + Get.bottomSheet(exitBottomSheet(), isScrollControlled: true); + }, + icon: Assets.vec.logoutSvg.path, + ), + ], + ), + ), + + 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() { + return 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) { + UserProfile item = data.value.data!; + return Column( + spacing: 6, + children: [ + buildRowOnTapped( + onTap: () { + Get.bottomSheet( + userInformationBottomSheet(), + isScrollControlled: true, + ignoreSafeArea: false, + ); + }, + titleWidget: Column( + spacing: 3, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'اطلاعات هویتی', + style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), + ), + Container(width: 37.w, height: 1.h, color: AppColor.greenNormal), + ], + ), + valueWidget: Assets.vec.editSvg.svg( + width: 24.w, + height: 24.h, + colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn), + ), + ), + itemList( + title: 'نام و نام خانوادگی', + content: item.fullname ?? 'نامشخص', + icon: Assets.vec.userSvg.path, + hasColoredBox: true, + ), + itemList( + title: 'موبایل', + content: item.mobile ?? 'نامشخص', + icon: Assets.vec.callSvg.path, + ), + itemList( + title: 'کدملی', + content: item.nationalId ?? 'نامشخص', + icon: Assets.vec.tagUserSvg.path, + ), + itemList( + title: 'شماره شناسنامه', + content: item.nationalCode ?? 'نامشخص', + icon: Assets.vec.userSquareSvg.path, + ), + itemList( + title: 'تاریخ تولد', + content: item.birthday?.toJalali.formatCompactDate() ?? 'نامشخص', + icon: Assets.vec.calendarSvg.path, + ), + itemList( + title: 'استان', + content: item.province ?? 'نامشخص', + icon: Assets.vec.pictureFrameSvg.path, + ), + itemList(title: 'شهر', content: item.city ?? 'نامشخص', icon: Assets.vec.mapSvg.path), + ], + ); + } else { + return SizedBox.shrink(); + } + }, controller.userProfile); + } + + Widget itemList({ + required String title, + required String content, + String? icon, + bool hasColoredBox = false, + }) => 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.mediumGreyNormalActive, BlendMode.srcIn), + ), + ), + Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyNormalActive)), + Spacer(), + Text(content, style: AppFonts.yekan13.copyWith(color: AppColor.mediumGreyNormalHover)), + ], + ), + ); + + Widget cardActionWidget({ + required String title, + required VoidCallback onPressed, + required String icon, + bool selected = false, + ColorFilter? color, + Color? cardColor, + Color? textColor, + }) { + return GestureDetector( + onTap: onPressed, + child: Column( + spacing: 4, + children: [ + Container( + width: 52, + height: 52, + padding: EdgeInsets.all(8), + decoration: ShapeDecoration( + color: cardColor ?? AppColor.blueLight, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + child: SvgGenImage.vec(icon).svg( + width: 40, + height: 40, + colorFilter: + color ?? + ColorFilter.mode( + selected ? AppColor.blueNormal : AppColor.whiteLight, + BlendMode.srcIn, + ), + ), + ), + SizedBox(height: 2), + Text( + title, + style: AppFonts.yekan10.copyWith( + color: textColor ?? (selected ? AppColor.blueNormal : AppColor.blueLightActive), + ), + 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 _provinceWidget() { + return Obx(() { + return OverlayDropdownWidget( + items: controller.rootLogic.provinces, + onChanged: (value) { + controller.selectedProvince.value = value; + }, + selectedItem: controller.selectedProvince.value, + itemBuilder: (item) => Text(item.name ?? 'بدون نام'), + labelBuilder: (item) => Text(item?.name ?? 'انتخاب استان'), + ); + }); + } + + Widget _cityWidget() { + return ObxValue((data) { + return OverlayDropdownWidget( + items: data, + onChanged: (value) { + controller.selectedCity.value = value; + }, + selectedItem: controller.selectedCity.value, + itemBuilder: (item) => Text(item.name ?? 'بدون نام'), + labelBuilder: (item) => Text(item?.name ?? 'انتخاب شهر'), + ); + }, controller.cites); + } + + 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 controller.rootLogic.tokenService.deleteAllTokens().then((value) { + Get.back(); + Get.offAllNamed(ChickenRoutes.auth, arguments: Module.chicken); + }); + }, + ), + ROutlinedElevated( + height: 40.h, + text: 'انصراف', + borderColor: AppColor.blueNormal, + onPressed: () { + Get.back(); + }, + ), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/packages/chicken/lib/presentation/pages/poultry_science/root/logic.dart b/packages/chicken/lib/presentation/pages/poultry_science/root/logic.dart new file mode 100644 index 0000000..5ce5e8e --- /dev/null +++ b/packages/chicken/lib/presentation/pages/poultry_science/root/logic.dart @@ -0,0 +1,71 @@ +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/inventory/inventory_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/repositories/poultry_science/poultry_science_repository.dart'; +import 'package:rasadyar_chicken/presentation/pages/poultry_science/home/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/profile/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/utils.dart'; +import 'package:rasadyar_core/core.dart'; + +enum ErrorLocationType { serviceDisabled, permissionDenied, none } + +class PoultryScienceRootLogic extends GetxController { + RxInt currentPage = 2.obs; + List pages = [BuyPage(), SalePage(), PoultryScienceHomePage(), SegmentationPage(), ProfilePage()]; + + late DioRemote dioRemote; + var tokenService = Get.find(); + late PoultryScienceRepository poultryRepository; + RxList errorLocationType = RxList(); + RxMap homeExpandedList = RxMap(); + Rxn inventoryModel = Rxn(); + RxList provinces = [].obs; + + // Cancel tokens for API calls + CancelToken? _inventoryCancelToken; + CancelToken? _provincesCancelToken; + + @override + void onInit() { + super.onInit(); + + poultryRepository = diChicken.get(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void toggleExpanded(int index) { + if (homeExpandedList.keys.contains(index)) { + homeExpandedList.remove(index); + } else { + homeExpandedList[index] = false; + } + } + + void rootErrorHandler(DioException error) { + handleGeneric(error, () { + tokenService.deleteAllTokens(); + }); + } + + void changePage(int index) { + currentPage.value = index; + } +} diff --git a/packages/chicken/lib/presentation/pages/poultry_science/root/view.dart b/packages/chicken/lib/presentation/pages/poultry_science/root/view.dart new file mode 100644 index 0000000..9a68572 --- /dev/null +++ b/packages/chicken/lib/presentation/pages/poultry_science/root/view.dart @@ -0,0 +1,128 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.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_core/core.dart'; + +import 'logic.dart'; + +class PoultryScienceRootPage extends GetView { + PoultryScienceRootPage({super.key}); + + DateTime? _lastBackPressed; + + @override + Widget build(BuildContext context) { + return ObxValue((data) { + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) async { + final nestedKey = Get.nestedKey(controller.currentPage.value); + final currentNavigator = nestedKey?.currentState; + + if (currentNavigator?.canPop() ?? false) { + currentNavigator?.pop(); + } 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(); + } + } + }, + child: Scaffold( + backgroundColor: AppColor.bgLight, + body: IndexedStack( + children: [ + Navigator( + key: Get.nestedKey(0), + 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(1), + 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(2), + onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[2]), + ), + Navigator( + key: Get.nestedKey(3), + onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[3]), + ), + Navigator( + key: Get.nestedKey(4), + onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[4]), + ), + ], + index: data.value, + ), + + bottomNavigationBar: RBottomNavigation( + mainAxisAlignment: MainAxisAlignment.spaceAround, + items: [ + RBottomNavigationItem( + label: 'اقدام', + icon: Assets.vec.settingSvg.path, + isSelected: controller.currentPage.value == 0, + onTap: () { + //Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst); + + controller.changePage(0); + }, + ), + RBottomNavigationItem( + label: 'خانه', + icon: Assets.vec.homeSvg.path, + isSelected: controller.currentPage.value == 1, + onTap: () { + /* Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst); + Get.nestedKey(0)?.currentState?.popUntil((route) => route.isFirst);*/ + controller.changePage(1); + }, + ), + RBottomNavigationItem( + label: 'پروفایل', + icon: Assets.vec.profileCircleSvg.path, + isSelected: controller.currentPage.value == 2, + onTap: () { + /* Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst); + Get.nestedKey(0)?.currentState?.popUntil((route) => route.isFirst); +*/ + controller.changePage(2); + }, + ), + ], + ), + ), + ); + }, controller.currentPage); + } + + +} diff --git a/packages/chicken/lib/presentation/routes/pages.dart b/packages/chicken/lib/presentation/routes/pages.dart index f09ad3b..9414da7 100644 --- a/packages/chicken/lib/presentation/routes/pages.dart +++ b/packages/chicken/lib/presentation/routes/pages.dart @@ -1,5 +1,8 @@ import 'package:rasadyar_chicken/presentation/pages/auth/logic.dart'; import 'package:rasadyar_chicken/presentation/pages/auth/view.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_chicken/presentation/pages/poultry_science/root/view.dart'; import 'package:rasadyar_chicken/presentation/pages/role/logic.dart'; import 'package:rasadyar_chicken/presentation/pages/role/view.dart'; import 'package:rasadyar_chicken/presentation/pages/steward/steward.dart'; @@ -136,5 +139,24 @@ sealed class ChickenPages { ), //endregion + + //region Poultry science Pages + GetPage( + name: ChickenRoutes.initPoultryScience, + page: () => PoultryScienceRootPage(), + middlewares: [AuthMiddleware()], + binding: BindingsBuilder(() { + Get.lazyPut(() => BaseLogic()); + Get.lazyPut(() => PoultryScienceRootLogic()); + Get.lazyPut(() => PoultryScienceHomeLogic()); + Get.lazyPut(() => BuyLogic()); + Get.lazyPut(() => SaleLogic()); + Get.lazyPut(() => ProfileLogic()); + Get.lazyPut(() => SegmentationLogic()); + Get.lazyPut(() => SearchLogic()); + }), + ), + + //endregion ]; }