Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement Proposal history section logic #339

Merged
merged 2 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading