Skip to content

Commit

Permalink
Merge branch 'main' into feat/tokens-view-toggle
Browse files Browse the repository at this point in the history
# Conflicts:
#	lib/ui/proposals/details/components/proposal_details_view.dart
  • Loading branch information
nbetsaif committed Sep 27, 2024
2 parents 8fb5bfb + 763b66a commit ca0d395
Show file tree
Hide file tree
Showing 26 changed files with 670 additions and 166 deletions.
11 changes: 9 additions & 2 deletions lib/core/di/bloc_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,14 @@ void _registerBlocsModule() {
_getIt<ProposalsBloc>(),
_getIt<FetchProfileUseCase>(),
_getIt<AggregateDaoProposalCountsUseCase>(),
_getIt<GetDaosFromProposalCountsUseCase>(),
_getIt<ErrorHandlerManager>(),
));
}

_registerFactoryWithParams<ProposalsHistoryBloc, DaoData, void>(
(dao, _) => ProposalsHistoryBloc(
_getIt<GetProposalsUseCase>(),
_getIt<ErrorHandlerManager>(),
dao
),
);
}
3 changes: 2 additions & 1 deletion lib/core/di/di_setup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import 'package:hypha_wallet/core/network/api/services/token_service.dart';
import 'package:hypha_wallet/core/network/api/services/transaction_history_service.dart';
import 'package:hypha_wallet/core/network/api/services/user_account_service.dart';
import 'package:hypha_wallet/core/network/ipfs/ipfs_manager.dart';
import 'package:hypha_wallet/core/network/models/dao_data_model.dart';
import 'package:hypha_wallet/core/network/models/network.dart';
import 'package:hypha_wallet/core/network/models/user_profile_data.dart';
import 'package:hypha_wallet/core/network/networking_manager.dart';
Expand Down Expand Up @@ -75,7 +76,7 @@ import 'package:hypha_wallet/ui/profile/usecases/set_name_use_case.dart';
import 'package:hypha_wallet/ui/proposals/details/usecases/get_proposal_details_use_case.dart';
import 'package:hypha_wallet/ui/proposals/filter/interactor/filter_proposals_bloc.dart';
import 'package:hypha_wallet/ui/proposals/filter/usecases/aggregate_dao_proposal_counts_use_case.dart';
import 'package:hypha_wallet/ui/proposals/filter/usecases/get_daos_from_proposal_counts_use_case.dart';
import 'package:hypha_wallet/ui/proposals/history/interactor/proposals_history_bloc.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';
Expand Down
4 changes: 1 addition & 3 deletions lib/core/di/usecases_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,4 @@ void _registerUseCasesModule() {
_registerFactory(() => GetProposalDetailsUseCase(_getIt<AuthRepository>(), _getIt<ProposalRepository>()));

_registerFactory(() => AggregateDaoProposalCountsUseCase());

_registerFactory(() => GetDaosFromProposalCountsUseCase());
}
}
1 change: 1 addition & 0 deletions lib/core/extension/base_proposal_model_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:hypha_wallet/core/network/models/base_proposal_model.dart';

