Skip to content

Commit

Permalink
Merge pull request #339 from hypha-dao/feat/add-proposals-history-sec…
Browse files Browse the repository at this point in the history
…tion

feat: Implement Proposal history section logic
  • Loading branch information
nbetsaif authored Oct 3, 2024
2 parents a6c036f + d5de864 commit 0bb9f10
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 82 deletions.
3 changes: 3 additions & 0 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 9CX5MA4DG5;
ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 1.3.2;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down Expand Up @@ -527,6 +528,7 @@
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 9CX5MA4DG5;
ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 1.3.2;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down Expand Up @@ -556,6 +558,7 @@
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 9CX5MA4DG5;
ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 1.3.2;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down
8 changes: 8 additions & 0 deletions lib/core/network/models/dao_proposals_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:hypha_wallet/core/network/models/dao_data_model.dart';
import 'package:hypha_wallet/core/network/models/proposal_model.dart';

class DaoProposalsModel {
final DaoData dao;
final List<ProposalModel> proposals;
DaoProposalsModel({required this.dao, required this.proposals});
}
100 changes: 84 additions & 16 deletions lib/core/network/repository/proposal_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:hypha_wallet/core/logging/log_helper.dart';
import 'package:hypha_wallet/core/network/api/services/dao_service.dart';
import 'package:hypha_wallet/core/network/api/services/proposal_service.dart';
import 'package:hypha_wallet/core/network/models/dao_data_model.dart';
import 'package:hypha_wallet/core/network/models/dao_proposals_model.dart';
import 'package:hypha_wallet/core/network/models/network.dart';
import 'package:hypha_wallet/core/network/models/proposal_details_model.dart';
import 'package:hypha_wallet/core/network/models/proposal_model.dart';
Expand All @@ -25,12 +26,17 @@ class ProposalRepository {
this._daoService,
this._proposalService, this._profileService);

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);
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);
final List<Result<Map<String, dynamic>, HyphaError>> futureResults =
await Future.wait(futures);

final List<ProposalModel> allProposals = [];

Expand All @@ -46,11 +52,15 @@ class ProposalRepository {
}

try {
final List<ProposalModel> proposals = await _parseProposalsFromResponse(response, input.daos[i], input.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);
return Result.error(HyphaError.generic('Error parsing data into proposal model'));
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);
Expand All @@ -62,13 +72,69 @@ class ProposalRepository {
return Result.value(allProposals);
}

