Skip to content

Commit ec4686f

Browse files
LynxLynxxminikin
andauthored
fix(cat-voices): view comments in workspace page (#2169)
* fix(cat-voices): refactor proposals routing and enhance comments view in workspace header * fix(cat-voices): update comment display to use pluralization and enhance workspace proposal interaction with mouse cursor * fix: review * fix(cat-voices): optimize tab switching logic to use animation instead of recreation in proposals page --------- Co-authored-by: Oleksandr Prokhorenko <[email protected]>
1 parent 8e77f59 commit ec4686f

File tree

7 files changed

+286
-181
lines changed

7 files changed

+286
-181
lines changed

catalyst_voices/apps/voices/lib/pages/overall_spaces/space/workspace_overview.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class _BrowseMyProposals extends StatelessWidget {
4646
context.l10n.browseMyProposals,
4747
style: Theme.of(context).textTheme.bodyLarge,
4848
),
49-
onTap: () => const MyProposalsRoute().go(context),
49+
onTap: () => ProposalsRoute.myProposals().go(context),
5050
);
5151
}
5252
}

catalyst_voices/apps/voices/lib/pages/proposals/proposals_page.dart

Lines changed: 174 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -42,28 +42,6 @@ class ProposalsPage extends StatefulWidget {
4242
State<ProposalsPage> createState() => _ProposalsPageState();
4343
}
4444

