diff --git a/board_games_companion/assets/mockups/Board Games Companion.mockup b/board_games_companion/assets/mockups/Board Games Companion.mockup index b6d14202..ed89ae2e 100644 Binary files a/board_games_companion/assets/mockups/Board Games Companion.mockup and b/board_games_companion/assets/mockups/Board Games Companion.mockup differ diff --git a/board_games_companion/lib/common/app_text.dart b/board_games_companion/lib/common/app_text.dart index 8dcd2a84..30a1d49b 100644 --- a/board_games_companion/lib/common/app_text.dart +++ b/board_games_companion/lib/common/app_text.dart @@ -48,4 +48,6 @@ class AppText { static const enterScoreDialogDoneButtonText = 'Done'; static const filterGamesPanelClearFiltersButtonText = 'Clear filters'; + + static const playthroughsLogGamePagePlayerScoresStepTitle = 'Player scores'; } diff --git a/board_games_companion/lib/pages/edit_playthrough/edit_playthrough_page.dart b/board_games_companion/lib/pages/edit_playthrough/edit_playthrough_page.dart index b7b01f89..14a47c65 100644 --- a/board_games_companion/lib/pages/edit_playthrough/edit_playthrough_page.dart +++ b/board_games_companion/lib/pages/edit_playthrough/edit_playthrough_page.dart @@ -238,9 +238,6 @@ class _ScoresSectionState extends State<_ScoresSection> { child: _PlayerScoreTile( playerScore: viewModel.playerScores[index], playthroughId: viewModel.playthrough.id, - onUpdatePlayerScore: (num score) async { - _updatePlayerScore(viewModel.playerScores[index], score); - }, ), ); }, @@ -250,21 +247,6 @@ class _ScoresSectionState extends State<_ScoresSection> { }, ); } - - void _updatePlayerScore(PlayerScore playerScore, num newScore) { - if (newScore < 0) { - return; - } - - final String scoreText = newScore.toString(); - if (playerScore.score.value == scoreText) { - return; - } - - playerScore.updatePlayerScore(scoreText); - - setState(() {}); - } } class _PlayerScoreTile extends StatelessWidget { @@ -272,12 +254,10 @@ class _PlayerScoreTile extends StatelessWidget { Key? key, required this.playerScore, required this.playthroughId, - required this.onUpdatePlayerScore, }) : super(key: key); final PlayerScore playerScore; final String playthroughId; - final Future Function(num) onUpdatePlayerScore; @override Widget build(BuildContext context) { @@ -295,10 +275,7 @@ class _PlayerScoreTile extends StatelessWidget { ), const SizedBox(width: Dimensions.standardSpacing), Expanded( - child: _PlayerScore( - playerScore: playerScore, - onUpdatePlayerScore: onUpdatePlayerScore, - ), + child: _PlayerScore(playerScore: playerScore), ), ], ), @@ -306,39 +283,13 @@ class _PlayerScoreTile extends StatelessWidget { } } -class _PlayerScore extends StatefulWidget { +class _PlayerScore extends StatelessWidget { const _PlayerScore({ Key? key, required this.playerScore, - required this.onUpdatePlayerScore, }) : super(key: key); final PlayerScore playerScore; - final Future Function(num) onUpdatePlayerScore; - - @override - State<_PlayerScore> createState() => _PlayerScoreState(); -} - -class _PlayerScoreState extends State<_PlayerScore> { - late TextEditingController playerScoreEditingController; - late FocusNode playerScoreFocusNode; - - @override - void initState() { - super.initState(); - - playerScoreEditingController = TextEditingController(text: widget.playerScore.score.value); - playerScoreFocusNode = FocusNode(); - } - - @override - void dispose() { - playerScoreEditingController.dispose(); - playerScoreFocusNode.dispose(); - - super.dispose(); - } @override Widget build(BuildContext context) { @@ -350,13 +301,15 @@ class _PlayerScoreState extends State<_PlayerScore> { mainAxisAlignment: MainAxisAlignment.center, children: [ ChangeNotifierProvider.value( - value: widget.playerScore, - child: Consumer(builder: (_, playerScore, __) { - return Text( - '${playerScore.score.valueInt}', - style: Styles.playerScoreTextStyle, - ); - }), + value: playerScore, + child: Consumer( + builder: (_, playerScore, __) { + return Text( + '${playerScore.score.valueInt}', + style: Styles.playerScoreTextStyle, + ); + }, + ), ), const SizedBox(height: Dimensions.halfStandardSpacing), Text(AppText.editPlaythroughScorePoints, style: AppTheme.theme.textTheme.bodyText2), diff --git a/board_games_companion/lib/pages/playthroughs/playthroughs_log_game_page.dart b/board_games_companion/lib/pages/playthroughs/playthroughs_log_game_page.dart index 43288b73..2db732bf 100644 --- a/board_games_companion/lib/pages/playthroughs/playthroughs_log_game_page.dart +++ b/board_games_companion/lib/pages/playthroughs/playthroughs_log_game_page.dart @@ -4,10 +4,13 @@ import 'package:flutter/material.dart'; import 'package:numberpicker/numberpicker.dart'; import 'package:provider/provider.dart'; +import '../../common/app_text.dart'; import '../../common/app_theme.dart'; import '../../common/constants.dart'; import '../../common/dimensions.dart'; +import '../../common/styles.dart'; import '../../extensions/date_time_extensions.dart'; +import '../../mixins/enter_score_dialog.dart'; import '../../models/hive/board_game_details.dart'; import '../../models/navigation/player_page_arguments.dart'; import '../../models/player_score.dart'; @@ -18,6 +21,7 @@ import '../../widgets/common/elevated_icon_button.dart'; import '../../widgets/common/text/item_property_value_widget.dart'; import '../../widgets/player/player_avatar.dart'; import '../../widgets/playthrough/calendar_card.dart'; +import '../enter_score/enter_score_view_model.dart'; import '../players/player_page.dart'; import '../players/players_view_model.dart'; import 'playthroughs_log_game_view_model.dart'; @@ -141,7 +145,7 @@ class _LogPlaythroughStepperState extends State<_LogPlaythroughStepper> { ), ), Step( - title: const Text('Player scores'), + title: const Text(AppText.playthroughsLogGamePagePlayerScoresStepTitle), isActive: widget.viewModel.playthroughStartTime == PlaythroughStartTime.inThePast, state: widget.viewModel.playthroughStartTime == PlaythroughStartTime.now ? StepState.disabled @@ -293,7 +297,7 @@ class _LogPlaythroughStepperState extends State<_LogPlaythroughStepper> { } } -class _PlayerScoresStep extends StatelessWidget { +class _PlayerScoresStep extends StatelessWidget with EnterScoreDialogMixin { const _PlayerScoresStep({ required this.viewModel, Key? key, @@ -309,7 +313,12 @@ class _PlayerScoresStep extends StatelessWidget { child: Column( children: [ for (var playerScore in viewModel.playerScores.values) ...[ - _PlayerScore(playerScore: playerScore), + _PlayerScore( + playerScore: playerScore, + onTap: (PlayerScore playerScore) async { + await showEnterScoreDialog(context, EnterScoreViewModel(playerScore)); + }, + ), const SizedBox(height: Dimensions.standardSpacing), ] ], @@ -666,60 +675,43 @@ class _PlayerScore extends StatelessWidget { const _PlayerScore({ Key? key, required this.playerScore, + required this.onTap, }) : super(key: key); final PlayerScore playerScore; + final void Function(PlayerScore) onTap; @override Widget build(BuildContext context) { - return Row( - children: [ - SizedBox( - height: Dimensions.smallPlayerAvatarSize, - width: Dimensions.smallPlayerAvatarSize, - child: PlayerAvatar(playerScore.player), - ), - const SizedBox( - width: Dimensions.standardSpacing, - ), - Column( - children: [ - ChangeNotifierProvider.value( - value: playerScore, - child: Consumer( - builder: (_, PlayerScore playerScoreConsumer, __) { - return NumberPicker( - value: int.tryParse(playerScoreConsumer.score.value ?? '0') ?? 0, - axis: Axis.horizontal, - itemWidth: 46, - minValue: 0, - maxValue: 10000, - onChanged: (num value) { - final String valueText = value.toString(); - if (playerScoreConsumer.score.value == valueText) { - return; - } - - playerScoreConsumer.updatePlayerScore(valueText); - }, - selectedTextStyle: const TextStyle( - color: AppTheme.accentColor, - fontSize: Dimensions.doubleExtraLargeFontSize, - ), - ); - }, + return InkWell( + onTap: () => onTap(playerScore), + child: Row( + children: [ + SizedBox( + height: Dimensions.smallPlayerAvatarSize, + width: Dimensions.smallPlayerAvatarSize, + child: PlayerAvatar(playerScore.player), + ), + const SizedBox(width: Dimensions.doubleStandardSpacing), + Column( + children: [ + ChangeNotifierProvider.value( + value: playerScore, + child: Consumer( + builder: (_, PlayerScore playerScore, __) { + return Text( + '${playerScore.score.valueInt}', + style: Styles.playerScoreTextStyle, + ); + }, + ), ), - ), - const SizedBox( - height: Dimensions.halfStandardSpacing, - ), - Text( - 'points', - style: AppTheme.theme.textTheme.bodyText2, - ), - ], - ), - ], + const SizedBox(height: Dimensions.halfStandardSpacing), + Text('points', style: AppTheme.theme.textTheme.bodyText2), + ], + ), + ], + ), ); } }