extension BaseProposalModelExtension on BaseProposalModel {
String formatExpiration() {
// TODO(Zied-Saif): use another word instead of 'Expired'
if (expiration == null) return 'Expired';

if (isExpired()) {
Expand Down
7 changes: 7 additions & 0 deletions lib/core/extension/proposals_filter_extension.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:hypha_wallet/core/network/models/proposal_model.dart';

extension ProposalFilterExtension on List<ProposalModel> {
List<ProposalModel> filterByDao(List<int> daoIds) {
return where((proposal) => daoIds.contains(proposal.dao?.docId)).toList();
}
}
1 change: 1 addition & 0 deletions lib/core/extension/string_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ extension NullableStringExtension on String? {

extension StringExtension on String {
// convert blockchain quantity to double, e.g. "1.0000 SEEDS"
// This parses a the value of type "Asset" and returns it as double
double get quantityAsDouble {
final List<String> parts = split(' ');
return double.parse(parts[0]);
Expand Down
62 changes: 34 additions & 28 deletions lib/core/network/models/proposal_details_model.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:hypha_wallet/core/extension/string_extension.dart'; // Add this import
import 'package:hypha_wallet/core/network/models/base_proposal_model.dart';
import 'package:hypha_wallet/core/network/models/dao_data_model.dart';
import 'package:hypha_wallet/core/network/models/vote_model.dart';
Expand All @@ -8,6 +9,13 @@ part 'proposal_details_model.g.dart';

@JsonSerializable()
class ProposalDetailsModel extends BaseProposalModel {
double? get utilityAmountDouble => utilityAmount?.quantityAsDouble;
double? get voiceAmountDouble => voiceAmount?.quantityAsDouble;
double? get cashAmountDouble => cashAmount?.quantityAsDouble;
double? get utilityAmountPerPeriodDouble => utilityAmountPerPeriod?.quantityAsDouble;
double? get voiceAmountPerPeriodDouble => voiceAmountPerPeriod?.quantityAsDouble;
double? get cashAmountPerPeriodDouble => cashAmountPerPeriod?.quantityAsDouble;

@JsonKey(name: '__typename')
final String type;

Expand Down Expand Up @@ -44,37 +52,35 @@ class ProposalDetailsModel extends BaseProposalModel {
@JsonKey(name: 'details_description_s')
final String? description;

ProposalDetailsModel({
required super.id,
required this.type,
required this.creationDate,
super.dao,
super.commitment,
super.title,
super.unity,
super.quorum,
super.expiration,
super.creator,
super.votes,
this.tokenMixPercentage,
this.cycleCount,
this.cycleStartDate,
this.utilityAmount,
this.voiceAmount,
this.cashAmount,
this.utilityAmountPerPeriod,
this.voiceAmountPerPeriod,
this.cashAmountPerPeriod,
this.description
});
ProposalDetailsModel(
{required super.id,
required this.type,
required this.creationDate,
super.dao,
super.commitment,
super.title,
super.unity,
super.quorum,
super.expiration,
super.creator,
super.votes,
this.tokenMixPercentage,
this.cycleCount,
this.cycleStartDate,
this.utilityAmount,
this.voiceAmount,
this.cashAmount,
this.utilityAmountPerPeriod,
this.voiceAmountPerPeriod,
this.cashAmountPerPeriod,
this.description});

factory ProposalDetailsModel.fromJson(Map<String, dynamic> json) {
if(json['start'] is List){
if((json['start'] as List).isNotEmpty){
if (json['start'] is List) {
if ((json['start'] as List).isNotEmpty) {
json['start'] = json['start'][0]['details_startTime_t'];
}
else{
json['start']=null;
} else {
json['start'] = null;
}
}
// TODO(Saif): check this
Expand Down
9 changes: 5 additions & 4 deletions lib/core/network/repository/proposal_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import 'package:hypha_wallet/core/network/repository/profile_repository.dart';
import 'package:hypha_wallet/ui/architecture/result/result.dart';
import 'package:hypha_wallet/ui/profile/interactor/profile_data.dart';
import 'package:hypha_wallet/ui/proposals/filter/interactor/filter_status.dart';
import 'package:hypha_wallet/ui/proposals/list/interactor/get_proposals_use_case_input.dart';

class ProposalRepository {
final ProposalService _proposalService;
final ProfileService _profileService;

ProposalRepository(this._proposalService, this._profileService);

Future<Result<List<ProposalModel>, HyphaError>> getProposals(UserProfileData user, List<DaoData> daos, FilterStatus filterStatus) async {
final List<Future<Result<Map<String, dynamic>, HyphaError>>> futures = daos.map((DaoData dao) {
return filterStatus == FilterStatus.active ? _proposalService.getActiveProposals(user, dao.docId) : _proposalService.getPastProposals(user, dao.docId);
Future<Result<List<ProposalModel>, HyphaError>> getProposals(UserProfileData user, GetProposalsUseCaseInput input) async {
final List<Future<Result<Map<String, dynamic>, HyphaError>>> futures = input.daos.map((DaoData dao) {
return input.filterStatus == FilterStatus.active ? _proposalService.getActiveProposals(user, dao.docId) : _proposalService.getPastProposals(user, dao.docId);
}).toList();

final List<Result<Map<String, dynamic>, HyphaError>> futureResults = await Future.wait(futures);
Expand All @@ -38,7 +39,7 @@ class ProposalRepository {
}

try {
final List<ProposalModel> proposals = await _parseProposalsFromResponse(response, daos[i], filterStatus);
final List<ProposalModel> proposals = await _parseProposalsFromResponse(response, input.daos[i], input.filterStatus);
allProposals.addAll(proposals);
} catch (e, stackTrace) {
LogHelper.e('Error parsing data into proposal model', error: e, stacktrace: stackTrace);
Expand Down
20 changes: 20 additions & 0 deletions lib/ui/proposals/components/proposals_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
import 'package:hypha_wallet/core/network/models/proposal_model.dart';
import 'package:hypha_wallet/ui/proposals/list/components/hypha_proposals_action_card.dart';

class ProposalsList extends StatelessWidget {
final List<ProposalModel> proposals;

const ProposalsList(this.proposals, {super.key});

@override
Widget build(BuildContext context) {
return ListView.separated(
padding: const EdgeInsets.only(bottom: 22),
itemBuilder: (BuildContext context, int index) => HyphaProposalsActionCard(proposals[index]),
separatorBuilder: (BuildContext context, int index) {
return const SizedBox(height: 16);
},
itemCount: proposals.length);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ class FilterProposalsView extends StatelessWidget {
HyphaAppButton(
title: 'SAVE FILTERS',
onPressed: () {
filterProposalsBloc.add(FilterProposalsEvent.saveFilters(filterProposalsBloc.selectedDaoIndexNotifier.value == null ? state.daoProposalCounts: [state.daoProposalCounts[filterProposalsBloc.selectedDaoIndexNotifier.value!]], filterProposalsBloc.selectedStatusIndexNotifier.value == 0 ? FilterStatus.active : FilterStatus.past));
final int? index = filterProposalsBloc.selectedDaoIndexNotifier.value;
filterProposalsBloc.add(FilterProposalsEvent.saveFilters(index == null ? state.daoProposalCounts : [state.daoProposalCounts[index]], filterProposalsBloc.selectedStatusIndexNotifier.value == 0 ? FilterStatus.active : FilterStatus.past));
},
),
const SizedBox(
Expand Down
6 changes: 2 additions & 4 deletions lib/ui/proposals/filter/components/hypha_filter_card.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import 'package:flutter/material.dart';
import 'package:hypha_wallet/core/network/models/dao_data_model.dart';
import 'package:hypha_wallet/design/avatar_image/hypha_avatar_image.dart';
import 'package:hypha_wallet/design/dao_image.dart';
import 'package:hypha_wallet/design/hypha_card.dart';
import 'package:hypha_wallet/design/hypha_colors.dart';
import 'package:hypha_wallet/design/ipfs_image.dart';
import 'package:hypha_wallet/design/themes/extensions/theme_extension_provider.dart';
import 'package:hypha_wallet/design/dao_image.dart';

class HyphaFilterCard extends StatelessWidget {
final DaoData? dao;
Expand All @@ -21,7 +19,7 @@ class HyphaFilterCard extends StatelessWidget {
// TODO(Saif): fix the card height (filter by status)
return GestureDetector(
onTap: () {
valueNotifier.value = index;
valueNotifier.value = valueNotifier.value == index ? null : index;
},
child: HyphaCard(
child: Padding(
Expand Down
10 changes: 5 additions & 5 deletions lib/ui/proposals/filter/interactor/filter_proposals_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import 'package:hypha_wallet/ui/profile/usecases/fetch_profile_use_case.dart';
import 'package:hypha_wallet/ui/proposals/filter/interactor/dao_proposal_count_entity.dart';
import 'package:hypha_wallet/ui/proposals/filter/interactor/filter_status.dart';
import 'package:hypha_wallet/ui/proposals/filter/usecases/aggregate_dao_proposal_counts_use_case.dart';
import 'package:hypha_wallet/ui/proposals/filter/usecases/get_daos_from_proposal_counts_use_case.dart';
import 'package:hypha_wallet/ui/proposals/list/interactor/proposals_bloc.dart';

part 'page_command.dart';
Expand All @@ -23,14 +22,12 @@ class FilterProposalsBloc extends Bloc<FilterProposalsEvent, FilterProposalsStat
final ProposalsBloc _proposalsBloc;
final FetchProfileUseCase _fetchProfileUseCase;
final AggregateDaoProposalCountsUseCase _aggregateDaoProposalCountsUseCase;
final GetDaosFromProposalCountsUseCase _getDaosFromProposalCountsUseCase;
final ErrorHandlerManager _errorHandlerManager;

FilterProposalsBloc(
this._proposalsBloc,
this._fetchProfileUseCase,
this._aggregateDaoProposalCountsUseCase,
this._getDaosFromProposalCountsUseCase,
this._errorHandlerManager,
) : super(const FilterProposalsState()) {
on<_Initial>(_initial);
Expand All @@ -40,11 +37,13 @@ class FilterProposalsBloc extends Bloc<FilterProposalsEvent, FilterProposalsStat
add(const FilterProposalsEvent.initial());
}

final ValueNotifier<int?> _selectedDaoIndexNotifier = ValueNotifier<int?>(null);
final ValueNotifier<int?> _selectedDaoIndexNotifier = ValueNotifier<int?>(0);
final ValueNotifier<int> _selectedStatusIndexNotifier = ValueNotifier<int>(0);
List<int>? _daoIds;

ValueNotifier<int?> get selectedDaoIndexNotifier => _selectedDaoIndexNotifier;
ValueNotifier<int> get selectedStatusIndexNotifier => _selectedStatusIndexNotifier;
List<int>? get daoIds => _daoIds;

Future<void> _initial(_Initial event, Emitter<FilterProposalsState> emit) async {
emit(state.copyWith(pageState: PageState.loading));
Expand Down Expand Up @@ -76,7 +75,8 @@ class FilterProposalsBloc extends Bloc<FilterProposalsEvent, FilterProposalsStat
}

Future<void> _saveFilters(_SaveFilters event, Emitter<FilterProposalsState> emit) async {
_proposalsBloc.add(ProposalsEvent.initial(daos: _getDaosFromProposalCountsUseCase.run(event.daoProposalCounts), filterStatus: event.filterStatus));
_daoIds = event.daoProposalCounts.map((DaoProposalCountEntity daoProposalCount) => daoProposalCount.dao.docId).toList();
_proposalsBloc.add(ProposalsEvent.initial(filterStatus: event.filterStatus));
emit(state.copyWith(command: const PageCommand.navigateToProposals()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ class AggregateDaoProposalCountsUseCase {
}
}

return daoProposalCounts.entries
.map((entry) => DaoProposalCountEntity(entry.key, entry.value))
.toList();
final List<MapEntry<DaoData, int>> sortedEntries = daoProposalCounts.entries.toList()
..sort((a, b) => a.key.settingsDaoTitle.compareTo(b.key.settingsDaoTitle));

return sortedEntries.map((entry) => DaoProposalCountEntity(entry.key, entry.value)).toList();
}
}

This file was deleted.

35 changes: 35 additions & 0 deletions lib/ui/proposals/history/components/proposals_history_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get/get.dart';
import 'package:hypha_wallet/design/hypha_colors.dart';
import 'package:hypha_wallet/ui/proposals/components/proposals_list.dart';
import 'package:hypha_wallet/ui/proposals/history/interactor/proposals_history_bloc.dart';
import 'package:hypha_wallet/ui/shared/hypha_body_widget.dart';

class ProposalsHistoryView extends StatelessWidget {
const ProposalsHistoryView({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: context.isDarkMode ? HyphaColors.darkBlack : HyphaColors.offWhite,
appBar: AppBar(
title: const Text('Proposals History'),
),
body: RefreshIndicator(
onRefresh: () async {
context.read<ProposalsHistoryBloc>().add(const ProposalsHistoryEvent.initial(refresh: true));
},
child: BlocBuilder<ProposalsHistoryBloc, ProposalsHistoryState>(
builder: (context, state) {
return HyphaBodyWidget(pageState: state.pageState, success: (context) {
return Container(
padding: const EdgeInsets.all(20),
child: ProposalsList(state.proposals),
);
});
}),
)
);
}
}
40 changes: 40 additions & 0 deletions lib/ui/proposals/history/interactor/proposals_history_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
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/dao_data_model.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/filter/interactor/filter_status.dart';
import 'package:hypha_wallet/ui/proposals/list/interactor/get_proposals_use_case_input.dart';
import 'package:hypha_wallet/ui/proposals/list/usecases/get_proposals_use_case.dart';

part 'proposals_history_bloc.freezed.dart';
part 'proposals_history_event.dart';
part 'proposals_history_state.dart';

class ProposalsHistoryBloc extends Bloc<ProposalsHistoryEvent, ProposalsHistoryState> {
final GetProposalsUseCase _getProposalsUseCase;
final ErrorHandlerManager _errorHandlerManager;
final DaoData _dao;

ProposalsHistoryBloc(this._getProposalsUseCase, this._errorHandlerManager, this._dao) : super(const ProposalsHistoryState()) {
on<_Initial>(_initial);
}

Future<void> _initial(_Initial event, Emitter<ProposalsHistoryState> emit) async {
if (!event.refresh) {
emit(state.copyWith(pageState: PageState.loading));
}

final Result<List<ProposalModel>, HyphaError> proposalsResult = await _getProposalsUseCase.run(GetProposalsUseCaseInput([_dao], FilterStatus.past));

if (proposalsResult.isValue) {
emit(state.copyWith(pageState: PageState.success, proposals: proposalsResult.asValue!.value));
} else {
await _errorHandlerManager.handlerError(proposalsResult.asError!.error);
emit(state.copyWith(pageState: PageState.failure));
}
}
}
Loading

0 comments on commit ca0d395

Please sign in to comment.