diff --git a/flutter_nps/lib/capture/cubit/capture_cubit.dart b/flutter_nps/lib/capture/cubit/capture_cubit.dart index 8c11e2ff..8aeae7e7 100644 --- a/flutter_nps/lib/capture/cubit/capture_cubit.dart +++ b/flutter_nps/lib/capture/cubit/capture_cubit.dart @@ -12,9 +12,6 @@ import 'package:flutter_nps/flutter_nps.dart'; class CaptureCubit extends Cubit { CaptureCubit() : super(CaptureCubitState.initial()); - bool get isScoreSelected => state.score != -1; - bool get canSubmit => state.score != -1 && state.chipIndexes.isNotEmpty; - void selectScore({required int score}) => emit(state.copyWith(score: score)); void chipToogled({required int index}) => state.chipIndexes.contains(index) diff --git a/flutter_nps/lib/capture/view/capture_page.dart b/flutter_nps/lib/capture/view/capture_page.dart index 187d155f..bfe10a4e 100644 --- a/flutter_nps/lib/capture/view/capture_page.dart +++ b/flutter_nps/lib/capture/view/capture_page.dart @@ -60,34 +60,21 @@ class CaptureView extends StatelessWidget { const SizedBox(height: 16), const CaptureScoreSelectorLabels(), const SizedBox(height: 32), - AnimatedOpacity( - duration: const Duration(milliseconds: 1500), - opacity: - context.watch().isScoreSelected ? 1.0 : 0.0, - child: Column( - children: [ - const AnswerChips(), - const SizedBox(height: 32), - ElevatedButton( - key: const Key('capturePage_submit_elevatedButton'), - onPressed: context.watch().canSubmit - ? context.read().submitResult - : null, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 72, - vertical: 12, - ), - child: Text( - context.l10n.submit, - style: const TextStyle( - fontWeight: FontWeight.bold, - ), - ), - ), + BlocSelector( + selector: (state) => state.isScoreSelected, + builder: (context, isScoreSelected) { + return AnimatedOpacity( + duration: const Duration(milliseconds: 1500), + opacity: isScoreSelected ? 1.0 : 0.0, + child: Column( + children: const [ + AnswerChips(), + SizedBox(height: 32), + _SubmitButton(), + ], ), - ], - ), + ); + }, ), const SizedBox(height: 55), // TODO(Jan-Stepien): implement Need Help button @@ -109,6 +96,33 @@ class CaptureView extends StatelessWidget { } } +class _SubmitButton extends StatelessWidget { + const _SubmitButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final canSubmit = context.select( + (CaptureCubit cubit) => cubit.state.canSubmit, + ); + return ElevatedButton( + onPressed: + canSubmit ? () => context.read().submitResult() : null, + child: const Padding( + padding: EdgeInsets.symmetric( + horizontal: 72, + vertical: 12, + ), + child: Text( + Texts.submit, + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + ), + ); + } +} + class CaptureScoreSelector extends StatelessWidget { const CaptureScoreSelector({Key? key, this.radius = 30}) : super(key: key); @@ -116,44 +130,47 @@ class CaptureScoreSelector extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final maxScore = context.select( + (CaptureCubit cubit) => cubit.state.maxScore, + ); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: List.generate( - context.read().state.maxScore, - (index) => AnimatedContainer( - duration: const Duration(milliseconds: 500), - height: radius * 2, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: - context.select((CaptureCubit cubit) => cubit.state.score) - 1 == - index - ? NpsColors.colorSecondary - : NpsColors.colorGrey5, - ), - child: TextButton( - onPressed: () => - context.read().selectScore(score: index + 1), - style: ButtonStyle( - shape: MaterialStateProperty.all( - const CircleBorder(), - ), - alignment: Alignment.center, + maxScore, + (index) { + final isSelected = context.select( + (CaptureCubit cubit) => cubit.state.score - 1 == index, + ); + return AnimatedContainer( + duration: const Duration(milliseconds: 500), + height: radius * 2, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + isSelected ? NpsColors.colorSecondary : NpsColors.colorGrey5, ), - child: Text( - (index + 1).toString(), - style: Theme.of(context).textTheme.subtitle1?.copyWith( - color: context.select( - (CaptureCubit cubit) => cubit.state.score, - ) - - 1 == - index - ? NpsColors.colorWhite - : NpsColors.colorPrimary1, - ), + child: TextButton( + onPressed: () { + context.read().selectScore(score: index + 1); + }, + style: ButtonStyle( + shape: MaterialStateProperty.all( + const CircleBorder(), + ), + alignment: Alignment.center, + ), + child: Text( + (index + 1).toString(), + style: theme.textTheme.subtitle1?.copyWith( + color: isSelected + ? NpsColors.colorWhite + : NpsColors.colorPrimary1, + ), + ), ), - ), - ), + ); + }, ), ); } @@ -214,37 +231,37 @@ class AnswerChips extends StatelessWidget { alignment: WrapAlignment.center, children: List>.generate( chips.length, - (index) => [ - ActionChip( - onPressed: () => - context.read().chipToogled(index: index), - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 12, - ), - label: Text( - chips[index], - style: TextStyle( - fontWeight: FontWeight.bold, - color: context - .watch() - .state - .chipIndexes - .contains(index) - ? NpsColors.colorWhite - : NpsColors.colorPrimary1, + (index) { + final isSelected = context.select( + (CaptureCubit cubit) => cubit.state.chipIndexes.contains(index), + ); + return [ + ActionChip( + onPressed: () { + context.read().chipToogled(index: index); + }, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + label: Text( + chips[index], + style: TextStyle( + fontWeight: FontWeight.bold, + color: isSelected + ? NpsColors.colorWhite + : NpsColors.colorPrimary1, + ), ), + backgroundColor: + isSelected ? NpsColors.colorSecondary : NpsColors.colorGrey5, ), - backgroundColor: - context.watch().state.chipIndexes.contains(index) - ? NpsColors.colorSecondary - : NpsColors.colorGrey5, - ), - const SizedBox(width: 8), - ], - ).reduce( - (value, element) => [...value, ...element], - ), + const SizedBox(width: 8), + ]; + }, + ).reduce((value, element) => [...value, ...element]), ); } } + +extension on CaptureCubitState { + bool get isScoreSelected => score != -1; + bool get canSubmit => score != -1 && chipIndexes.isNotEmpty; +}