From d63288a327438c9b1c26e3eae90ce6cc79dd9698 Mon Sep 17 00:00:00 2001 From: Zied Dahmani Date: Thu, 22 Aug 2024 20:57:43 +0100 Subject: [PATCH 1/3] feat: implement logic to retrieve active proposals --- lib/core/di/bloc_module.dart | 7 +- lib/core/di/di_setup.dart | 4 + lib/core/di/repositories_module.dart | 4 +- lib/core/di/services_module.dart | 2 + lib/core/di/usecases_module.dart | 4 +- .../api/services/proposal_service.dart | 16 + lib/core/network/models/proposal_model.dart | 32 + lib/core/network/models/proposal_model.g.dart | 35 + lib/core/network/models/vote_model.dart | 18 + lib/core/network/models/vote_model.g.dart | 24 + .../repository/proposal_repository.dart | 44 ++ .../list/interactor/page_command.dart | 5 + .../list/interactor/proposals_bloc.dart | 35 + .../interactor/proposals_bloc.freezed.dart | 719 ++++++++++++++++++ .../list/interactor/proposals_event.dart | 7 + .../list/interactor/proposals_state.dart | 10 + lib/ui/proposals/list/proposals_page.dart | 29 + .../list/usecases/get_proposals_use_case.dart | 14 + 18 files changed, 1006 insertions(+), 3 deletions(-) create mode 100644 lib/core/network/api/services/proposal_service.dart create mode 100644 lib/core/network/models/proposal_model.dart create mode 100644 lib/core/network/models/proposal_model.g.dart create mode 100644 lib/core/network/models/vote_model.dart create mode 100644 lib/core/network/models/vote_model.g.dart create mode 100644 lib/core/network/repository/proposal_repository.dart create mode 100644 lib/ui/proposals/list/interactor/page_command.dart create mode 100644 lib/ui/proposals/list/interactor/proposals_bloc.dart create mode 100644 lib/ui/proposals/list/interactor/proposals_bloc.freezed.dart create mode 100644 lib/ui/proposals/list/interactor/proposals_event.dart create mode 100644 lib/ui/proposals/list/interactor/proposals_state.dart create mode 100644 lib/ui/proposals/list/proposals_page.dart create mode 100644 lib/ui/proposals/list/usecases/get_proposals_use_case.dart diff --git a/lib/core/di/bloc_module.dart b/lib/core/di/bloc_module.dart index 4b7abe64..6131407e 100644 --- a/lib/core/di/bloc_module.dart +++ b/lib/core/di/bloc_module.dart @@ -133,4 +133,9 @@ void _registerBlocsModule() { _getIt(), _getIt(), )); -} + + _registerFactory(() => ProposalsBloc( + _getIt(), + _getIt(), + )); +} \ No newline at end of file diff --git a/lib/core/di/di_setup.dart b/lib/core/di/di_setup.dart index d8fddfe7..27a1f89f 100644 --- a/lib/core/di/di_setup.dart +++ b/lib/core/di/di_setup.dart @@ -22,6 +22,7 @@ import 'package:hypha_wallet/core/network/api/services/graphql_service.dart'; import 'package:hypha_wallet/core/network/api/services/hypha_member_service.dart'; import 'package:hypha_wallet/core/network/api/services/invite_service.dart'; import 'package:hypha_wallet/core/network/api/services/pay_cpu_service.dart'; +import 'package:hypha_wallet/core/network/api/services/proposal_service.dart'; import 'package:hypha_wallet/core/network/api/services/remote_config_service.dart'; import 'package:hypha_wallet/core/network/api/services/sign_transaction_callback_service.dart'; import 'package:hypha_wallet/core/network/api/services/token_repository.dart'; @@ -34,6 +35,7 @@ import 'package:hypha_wallet/core/network/models/user_profile_data.dart'; import 'package:hypha_wallet/core/network/networking_manager.dart'; import 'package:hypha_wallet/core/network/repository/auth_repository.dart'; import 'package:hypha_wallet/core/network/repository/profile_repository.dart'; +import 'package:hypha_wallet/core/network/repository/proposal_repository.dart'; import 'package:hypha_wallet/core/network/repository/transaction_history_repository.dart'; import 'package:hypha_wallet/core/network/repository/user_account_repository.dart'; import 'package:hypha_wallet/core/shared_preferences/hypha_shared_prefs.dart'; @@ -70,6 +72,8 @@ import 'package:hypha_wallet/ui/profile/usecases/remove_avatar_use_case.dart'; import 'package:hypha_wallet/ui/profile/usecases/set_bio_use_case.dart'; import 'package:hypha_wallet/ui/profile/usecases/set_image_use_case.dart'; import 'package:hypha_wallet/ui/profile/usecases/set_name_use_case.dart'; +import 'package:hypha_wallet/ui/proposals/list/interactor/proposals_bloc.dart'; +import 'package:hypha_wallet/ui/proposals/list/usecases/get_proposals_use_case.dart'; import 'package:hypha_wallet/ui/search_user/interactor/search_user_bloc.dart'; import 'package:hypha_wallet/ui/search_user/usecases/search_for_user_use_case.dart'; import 'package:hypha_wallet/ui/settings/interactor/settings_bloc.dart'; diff --git a/lib/core/di/repositories_module.dart b/lib/core/di/repositories_module.dart index 7baadd8c..35c0a0b9 100644 --- a/lib/core/di/repositories_module.dart +++ b/lib/core/di/repositories_module.dart @@ -22,4 +22,6 @@ void _registerRepositoriesModule() { _registerLazySingleton(() => UserAccountRepository(userService: _getIt(), memberService: _getIt())); _registerLazySingleton(() => TransactionHistoryRepository(service: _getIt())); -} + + _registerLazySingleton(() => ProposalRepository(_getIt())); +} \ No newline at end of file diff --git a/lib/core/di/services_module.dart b/lib/core/di/services_module.dart index 2c59528b..45b0af22 100644 --- a/lib/core/di/services_module.dart +++ b/lib/core/di/services_module.dart @@ -42,4 +42,6 @@ Future _registerServicesModule() async { _registerLazySingleton(() => PermissionServiceImplementation()); _registerLazySingleton(() => ProfileService(_getIt())); + + _registerLazySingleton(() => ProposalService(_getIt())); } diff --git a/lib/core/di/usecases_module.dart b/lib/core/di/usecases_module.dart index 33a91a04..448bf02f 100644 --- a/lib/core/di/usecases_module.dart +++ b/lib/core/di/usecases_module.dart @@ -81,4 +81,6 @@ void _registerUseCasesModule() { )); _registerFactory(() => GetDaoNameUseCase(_getIt())); -} + + _registerFactory(() => GetProposalsUseCase(_getIt(), _getIt())); +} \ No newline at end of file diff --git a/lib/core/network/api/services/proposal_service.dart b/lib/core/network/api/services/proposal_service.dart new file mode 100644 index 00000000..4357a6b3 --- /dev/null +++ b/lib/core/network/api/services/proposal_service.dart @@ -0,0 +1,16 @@ +import 'package:hypha_wallet/core/error_handler/model/hypha_error.dart'; +import 'package:hypha_wallet/core/network/api/services/graphql_service.dart'; +import 'package:hypha_wallet/core/network/models/user_profile_data.dart'; +import 'package:hypha_wallet/ui/architecture/result/result.dart'; + +class ProposalService { + final GraphQLService _graphQLService; + + const ProposalService(this._graphQLService); + + Future, HyphaError>> getProposals(UserProfileData user) async { + final String query = r'{"query":"query Proposals($first: Int, $offset: Int) { queryDao(first: $first, offset: $offset) { details_daoName_n proposal(first: $first, offset: $offset) { docId ... on Poll { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Budget { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Queststart { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Questcomplet { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Policy { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Circle { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Payout { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignment { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignbadge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Role { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Badge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Suspend { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Edit { original { ... on Assignbadge { details_title_s } ... on Assignment { details_title_s } } details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Votable { vote { ... on Vote { vote_voter_n vote_vote_s } } } } }}"}'; + + return _graphQLService.graphQLQuery(network: user.network, query: query); + } +} \ No newline at end of file diff --git a/lib/core/network/models/proposal_model.dart b/lib/core/network/models/proposal_model.dart new file mode 100644 index 00000000..055d6adb --- /dev/null +++ b/lib/core/network/models/proposal_model.dart @@ -0,0 +1,32 @@ +import 'package:hypha_wallet/core/network/models/vote_model.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'proposal_model.g.dart'; + +@JsonSerializable() +class ProposalModel { + @JsonKey(name: 'docId') + final String id; + final String daoName; + @JsonKey(name: 'details_title_s') + final String? title; + @JsonKey(name: 'details_ballotAlignment_i') + final int? unity; + @JsonKey(name: 'details_ballotQuorum_i') + final int? quorum; + @JsonKey(name: 'ballot_expiration_t') + final DateTime? expiration; + final String creator; + @JsonKey(name: 'vote') + final List? votes; + + ProposalModel({required this.id, required this.daoName, this.title, this.unity, this.quorum, this.expiration, required this.creator, this.votes}); + + factory ProposalModel.fromJson(Map json) { + if (json.containsKey('original')) { + json['details_title_s'] = json['original'][0]['details_title_s']; + } + + return _$ProposalModelFromJson(json); + } +} \ No newline at end of file diff --git a/lib/core/network/models/proposal_model.g.dart b/lib/core/network/models/proposal_model.g.dart new file mode 100644 index 00000000..48ad656c --- /dev/null +++ b/lib/core/network/models/proposal_model.g.dart @@ -0,0 +1,35 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'proposal_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ProposalModel _$ProposalModelFromJson(Map json) => + ProposalModel( + id: json['docId'] as String, + daoName: json['daoName'] as String, + title: json['details_title_s'] as String?, + unity: (json['details_ballotAlignment_i'] as num?)?.toInt(), + quorum: (json['details_ballotQuorum_i'] as num?)?.toInt(), + expiration: json['ballot_expiration_t'] == null + ? null + : DateTime.parse(json['ballot_expiration_t'] as String), + creator: json['creator'] as String, + votes: (json['vote'] as List?) + ?.map((e) => VoteModel.fromJson(e as Map)) + .toList(), + ); + +Map _$ProposalModelToJson(ProposalModel instance) => + { + 'docId': instance.id, + 'daoName': instance.daoName, + 'details_title_s': instance.title, + 'details_ballotAlignment_i': instance.unity, + 'details_ballotQuorum_i': instance.quorum, + 'ballot_expiration_t': instance.expiration?.toIso8601String(), + 'creator': instance.creator, + 'vote': instance.votes, + }; diff --git a/lib/core/network/models/vote_model.dart b/lib/core/network/models/vote_model.dart new file mode 100644 index 00000000..0e3251dc --- /dev/null +++ b/lib/core/network/models/vote_model.dart @@ -0,0 +1,18 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'vote_model.g.dart'; + +enum VoteStatus { pass, abstain, fail, unknown } + +@JsonSerializable() +class VoteModel { + @JsonKey(name: 'vote_voter_n') + final String voter; + + @JsonKey(name: 'vote_vote_s') + final VoteStatus voteStatus; + + VoteModel(this.voter, this.voteStatus); + + factory VoteModel.fromJson(Map json) => _$VoteModelFromJson(json); +} \ No newline at end of file diff --git a/lib/core/network/models/vote_model.g.dart b/lib/core/network/models/vote_model.g.dart new file mode 100644 index 00000000..545bdf94 --- /dev/null +++ b/lib/core/network/models/vote_model.g.dart @@ -0,0 +1,24 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'vote_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +VoteModel _$VoteModelFromJson(Map json) => VoteModel( + json['vote_voter_n'] as String, + $enumDecode(_$VoteStatusEnumMap, json['vote_vote_s']), + ); + +Map _$VoteModelToJson(VoteModel instance) => { + 'vote_voter_n': instance.voter, + 'vote_vote_s': _$VoteStatusEnumMap[instance.voteStatus]!, + }; + +const _$VoteStatusEnumMap = { + VoteStatus.pass: 'pass', + VoteStatus.abstain: 'abstain', + VoteStatus.fail: 'fail', + VoteStatus.unknown: 'unknown', +}; diff --git a/lib/core/network/repository/proposal_repository.dart b/lib/core/network/repository/proposal_repository.dart new file mode 100644 index 00000000..ed544700 --- /dev/null +++ b/lib/core/network/repository/proposal_repository.dart @@ -0,0 +1,44 @@ +import 'package:hypha_wallet/core/error_handler/model/hypha_error.dart'; +import 'package:hypha_wallet/core/logging/log_helper.dart'; +import 'package:hypha_wallet/core/network/api/services/proposal_service.dart'; +import 'package:hypha_wallet/core/network/models/proposal_model.dart'; +import 'package:hypha_wallet/core/network/models/user_profile_data.dart'; +import 'package:hypha_wallet/ui/architecture/result/result.dart'; + +class ProposalRepository { + final ProposalService _proposalService; + + ProposalRepository(this._proposalService); + + Future, HyphaError>> getProposals(UserProfileData user) async { + final Result, HyphaError> result = await _proposalService.getProposals(user); + + if (result.isValue) { + if (result.asValue!.value['errors'] != null) { + LogHelper.e('GraphQL query failed',error: result.asValue!.value['errors']); + return Result.error(HyphaError.api('GraphQL query failed')); + } + + try { + final Map response = result.valueOrCrash; + final List proposalsData = response['data']['queryDao']; + final List proposals = proposalsData.expand((dao) { + final String daoName = dao['details_daoName_n']; + final List proposals = dao['proposal'] as List; + + return proposals.map((dynamic proposal) { + return ProposalModel.fromJson({...{'daoName': daoName}, ...proposal}); + }); + }).toList(); + + return Result.value(proposals); + } catch (e, stackTrace) { + LogHelper.e('Error parsing data into proposal model', error: e, stacktrace: stackTrace); + return Result.error(HyphaError.generic('Error parsing data into proposal model')); + } + } else { + LogHelper.e('GraphQL query failed', error: result.asError!.error); + return Result.error(result.asError!.error); + } + } +} \ No newline at end of file diff --git a/lib/ui/proposals/list/interactor/page_command.dart b/lib/ui/proposals/list/interactor/page_command.dart new file mode 100644 index 00000000..dd4437b3 --- /dev/null +++ b/lib/ui/proposals/list/interactor/page_command.dart @@ -0,0 +1,5 @@ +part of 'proposals_bloc.dart'; +@freezed +class PageCommand with _$PageCommand { + const factory PageCommand.navigateToProposalDetails(ProposalModel proposal) = _NavigateToProposalDetails; +} \ No newline at end of file diff --git a/lib/ui/proposals/list/interactor/proposals_bloc.dart b/lib/ui/proposals/list/interactor/proposals_bloc.dart new file mode 100644 index 00000000..1868cb0f --- /dev/null +++ b/lib/ui/proposals/list/interactor/proposals_bloc.dart @@ -0,0 +1,35 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:hypha_wallet/core/error_handler/error_handler_manager.dart'; +import 'package:hypha_wallet/core/error_handler/model/hypha_error.dart'; +import 'package:hypha_wallet/core/network/models/proposal_model.dart'; +import 'package:hypha_wallet/ui/architecture/interactor/page_states.dart'; +import 'package:hypha_wallet/ui/architecture/result/result.dart'; +import 'package:hypha_wallet/ui/proposals/list/usecases/get_proposals_use_case.dart'; + +part 'page_command.dart'; +part 'proposals_bloc.freezed.dart'; +part 'proposals_event.dart'; +part 'proposals_state.dart'; + +class ProposalsBloc extends Bloc { + final GetProposalsUseCase _getProposalsUseCase; + final ErrorHandlerManager _errorHandlerManager; + + ProposalsBloc(this._getProposalsUseCase, this._errorHandlerManager) : super(const ProposalsState()) { + on<_Initial>(_initial); + } + + Future _initial(_Initial event, Emitter emit) async { + emit(state.copyWith(pageState: PageState.loading)); + + final Result, HyphaError> result = await _getProposalsUseCase.run(); + + if (result.isValue) { + emit(state.copyWith(pageState: PageState.success, proposals: result.valueOrCrash)); + } else { + await _errorHandlerManager.handlerError(result.asError!.error); + emit(state.copyWith(pageState: PageState.failure)); + } + } +} \ No newline at end of file diff --git a/lib/ui/proposals/list/interactor/proposals_bloc.freezed.dart b/lib/ui/proposals/list/interactor/proposals_bloc.freezed.dart new file mode 100644 index 00000000..3ce6665f --- /dev/null +++ b/lib/ui/proposals/list/interactor/proposals_bloc.freezed.dart @@ -0,0 +1,719 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// 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 'proposals_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +/// @nodoc +mixin _$PageCommand { + ProposalModel get proposal => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult when({ + required TResult Function(ProposalModel proposal) navigateToProposalDetails, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ProposalModel proposal)? navigateToProposalDetails, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ProposalModel proposal)? navigateToProposalDetails, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_NavigateToProposalDetails value) + navigateToProposalDetails, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NavigateToProposalDetails value)? + navigateToProposalDetails, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NavigateToProposalDetails value)? + navigateToProposalDetails, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + + /// Create a copy of PageCommand + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PageCommandCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PageCommandCopyWith<$Res> { + factory $PageCommandCopyWith( + PageCommand value, $Res Function(PageCommand) then) = + _$PageCommandCopyWithImpl<$Res, PageCommand>; + @useResult + $Res call({ProposalModel proposal}); +} + +/// @nodoc +class _$PageCommandCopyWithImpl<$Res, $Val extends PageCommand> + implements $PageCommandCopyWith<$Res> { + _$PageCommandCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PageCommand + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? proposal = null, + }) { + return _then(_value.copyWith( + proposal: null == proposal + ? _value.proposal + : proposal // ignore: cast_nullable_to_non_nullable + as ProposalModel, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$NavigateToProposalDetailsImplCopyWith<$Res> + implements $PageCommandCopyWith<$Res> { + factory _$$NavigateToProposalDetailsImplCopyWith( + _$NavigateToProposalDetailsImpl value, + $Res Function(_$NavigateToProposalDetailsImpl) then) = + __$$NavigateToProposalDetailsImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ProposalModel proposal}); +} + +/// @nodoc +class __$$NavigateToProposalDetailsImplCopyWithImpl<$Res> + extends _$PageCommandCopyWithImpl<$Res, _$NavigateToProposalDetailsImpl> + implements _$$NavigateToProposalDetailsImplCopyWith<$Res> { + __$$NavigateToProposalDetailsImplCopyWithImpl( + _$NavigateToProposalDetailsImpl _value, + $Res Function(_$NavigateToProposalDetailsImpl) _then) + : super(_value, _then); + + /// Create a copy of PageCommand + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? proposal = null, + }) { + return _then(_$NavigateToProposalDetailsImpl( + null == proposal + ? _value.proposal + : proposal // ignore: cast_nullable_to_non_nullable + as ProposalModel, + )); + } +} + +/// @nodoc + +class _$NavigateToProposalDetailsImpl implements _NavigateToProposalDetails { + const _$NavigateToProposalDetailsImpl(this.proposal); + + @override + final ProposalModel proposal; + + @override + String toString() { + return 'PageCommand.navigateToProposalDetails(proposal: $proposal)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$NavigateToProposalDetailsImpl && + (identical(other.proposal, proposal) || + other.proposal == proposal)); + } + + @override + int get hashCode => Object.hash(runtimeType, proposal); + + /// Create a copy of PageCommand + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$NavigateToProposalDetailsImplCopyWith<_$NavigateToProposalDetailsImpl> + get copyWith => __$$NavigateToProposalDetailsImplCopyWithImpl< + _$NavigateToProposalDetailsImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ProposalModel proposal) navigateToProposalDetails, + }) { + return navigateToProposalDetails(proposal); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ProposalModel proposal)? navigateToProposalDetails, + }) { + return navigateToProposalDetails?.call(proposal); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ProposalModel proposal)? navigateToProposalDetails, + required TResult orElse(), + }) { + if (navigateToProposalDetails != null) { + return navigateToProposalDetails(proposal); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NavigateToProposalDetails value) + navigateToProposalDetails, + }) { + return navigateToProposalDetails(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NavigateToProposalDetails value)? + navigateToProposalDetails, + }) { + return navigateToProposalDetails?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NavigateToProposalDetails value)? + navigateToProposalDetails, + required TResult orElse(), + }) { + if (navigateToProposalDetails != null) { + return navigateToProposalDetails(this); + } + return orElse(); + } +} + +abstract class _NavigateToProposalDetails implements PageCommand { + const factory _NavigateToProposalDetails(final ProposalModel proposal) = + _$NavigateToProposalDetailsImpl; + + @override + ProposalModel get proposal; + + /// Create a copy of PageCommand + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$NavigateToProposalDetailsImplCopyWith<_$NavigateToProposalDetailsImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProposalsEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() clearPageCommand, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? clearPageCommand, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? clearPageCommand, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Initial value) initial, + required TResult Function(_ClearPageCommand value) clearPageCommand, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Initial value)? initial, + TResult? Function(_ClearPageCommand value)? clearPageCommand, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Initial value)? initial, + TResult Function(_ClearPageCommand value)? clearPageCommand, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProposalsEventCopyWith<$Res> { + factory $ProposalsEventCopyWith( + ProposalsEvent value, $Res Function(ProposalsEvent) then) = + _$ProposalsEventCopyWithImpl<$Res, ProposalsEvent>; +} + +/// @nodoc +class _$ProposalsEventCopyWithImpl<$Res, $Val extends ProposalsEvent> + implements $ProposalsEventCopyWith<$Res> { + _$ProposalsEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProposalsEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$InitialImplCopyWith<$Res> { + factory _$$InitialImplCopyWith( + _$InitialImpl value, $Res Function(_$InitialImpl) then) = + __$$InitialImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$InitialImplCopyWithImpl<$Res> + extends _$ProposalsEventCopyWithImpl<$Res, _$InitialImpl> + implements _$$InitialImplCopyWith<$Res> { + __$$InitialImplCopyWithImpl( + _$InitialImpl _value, $Res Function(_$InitialImpl) _then) + : super(_value, _then); + + /// Create a copy of ProposalsEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$InitialImpl implements _Initial { + const _$InitialImpl(); + + @override + String toString() { + return 'ProposalsEvent.initial()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$InitialImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() clearPageCommand, + }) { + return initial(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? clearPageCommand, + }) { + return initial?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? clearPageCommand, + required TResult orElse(), + }) { + if (initial != null) { + return initial(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Initial value) initial, + required TResult Function(_ClearPageCommand value) clearPageCommand, + }) { + return initial(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Initial value)? initial, + TResult? Function(_ClearPageCommand value)? clearPageCommand, + }) { + return initial?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Initial value)? initial, + TResult Function(_ClearPageCommand value)? clearPageCommand, + required TResult orElse(), + }) { + if (initial != null) { + return initial(this); + } + return orElse(); + } +} + +abstract class _Initial implements ProposalsEvent { + const factory _Initial() = _$InitialImpl; +} + +/// @nodoc +abstract class _$$ClearPageCommandImplCopyWith<$Res> { + factory _$$ClearPageCommandImplCopyWith(_$ClearPageCommandImpl value, + $Res Function(_$ClearPageCommandImpl) then) = + __$$ClearPageCommandImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$ClearPageCommandImplCopyWithImpl<$Res> + extends _$ProposalsEventCopyWithImpl<$Res, _$ClearPageCommandImpl> + implements _$$ClearPageCommandImplCopyWith<$Res> { + __$$ClearPageCommandImplCopyWithImpl(_$ClearPageCommandImpl _value, + $Res Function(_$ClearPageCommandImpl) _then) + : super(_value, _then); + + /// Create a copy of ProposalsEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$ClearPageCommandImpl implements _ClearPageCommand { + const _$ClearPageCommandImpl(); + + @override + String toString() { + return 'ProposalsEvent.clearPageCommand()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$ClearPageCommandImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() clearPageCommand, + }) { + return clearPageCommand(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? clearPageCommand, + }) { + return clearPageCommand?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? clearPageCommand, + required TResult orElse(), + }) { + if (clearPageCommand != null) { + return clearPageCommand(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Initial value) initial, + required TResult Function(_ClearPageCommand value) clearPageCommand, + }) { + return clearPageCommand(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Initial value)? initial, + TResult? Function(_ClearPageCommand value)? clearPageCommand, + }) { + return clearPageCommand?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Initial value)? initial, + TResult Function(_ClearPageCommand value)? clearPageCommand, + required TResult orElse(), + }) { + if (clearPageCommand != null) { + return clearPageCommand(this); + } + return orElse(); + } +} + +abstract class _ClearPageCommand implements ProposalsEvent { + const factory _ClearPageCommand() = _$ClearPageCommandImpl; +} + +/// @nodoc +mixin _$ProposalsState { + PageState get pageState => throw _privateConstructorUsedError; + List get proposals => throw _privateConstructorUsedError; + PageCommand? get command => throw _privateConstructorUsedError; + + /// Create a copy of ProposalsState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProposalsStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProposalsStateCopyWith<$Res> { + factory $ProposalsStateCopyWith( + ProposalsState value, $Res Function(ProposalsState) then) = + _$ProposalsStateCopyWithImpl<$Res, ProposalsState>; + @useResult + $Res call( + {PageState pageState, + List proposals, + PageCommand? command}); + + $PageCommandCopyWith<$Res>? get command; +} + +/// @nodoc +class _$ProposalsStateCopyWithImpl<$Res, $Val extends ProposalsState> + implements $ProposalsStateCopyWith<$Res> { + _$ProposalsStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProposalsState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pageState = null, + Object? proposals = null, + Object? command = freezed, + }) { + return _then(_value.copyWith( + pageState: null == pageState + ? _value.pageState + : pageState // ignore: cast_nullable_to_non_nullable + as PageState, + proposals: null == proposals + ? _value.proposals + : proposals // ignore: cast_nullable_to_non_nullable + as List, + command: freezed == command + ? _value.command + : command // ignore: cast_nullable_to_non_nullable + as PageCommand?, + ) as $Val); + } + + /// Create a copy of ProposalsState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $PageCommandCopyWith<$Res>? get command { + if (_value.command == null) { + return null; + } + + return $PageCommandCopyWith<$Res>(_value.command!, (value) { + return _then(_value.copyWith(command: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$ProposalsStateImplCopyWith<$Res> + implements $ProposalsStateCopyWith<$Res> { + factory _$$ProposalsStateImplCopyWith(_$ProposalsStateImpl value, + $Res Function(_$ProposalsStateImpl) then) = + __$$ProposalsStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {PageState pageState, + List proposals, + PageCommand? command}); + + @override + $PageCommandCopyWith<$Res>? get command; +} + +/// @nodoc +class __$$ProposalsStateImplCopyWithImpl<$Res> + extends _$ProposalsStateCopyWithImpl<$Res, _$ProposalsStateImpl> + implements _$$ProposalsStateImplCopyWith<$Res> { + __$$ProposalsStateImplCopyWithImpl( + _$ProposalsStateImpl _value, $Res Function(_$ProposalsStateImpl) _then) + : super(_value, _then); + + /// Create a copy of ProposalsState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pageState = null, + Object? proposals = null, + Object? command = freezed, + }) { + return _then(_$ProposalsStateImpl( + pageState: null == pageState + ? _value.pageState + : pageState // ignore: cast_nullable_to_non_nullable + as PageState, + proposals: null == proposals + ? _value._proposals + : proposals // ignore: cast_nullable_to_non_nullable + as List, + command: freezed == command + ? _value.command + : command // ignore: cast_nullable_to_non_nullable + as PageCommand?, + )); + } +} + +/// @nodoc + +class _$ProposalsStateImpl implements _ProposalsState { + const _$ProposalsStateImpl( + {this.pageState = PageState.initial, + final List proposals = const [], + this.command}) + : _proposals = proposals; + + @override + @JsonKey() + final PageState pageState; + final List _proposals; + @override + @JsonKey() + List get proposals { + if (_proposals is EqualUnmodifiableListView) return _proposals; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_proposals); + } + + @override + final PageCommand? command; + + @override + String toString() { + return 'ProposalsState(pageState: $pageState, proposals: $proposals, command: $command)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProposalsStateImpl && + (identical(other.pageState, pageState) || + other.pageState == pageState) && + const DeepCollectionEquality() + .equals(other._proposals, _proposals) && + (identical(other.command, command) || other.command == command)); + } + + @override + int get hashCode => Object.hash(runtimeType, pageState, + const DeepCollectionEquality().hash(_proposals), command); + + /// Create a copy of ProposalsState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProposalsStateImplCopyWith<_$ProposalsStateImpl> get copyWith => + __$$ProposalsStateImplCopyWithImpl<_$ProposalsStateImpl>( + this, _$identity); +} + +abstract class _ProposalsState implements ProposalsState { + const factory _ProposalsState( + {final PageState pageState, + final List proposals, + final PageCommand? command}) = _$ProposalsStateImpl; + + @override + PageState get pageState; + @override + List get proposals; + @override + PageCommand? get command; + + /// Create a copy of ProposalsState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProposalsStateImplCopyWith<_$ProposalsStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/ui/proposals/list/interactor/proposals_event.dart b/lib/ui/proposals/list/interactor/proposals_event.dart new file mode 100644 index 00000000..9f057d06 --- /dev/null +++ b/lib/ui/proposals/list/interactor/proposals_event.dart @@ -0,0 +1,7 @@ +part of 'proposals_bloc.dart'; + +@freezed +class ProposalsEvent with _$ProposalsEvent { + const factory ProposalsEvent.initial() = _Initial; + const factory ProposalsEvent.clearPageCommand() = _ClearPageCommand; +} \ No newline at end of file diff --git a/lib/ui/proposals/list/interactor/proposals_state.dart b/lib/ui/proposals/list/interactor/proposals_state.dart new file mode 100644 index 00000000..29923b49 --- /dev/null +++ b/lib/ui/proposals/list/interactor/proposals_state.dart @@ -0,0 +1,10 @@ +part of 'proposals_bloc.dart'; + +@freezed +class ProposalsState with _$ProposalsState { + const factory ProposalsState({ + @Default(PageState.initial) PageState pageState, + @Default([]) List proposals, + PageCommand? command, + }) = _ProposalsState; +} \ No newline at end of file diff --git a/lib/ui/proposals/list/proposals_page.dart b/lib/ui/proposals/list/proposals_page.dart new file mode 100644 index 00000000..362c4d84 --- /dev/null +++ b/lib/ui/proposals/list/proposals_page.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:get_it/get_it.dart'; +import 'package:hypha_wallet/core/network/models/proposal_model.dart'; +import 'package:hypha_wallet/ui/proposals/list/interactor/proposals_bloc.dart'; + +class ProposalsPage extends StatelessWidget { + const ProposalsPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => GetIt.I.get()..add(const ProposalsEvent.initial()), + child: BlocListener( + listenWhen: (previous, current) => previous.command != current.command, + listener: (context, state) { + state.command?.when( + navigateToProposalDetails: (ProposalModel proposal) { + // TODO: redirection + }, + ); + + context.read().add(const ProposalsEvent.clearPageCommand()); + }, + child: Container(), + ), + ); + } +} \ No newline at end of file diff --git a/lib/ui/proposals/list/usecases/get_proposals_use_case.dart b/lib/ui/proposals/list/usecases/get_proposals_use_case.dart new file mode 100644 index 00000000..b14176e2 --- /dev/null +++ b/lib/ui/proposals/list/usecases/get_proposals_use_case.dart @@ -0,0 +1,14 @@ +import 'package:hypha_wallet/core/error_handler/model/hypha_error.dart'; +import 'package:hypha_wallet/core/network/models/proposal_model.dart'; +import 'package:hypha_wallet/core/network/repository/auth_repository.dart'; +import 'package:hypha_wallet/core/network/repository/proposal_repository.dart'; +import 'package:hypha_wallet/ui/architecture/result/result.dart'; + +class GetProposalsUseCase { + final AuthRepository _authRepository; + final ProposalRepository _proposalRepository; + + GetProposalsUseCase(this._authRepository, this._proposalRepository); + + Future, HyphaError>> run() async => _proposalRepository.getProposals(_authRepository.authDataOrCrash.userProfileData); +} \ No newline at end of file From 365539c8dec8c88261a5eb22900a1c56e3f600f6 Mon Sep 17 00:00:00 2001 From: Zied Dahmani Date: Fri, 23 Aug 2024 11:00:19 +0100 Subject: [PATCH 2/3] refactor: add refresh param --- lib/core/network/models/vote_model.dart | 2 +- lib/core/network/models/vote_model.g.dart | 1 - .../list/interactor/page_command.dart | 1 + .../list/interactor/proposals_bloc.dart | 4 +- .../interactor/proposals_bloc.freezed.dart | 70 ++++++++++++++----- .../list/interactor/proposals_event.dart | 2 +- 6 files changed, 59 insertions(+), 21 deletions(-) diff --git a/lib/core/network/models/vote_model.dart b/lib/core/network/models/vote_model.dart index 0e3251dc..e0da49cd 100644 --- a/lib/core/network/models/vote_model.dart +++ b/lib/core/network/models/vote_model.dart @@ -2,7 +2,7 @@ import 'package:json_annotation/json_annotation.dart'; part 'vote_model.g.dart'; -enum VoteStatus { pass, abstain, fail, unknown } +enum VoteStatus { pass, abstain, fail } @JsonSerializable() class VoteModel { diff --git a/lib/core/network/models/vote_model.g.dart b/lib/core/network/models/vote_model.g.dart index 545bdf94..47c3eec1 100644 --- a/lib/core/network/models/vote_model.g.dart +++ b/lib/core/network/models/vote_model.g.dart @@ -20,5 +20,4 @@ const _$VoteStatusEnumMap = { VoteStatus.pass: 'pass', VoteStatus.abstain: 'abstain', VoteStatus.fail: 'fail', - VoteStatus.unknown: 'unknown', }; diff --git a/lib/ui/proposals/list/interactor/page_command.dart b/lib/ui/proposals/list/interactor/page_command.dart index dd4437b3..9238108c 100644 --- a/lib/ui/proposals/list/interactor/page_command.dart +++ b/lib/ui/proposals/list/interactor/page_command.dart @@ -1,4 +1,5 @@ part of 'proposals_bloc.dart'; + @freezed class PageCommand with _$PageCommand { const factory PageCommand.navigateToProposalDetails(ProposalModel proposal) = _NavigateToProposalDetails; diff --git a/lib/ui/proposals/list/interactor/proposals_bloc.dart b/lib/ui/proposals/list/interactor/proposals_bloc.dart index 1868cb0f..2353158e 100644 --- a/lib/ui/proposals/list/interactor/proposals_bloc.dart +++ b/lib/ui/proposals/list/interactor/proposals_bloc.dart @@ -21,7 +21,9 @@ class ProposalsBloc extends Bloc { } Future _initial(_Initial event, Emitter emit) async { - emit(state.copyWith(pageState: PageState.loading)); + if(!event.refresh) { + emit(state.copyWith(pageState: PageState.loading)); + } final Result, HyphaError> result = await _getProposalsUseCase.run(); diff --git a/lib/ui/proposals/list/interactor/proposals_bloc.freezed.dart b/lib/ui/proposals/list/interactor/proposals_bloc.freezed.dart index 3ce6665f..4bf4b2dc 100644 --- a/lib/ui/proposals/list/interactor/proposals_bloc.freezed.dart +++ b/lib/ui/proposals/list/interactor/proposals_bloc.freezed.dart @@ -245,19 +245,19 @@ abstract class _NavigateToProposalDetails implements PageCommand { mixin _$ProposalsEvent { @optionalTypeArgs TResult when({ - required TResult Function() initial, + required TResult Function(bool refresh) initial, required TResult Function() clearPageCommand, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? whenOrNull({ - TResult? Function()? initial, + TResult? Function(bool refresh)? initial, TResult? Function()? clearPageCommand, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ - TResult Function()? initial, + TResult Function(bool refresh)? initial, TResult Function()? clearPageCommand, required TResult orElse(), }) => @@ -309,6 +309,8 @@ abstract class _$$InitialImplCopyWith<$Res> { factory _$$InitialImplCopyWith( _$InitialImpl value, $Res Function(_$InitialImpl) then) = __$$InitialImplCopyWithImpl<$Res>; + @useResult + $Res call({bool refresh}); } /// @nodoc @@ -321,54 +323,80 @@ class __$$InitialImplCopyWithImpl<$Res> /// Create a copy of ProposalsEvent /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? refresh = null, + }) { + return _then(_$InitialImpl( + refresh: null == refresh + ? _value.refresh + : refresh // ignore: cast_nullable_to_non_nullable + as bool, + )); + } } /// @nodoc class _$InitialImpl implements _Initial { - const _$InitialImpl(); + const _$InitialImpl({this.refresh = false}); + + @override + @JsonKey() + final bool refresh; @override String toString() { - return 'ProposalsEvent.initial()'; + return 'ProposalsEvent.initial(refresh: $refresh)'; } @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is _$InitialImpl); + (other.runtimeType == runtimeType && + other is _$InitialImpl && + (identical(other.refresh, refresh) || other.refresh == refresh)); } @override - int get hashCode => runtimeType.hashCode; + int get hashCode => Object.hash(runtimeType, refresh); + + /// Create a copy of ProposalsEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InitialImplCopyWith<_$InitialImpl> get copyWith => + __$$InitialImplCopyWithImpl<_$InitialImpl>(this, _$identity); @override @optionalTypeArgs TResult when({ - required TResult Function() initial, + required TResult Function(bool refresh) initial, required TResult Function() clearPageCommand, }) { - return initial(); + return initial(refresh); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function()? initial, + TResult? Function(bool refresh)? initial, TResult? Function()? clearPageCommand, }) { - return initial?.call(); + return initial?.call(refresh); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function()? initial, + TResult Function(bool refresh)? initial, TResult Function()? clearPageCommand, required TResult orElse(), }) { if (initial != null) { - return initial(); + return initial(refresh); } return orElse(); } @@ -406,7 +434,15 @@ class _$InitialImpl implements _Initial { } abstract class _Initial implements ProposalsEvent { - const factory _Initial() = _$InitialImpl; + const factory _Initial({final bool refresh}) = _$InitialImpl; + + bool get refresh; + + /// Create a copy of ProposalsEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InitialImplCopyWith<_$InitialImpl> get copyWith => + throw _privateConstructorUsedError; } /// @nodoc @@ -450,7 +486,7 @@ class _$ClearPageCommandImpl implements _ClearPageCommand { @override @optionalTypeArgs TResult when({ - required TResult Function() initial, + required TResult Function(bool refresh) initial, required TResult Function() clearPageCommand, }) { return clearPageCommand(); @@ -459,7 +495,7 @@ class _$ClearPageCommandImpl implements _ClearPageCommand { @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function()? initial, + TResult? Function(bool refresh)? initial, TResult? Function()? clearPageCommand, }) { return clearPageCommand?.call(); @@ -468,7 +504,7 @@ class _$ClearPageCommandImpl implements _ClearPageCommand { @override @optionalTypeArgs TResult maybeWhen({ - TResult Function()? initial, + TResult Function(bool refresh)? initial, TResult Function()? clearPageCommand, required TResult orElse(), }) { diff --git a/lib/ui/proposals/list/interactor/proposals_event.dart b/lib/ui/proposals/list/interactor/proposals_event.dart index 9f057d06..ae742b50 100644 --- a/lib/ui/proposals/list/interactor/proposals_event.dart +++ b/lib/ui/proposals/list/interactor/proposals_event.dart @@ -2,6 +2,6 @@ part of 'proposals_bloc.dart'; @freezed class ProposalsEvent with _$ProposalsEvent { - const factory ProposalsEvent.initial() = _Initial; + const factory ProposalsEvent.initial({@Default(false) bool refresh}) = _Initial; const factory ProposalsEvent.clearPageCommand() = _ClearPageCommand; } \ No newline at end of file From 5b2c3c0bb6bce8f713abf160b1d38ed2062a9cca Mon Sep 17 00:00:00 2001 From: Zied Dahmani Date: Fri, 23 Aug 2024 11:57:04 +0100 Subject: [PATCH 3/3] refactor: add commitment field to proposal model --- lib/core/network/api/services/proposal_service.dart | 2 +- lib/core/network/models/proposal_model.dart | 5 +++-- lib/core/network/models/proposal_model.g.dart | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/core/network/api/services/proposal_service.dart b/lib/core/network/api/services/proposal_service.dart index 4357a6b3..af713131 100644 --- a/lib/core/network/api/services/proposal_service.dart +++ b/lib/core/network/api/services/proposal_service.dart @@ -9,7 +9,7 @@ class ProposalService { const ProposalService(this._graphQLService); Future, HyphaError>> getProposals(UserProfileData user) async { - final String query = r'{"query":"query Proposals($first: Int, $offset: Int) { queryDao(first: $first, offset: $offset) { details_daoName_n proposal(first: $first, offset: $offset) { docId ... on Poll { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Budget { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Queststart { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Questcomplet { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Policy { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Circle { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Payout { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignment { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignbadge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Role { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Badge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Suspend { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Edit { original { ... on Assignbadge { details_title_s } ... on Assignment { details_title_s } } details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Votable { vote { ... on Vote { vote_voter_n vote_vote_s } } } } }}"}'; + final String query = r'{"query":"query Proposals($first: Int, $offset: Int) { queryDao(first: $first, offset: $offset) { details_daoName_n proposal(first: $first, offset: $offset) { docId ... on Poll { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Budget { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Queststart { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Questcomplet { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Policy { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Circle { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Payout { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignment { details_timeShareX100_i details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignbadge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Role { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Badge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Suspend { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Edit { details_timeShareX100_i original { ... on Assignbadge { details_title_s } ... on Assignment { details_title_s } } details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Votable { vote { ... on Vote { vote_voter_n vote_vote_s } } } } }}"}'; return _graphQLService.graphQLQuery(network: user.network, query: query); } diff --git a/lib/core/network/models/proposal_model.dart b/lib/core/network/models/proposal_model.dart index 055d6adb..09fe4a02 100644 --- a/lib/core/network/models/proposal_model.dart +++ b/lib/core/network/models/proposal_model.dart @@ -8,6 +8,8 @@ class ProposalModel { @JsonKey(name: 'docId') final String id; final String daoName; + @JsonKey(name: 'details_timeShareX100_i') + final int? commitment; @JsonKey(name: 'details_title_s') final String? title; @JsonKey(name: 'details_ballotAlignment_i') @@ -20,13 +22,12 @@ class ProposalModel { @JsonKey(name: 'vote') final List? votes; - ProposalModel({required this.id, required this.daoName, this.title, this.unity, this.quorum, this.expiration, required this.creator, this.votes}); + ProposalModel({required this.id, required this.daoName, this.commitment, this.title, this.unity, this.quorum, this.expiration, required this.creator, this.votes}); factory ProposalModel.fromJson(Map json) { if (json.containsKey('original')) { json['details_title_s'] = json['original'][0]['details_title_s']; } - return _$ProposalModelFromJson(json); } } \ No newline at end of file diff --git a/lib/core/network/models/proposal_model.g.dart b/lib/core/network/models/proposal_model.g.dart index 48ad656c..a1c1672b 100644 --- a/lib/core/network/models/proposal_model.g.dart +++ b/lib/core/network/models/proposal_model.g.dart @@ -10,6 +10,7 @@ ProposalModel _$ProposalModelFromJson(Map json) => ProposalModel( id: json['docId'] as String, daoName: json['daoName'] as String, + commitment: (json['details_timeShareX100_i'] as num?)?.toInt(), title: json['details_title_s'] as String?, unity: (json['details_ballotAlignment_i'] as num?)?.toInt(), quorum: (json['details_ballotQuorum_i'] as num?)?.toInt(), @@ -26,6 +27,7 @@ Map _$ProposalModelToJson(ProposalModel instance) => { 'docId': instance.id, 'daoName': instance.daoName, + 'details_timeShareX100_i': instance.commitment, 'details_title_s': instance.title, 'details_ballotAlignment_i': instance.unity, 'details_ballotQuorum_i': instance.quorum,