45-
class _ActiveAccountBody extends StatelessWidget {
46-
const _ActiveAccountBody();
47-
48-
@override
49-
Widget build(BuildContext context) {
50-
return SliverPadding(
51-
padding: const EdgeInsets.symmetric(horizontal: 32)
52-
.add(const EdgeInsets.only(bottom: 32)),
53-
sliver: SliverList(
54-
delegate: SliverChildListDelegate(
55-
[
56-
const SizedBox(height: 16),
57-
const _Header(),
58-
const SizedBox(height: 40),
59-
const _Tabs(),
60-
],
61-
),
62-
),
63-
);
64-
}
65-
}
66-
6745
class _CampaignDetailsButton extends StatelessWidget {
6846
const _CampaignDetailsButton();
6947

@@ -282,9 +260,22 @@ class _Header extends StatelessWidget {
282260
class _ProposalsPageState extends State<ProposalsPage> {
283261
@override
284262
Widget build(BuildContext context) {
285-
return const CustomScrollView(
263+
return CustomScrollView(
286264
slivers: [
287-
_ActiveAccountBody(),
265+
SliverPadding(
266+
padding: const EdgeInsets.symmetric(horizontal: 32)
267+
.add(const EdgeInsets.only(bottom: 32)),
268+
sliver: SliverList(
269+
delegate: SliverChildListDelegate(
270+
[
271+
const SizedBox(height: 16),
272+
const _Header(),
273+
const SizedBox(height: 40),
274+
_Tabs(selectMyProposalsView: widget.selectMyProposalsView),
275+
],
276+
),
277+
),
278+
),
288279
],
289280
);
290281
}
@@ -313,7 +304,9 @@ class _ProposalsPageState extends State<ProposalsPage> {
313304
}
314305

315306
class _TabBar extends StatelessWidget {
316-
const _TabBar();
307+
final TabController? tabController;
308+
309+
const _TabBar(this.tabController);
317310

318311
@override
319312
Widget build(BuildContext context) {
@@ -331,6 +324,7 @@ class _TabBar extends StatelessWidget {
331324
return ConstrainedBox(
332325
constraints: const BoxConstraints(),
333326
child: TabBar(
327+
controller: tabController,
334328
isScrollable: true,
335329
tabAlignment: TabAlignment.start,
336330
dividerHeight: 0,
@@ -363,135 +357,167 @@ class _TabBar extends StatelessWidget {
363357
}
364358
}
365359

366-
class _Tabs extends StatelessWidget {
367-
const _Tabs();
360+
class _Tabs extends StatefulWidget {
361+
final bool selectMyProposalsView;
362+
363+
const _Tabs({
364+
required this.selectMyProposalsView,
365+
});
366+
367+
@override
368+
State<_Tabs> createState() => _TabsState();
369+
}
370+
371+
class _TabsState extends State<_Tabs> with SingleTickerProviderStateMixin {
372+
TabController? _tabController;
368373

369374
@override
370375
Widget build(BuildContext context) {
371-
return DefaultTabController(
372-
length: 5,
373-
initialIndex: 0,
374-
child: Column(
375-
mainAxisSize: MainAxisSize.min,
376-
crossAxisAlignment: CrossAxisAlignment.start,
377-
children: [
378-
const SizedBox(
379-
width: double.infinity,
380-
child: Wrap(
381-
alignment: WrapAlignment.spaceBetween,
382-
crossAxisAlignment: WrapCrossAlignment.end,
383-
runSpacing: 10,
384-
children: [
385-
_TabBar(),
386-
_Controls(),
387-
],
388-
),
389-
),
390-
Offstage(
391-
offstage: MediaQuery.sizeOf(context).width < 1400,
392-
child: Container(
393-
height: 1,
394-
width: double.infinity,
395-
color: context.colors.primaryContainer,
396-
),
397-
),
398-
const SizedBox(height: 24),
399-
TabBarStackView(
400-
key: const Key('ProposalsTabBarStackView'),
376+
return Column(
377+
mainAxisSize: MainAxisSize.min,
378+
crossAxisAlignment: CrossAxisAlignment.start,
379+
children: [
380+
SizedBox(
381+
width: double.infinity,
382+
child: Wrap(
383+
alignment: WrapAlignment.spaceBetween,
384+
crossAxisAlignment: WrapCrossAlignment.end,
385+
runSpacing: 10,
401386
children: [
402-
BlocSelector<ProposalsCubit, ProposalsState,
403-
ProposalPaginationViewModel>(
404-
selector: (state) {
405-
return ProposalPaginationViewModel.fromPaginationItems(
406-
paginItems: state.allProposals,
407-
isLoading: state.allProposals.isLoading,
408-
categoryId: state.selectedCategoryId,
409-
searchValue: state.searchValue,
410-
);
411-
},
412-
builder: (context, state) {
413-
return ProposalPaginationTabView(
414-
paginationViewModel: state,
415-
);
416-
},
417-
),
418-
BlocSelector<ProposalsCubit, ProposalsState,
419-
ProposalPaginationViewModel>(
420-
selector: (state) {
421-
return ProposalPaginationViewModel.fromPaginationItems(
422-
paginItems: state.draftProposals,
423-
isLoading: state.draftProposals.isLoading,
424-
categoryId: state.selectedCategoryId,
425-
searchValue: state.searchValue,
426-
);
427-
},
428-
builder: (context, state) {
429-
return ProposalPaginationTabView(
430-
key: const Key('draftProposalsPagination'),
431-
paginationViewModel: state,
432-
stage: ProposalPublish.publishedDraft,
433-
);
434-
},
435-
),
436-
BlocSelector<ProposalsCubit, ProposalsState,
437-
ProposalPaginationViewModel>(
438-
selector: (state) {
439-
return ProposalPaginationViewModel.fromPaginationItems(
440-
paginItems: state.finalProposals,
441-
isLoading: state.finalProposals.isLoading,
442-
categoryId: state.selectedCategoryId,
443-
searchValue: state.searchValue,
444-
);
445-
},
446-
builder: (context, state) {
447-
return ProposalPaginationTabView(
448-
key: const Key('finalProposalsPagination'),
449-
paginationViewModel: state,
450-
stage: ProposalPublish.submittedProposal,
451-
);
452-
},
453-
),
454-
BlocSelector<ProposalsCubit, ProposalsState,
455-
ProposalPaginationViewModel>(
456-
selector: (state) {
457-
return ProposalPaginationViewModel.fromPaginationItems(
458-
paginItems: state.favoriteProposals,
459-
isLoading: state.favoriteProposals.isLoading,
460-
categoryId: state.selectedCategoryId,
461-
searchValue: state.searchValue,
462-
);
463-
},
464-
builder: (context, state) {
465-
return ProposalPaginationTabView(
466-
key: const Key('favoriteProposalsPagination'),
467-
paginationViewModel: state,
468-
usersFavorite: true,
469-
);
470-
},
471-
),
472-
BlocSelector<ProposalsCubit, ProposalsState,
473-
ProposalPaginationViewModel>(
474-
selector: (state) {
475-
return ProposalPaginationViewModel.fromPaginationItems(
476-
paginItems: state.userProposals,
477-
isLoading: state.userProposals.isLoading,
478-
categoryId: state.selectedCategoryId,
479-
searchValue: state.searchValue,
480-
);
481-
},
482-
builder: (context, state) {
483-
return ProposalPaginationTabView(
484-
key: const Key('userProposalsPagination'),
485-
paginationViewModel: state,
486-
userProposals: true,
487-
);
488-
},
489-
),
387+
_TabBar(_tabController),
388+
const _Controls(),
490389
],
491390
),
492-
const SizedBox(height: 12),
493-
],
494-
),
391+
),
392+
Offstage(
393+
offstage: MediaQuery.sizeOf(context).width < 1400,
394+
child: Container(
395+
height: 1,
396+
width: double.infinity,
397+
color: context.colors.primaryContainer,
398+
),
399+
),
400+
const SizedBox(height: 24),
401+
TabBarStackView(
402+
key: const Key('ProposalsTabBarStackView'),
403+
controller: _tabController,
404+
children: [
405+
BlocSelector<ProposalsCubit, ProposalsState,
406+
ProposalPaginationViewModel>(
407+
selector: (state) {
408+
return ProposalPaginationViewModel.fromPaginationItems(
409+
paginItems: state.allProposals,
410+
isLoading: state.allProposals.isLoading,
411+
categoryId: state.selectedCategoryId,
412+
searchValue: state.searchValue,
413+
);
414+
},
415+
builder: (context, state) {
416+
return ProposalPaginationTabView(
417+
paginationViewModel: state,
418+
);
419+
},
420+
),
421+
BlocSelector<ProposalsCubit, ProposalsState,
422+
ProposalPaginationViewModel>(
423+
selector: (state) {
424+
return ProposalPaginationViewModel.fromPaginationItems(
425+
paginItems: state.draftProposals,
426+
isLoading: state.draftProposals.isLoading,
427+
categoryId: state.selectedCategoryId,
428+
searchValue: state.searchValue,
429+
);
430+
},
431+
builder: (context, state) {
432+
return ProposalPaginationTabView(
433+
key: const Key('draftProposalsPagination'),
434+
paginationViewModel: state,
435+
stage: ProposalPublish.publishedDraft,
436+
);
437+
},
438+
),
439+
BlocSelector<ProposalsCubit, ProposalsState,
440+
ProposalPaginationViewModel>(
441+
selector: (state) {
442+
return ProposalPaginationViewModel.fromPaginationItems(
443+
paginItems: state.finalProposals,
444+
isLoading: state.finalProposals.isLoading,
445+
categoryId: state.selectedCategoryId,
446+
searchValue: state.searchValue,
447+
);
448+
},
449+
builder: (context, state) {
450+
return ProposalPaginationTabView(
451+
key: const Key('finalProposalsPagination'),
452+
paginationViewModel: state,
453+
stage: ProposalPublish.submittedProposal,
454+
);
455+
},
456+
),
457+
BlocSelector<ProposalsCubit, ProposalsState,
458+
ProposalPaginationViewModel>(
459+
selector: (state) {
460+
return ProposalPaginationViewModel.fromPaginationItems(
461+
paginItems: state.favoriteProposals,
462+
isLoading: state.favoriteProposals.isLoading,
463+
categoryId: state.selectedCategoryId,
464+
searchValue: state.searchValue,
465+
);
466+
},
467+
builder: (context, state) {
468+
return ProposalPaginationTabView(
469+
key: const Key('favoriteProposalsPagination'),
470+
paginationViewModel: state,
471+
usersFavorite: true,
472+
);
473+
},
474+
),
475+
BlocSelector<ProposalsCubit, ProposalsState,
476+
ProposalPaginationViewModel>(
477+
selector: (state) {
478+
return ProposalPaginationViewModel.fromPaginationItems(
479+
paginItems: state.userProposals,
480+
isLoading: state.userProposals.isLoading,
481+
categoryId: state.selectedCategoryId,
482+
searchValue: state.searchValue,
483+
);
484+
},
485+
builder: (context, state) {
486+
return ProposalPaginationTabView(
487+
key: const Key('userProposalsPagination'),
488+
paginationViewModel: state,
489+
userProposals: true,
490+
);
491+
},
492+
),
493+
],
494+
),
495+
const SizedBox(height: 12),
496+
],
495497
);
496498
}
499+
500+
@override
501+
void didUpdateWidget(_Tabs oldWidget) {
502+
super.didUpdateWidget(oldWidget);
503+
if (oldWidget.selectMyProposalsView != widget.selectMyProposalsView) {
504+
final index = widget.selectMyProposalsView ? 4 : 0;
505+
_tabController?.animateTo(index);
506+
}
507+
}
508+
509+
@override
510+
void dispose() {
511+
_tabController?.dispose();
512+
_tabController = null;
513+
super.dispose();
514+
}
515+
516+
@override
517+
void initState() {
518+
super.initState();
519+
final initialIndex = widget.selectMyProposalsView ? 4 : 0;
520+
_tabController =
521+
TabController(length: 5, vsync: this, initialIndex: initialIndex);
522+
}
497523
}

0 commit comments

Comments
 (0)