Future<List<ProposalModel>> _parseProposalsFromResponse(Map<String, dynamic> response, DaoData daoData, FilterStatus filterStatus) async {
Future<Result<List<DaoProposalsModel>, HyphaError>> getHistoryProposalsPerDao(
UserProfileData user, GetProposalsUseCaseInput input) async {
// Fetch past proposals for all DAOs
final List<Future<Result<Map<String, dynamic>, HyphaError>>> futures =
input.daos.map((DaoData dao) {
return _proposalService.getPastProposals(
user, dao.docId); // Fetch proposals using integer docId
}).toList();

final List<Result<Map<String, dynamic>, HyphaError>> futureResults =
await Future.wait(futures);

final List<DaoProposalsModel> daoProposalsList = [];

for (int i = 0; i < futureResults.length; i++) {
final Result<Map<String, dynamic>, HyphaError> result = futureResults[i];

if (result.isValue) {
final Map<String, dynamic> response = result.asValue!.value;
if (response['errors'] != null) {
LogHelper.e('GraphQL query failed', error: response['errors']);
return Result.error(HyphaError.api('GraphQL query failed'));
}

try {
// Parse proposals for the current DAO
final List<ProposalModel> proposals =
await _parseProposalsFromResponse(
response, input.daos[i], input.filterStatus);

// Create a DaoProposalsModel instance with the current DAO and its proposals
daoProposalsList
.add(DaoProposalsModel(dao: input.daos[i], proposals: 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);
}
}

// Return the list of DaoProposalsModel
return Result.value(daoProposalsList);
}

Future<List<ProposalModel>> _parseProposalsFromResponse(
Map<String, dynamic> response,
DaoData daoData,
FilterStatus filterStatus) async {
final List<dynamic> proposalsData = response['data']['queryDao'];

final List<Future<ProposalModel>> proposalFutures = proposalsData.expand((dao) {
final List<dynamic> proposals = dao[filterStatus == FilterStatus.active ? 'proposal' : 'votable'] as List<dynamic>;
final List<Future<ProposalModel>> proposalFutures =
proposalsData.expand((dao) {
final List<dynamic> proposals =
dao[filterStatus == FilterStatus.active ? 'proposal' : 'votable']
as List<dynamic>;
return proposals.map((dynamic proposal) async {
final Result<ProfileData, HyphaError> creator = await _profileService.getProfile(proposal['creator']);
final Result<ProfileData, HyphaError> creator =
await _profileService.getProfile(proposal['creator']);
proposal['creator'] = null;

final ProposalModel proposalModel = ProposalModel.fromJson(proposal);
Expand All @@ -86,7 +152,8 @@ class ProposalRepository {

void sortProposals(List<ProposalModel> proposals,) {
proposals.sort((a, b) {
final int daoNameComparison = (a.dao?.settingsDaoTitle ?? '').compareTo(b.dao?.settingsDaoTitle ?? '');
final int daoNameComparison = (a.dao?.settingsDaoTitle ?? '')
.compareTo(b.dao?.settingsDaoTitle ?? '');
if (daoNameComparison != 0) {
return daoNameComparison;
}
Expand All @@ -103,10 +170,11 @@ class ProposalRepository {
return a.expiration?.compareTo(b.expiration ?? DateTime.now()) ?? 0;
});
}

Future<Result<ProposalDetailsModel, HyphaError>> getProposalDetails(
String proposalId, UserProfileData user) async {
final Result<Map<String, dynamic>, HyphaError> result =
await _proposalService.getProposalDetails(proposalId, user);
await _proposalService.getProposalDetails(proposalId, user);
if (result.isValue) {
if (result.asValue!.value['errors'] != null) {
LogHelper.e('GraphQL query failed',
Expand All @@ -123,8 +191,8 @@ class ProposalRepository {
if (proposalDetails.votes != null) {
for (int i = 0; i < proposalDetails.votes!.length; i++) {
final Result<ProfileData, HyphaError> voterData =
await _profileService
.getProfile(proposalDetails.votes![i].voter);
await _profileService
.getProfile(proposalDetails.votes![i].voter);
if (voterData.isValue) {
proposalDetails.votes![i].voterImageUrl =
voterData.asValue!.value.avatarUrl;
Expand All @@ -145,4 +213,4 @@ class ProposalRepository {
return Result.error(result.asError!.error);
}
}
}
}
5 changes: 4 additions & 1 deletion lib/ui/proposals/history/proposals_history_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import 'package:hypha_wallet/ui/proposals/history/interactor/proposals_history_b

class ProposalsHistoryPage extends StatelessWidget {
final DaoData _dao;

const ProposalsHistoryPage(this._dao, {super.key});

// TODO(Zied): Refactor the logic to use the list of models already fetched from the proposal screen to avoid redundant fetching.
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => GetIt.I.get<ProposalsHistoryBloc>(param1: _dao)..add(const ProposalsHistoryEvent.initial()),
create: (context) => GetIt.I.get<ProposalsHistoryBloc>(param1: _dao)
..add(const ProposalsHistoryEvent.initial()),
child: const ProposalsHistoryView(),
);
}
Expand Down
77 changes: 41 additions & 36 deletions lib/ui/proposals/list/components/proposals_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get/get.dart' as GetX;
import 'package:get_it/get_it.dart';
import 'package:hypha_wallet/core/extension/proposals_filter_extension.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/design/avatar_image/hypha_avatar_image.dart';
import 'package:hypha_wallet/design/background/hypha_page_background.dart';
Expand All @@ -24,6 +23,8 @@ class ProposalsView extends StatelessWidget {

@override
Widget build(BuildContext context) {
final FilterStatus filterStatus =
context.watch<ProposalsBloc>().filterStatus;
return BlocBuilder<ProposalsBloc, ProposalsState>(
builder: (context, state) {
return HyphaPageBackground(
Expand Down Expand Up @@ -104,7 +105,7 @@ class ProposalsView extends StatelessWidget {
height: 22,
),
Text(
'${proposals.length} ${context.read<ProposalsBloc>().filterStatus.string} Proposal${proposals.length == 1 ? '' : 's'}',
'${proposals.length} ${filterStatus.string} Proposal${proposals.length == 1 ? '' : 's'}',
style: context.hyphaTextTheme.ralMediumBody
.copyWith(color: HyphaColors.midGrey),
),
Expand All @@ -121,41 +122,45 @@ class ProposalsView extends StatelessWidget {
proposals,
isScrollable: false,
),
const SizedBox(
height: 30,
SizedBox(
height:
filterStatus == FilterStatus.active
? 30
: 90,
),
Text(
'See Proposals History',
style: context
.hyphaTextTheme.ralMediumBody
.copyWith(color: HyphaColors.midGrey),
),
...List.generate(
2,
(index) {
return Container(
margin: const EdgeInsets.symmetric(
vertical: 10),
child:
const HyphaProposalHistoryCard(
dao: DaoData(
docId: 67176,
detailsDaoName:
't4rcvben2fe4',
settingsDaoTitle:
'Think-it Collective',
logoIPFSHash:
'QmVB8q28U1bjfi51reQMaU7XwP4FThWj39DrU5G8MriMS9',
logoType: 'png',
settingsDaoUrl:
'think-it-collective'),
subTitle: '1,234 Past Proposals',
));
},
),
const SizedBox(
height: 100,
)
if (filterStatus == FilterStatus.active)
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'See Proposals History',
style: context
.hyphaTextTheme.ralMediumBody
.copyWith(
color: HyphaColors.midGrey),
),
...List.generate(
state.historyProposalsPerDao
.length, (index) {
return Container(
margin:
const EdgeInsets.symmetric(
vertical: 10),
child: HyphaProposalHistoryCard(
dao: state
.historyProposalsPerDao[
index]
.dao,
subTitle:
'${state.historyProposalsPerDao[index].proposals.length} Past Proposals',
));
}),
const SizedBox(
height: 100,
)
],
),
],
),
),
Expand Down
Loading

0 comments on commit 0bb9f10

Please sign in to comment.