From 46d1c25bb56d0ebcfdd72e6d0fe8c6bbe7529aef Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 23 Nov 2025 19:41:57 +0100 Subject: [PATCH 01/27] create GameResultView with basic structure and styling --- .../views/main_menu/game_result_view.dart | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 lib/presentation/views/main_menu/game_result_view.dart diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart new file mode 100644 index 0000000..d953b0f --- /dev/null +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:game_tracker/core/custom_theme.dart'; +import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart'; + +class GameResultView extends StatefulWidget { + const GameResultView({super.key}); + + //TODO: Handle given game + + @override + State createState() => _GameResultViewState(); +} + +class _GameResultViewState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: CustomTheme.backgroundColor, + appBar: AppBar( + backgroundColor: CustomTheme.backgroundColor, + scrolledUnderElevation: 0, + title: const Text( + 'Game Result', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + centerTitle: true, + ), + body: SafeArea( + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + decoration: BoxDecoration( + color: CustomTheme.boxColor, + border: Border.all(color: CustomTheme.boxBorder), + borderRadius: BorderRadius.circular(12), + ), + child: const Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Select Winner", + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + //TODO: Add FutureBuilder + //TODO: Implement ListView.builder with RadioListTiles and Players from Game + //TODO Implement Save button with snackbar to confirm save/show error + CustomWidthButton(text: "Save", sizeRelativeToWidth: 0.95), + ], + ), + ), + ), + ); + } +} From 937f1e3ac876469080e30286f7f361bb2391f060 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 23 Nov 2025 19:42:31 +0100 Subject: [PATCH 02/27] made settingsbutton redirect to game result view --- lib/presentation/views/main_menu/custom_navigation_bar.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/presentation/views/main_menu/custom_navigation_bar.dart b/lib/presentation/views/main_menu/custom_navigation_bar.dart index 71a072e..18561c4 100644 --- a/lib/presentation/views/main_menu/custom_navigation_bar.dart +++ b/lib/presentation/views/main_menu/custom_navigation_bar.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/presentation/views/main_menu/game_history_view.dart'; +import 'package:game_tracker/presentation/views/main_menu/game_result_view.dart'; import 'package:game_tracker/presentation/views/main_menu/groups_view.dart'; import 'package:game_tracker/presentation/views/main_menu/home_view.dart'; -import 'package:game_tracker/presentation/views/main_menu/settings_view.dart'; import 'package:game_tracker/presentation/views/main_menu/statistics_view.dart'; import 'package:game_tracker/presentation/widgets/navbar_item.dart'; @@ -56,7 +56,9 @@ class _CustomNavigationBarState extends State onPressed: () async { await Navigator.push( context, - MaterialPageRoute(builder: (_) => const SettingsView()), + MaterialPageRoute( + builder: (_) => const GameResultView(), + ), //TODO Replace with Settingsview ); setState(() { tabKeyCount++; From 6dc74ca82ec58043d7881131bfdfa82cd3ed48fb Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 23 Nov 2025 20:18:26 +0100 Subject: [PATCH 03/27] Implement basic logic and UI for selecting game winners in GameResultView --- .../views/main_menu/game_result_view.dart | 107 ++++++++++++++---- 1 file changed, 85 insertions(+), 22 deletions(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index d953b0f..e39a4f3 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -1,5 +1,8 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; +import 'package:game_tracker/data/dto/game.dart'; +import 'package:game_tracker/data/dto/group.dart'; +import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart'; class GameResultView extends StatefulWidget { @@ -12,6 +15,30 @@ class GameResultView extends StatefulWidget { } class _GameResultViewState extends State { + late final List allPlayers; + final exampleGame = Game( + name: "Test Game", + players: [ + Player(name: "Petrus"), + Player(name: "Peter"), + Player(name: "Petra"), + ], + group: Group( + name: "Die Petris", + members: [ + Player(name: "Petralia"), + Player(name: "Petrenlia"), + Player(name: "Petrumlia"), + ], + ), + ); + + @override + void initState() { + allPlayers = getAllPlayers(exampleGame); + super.initState(); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -26,32 +53,68 @@ class _GameResultViewState extends State { centerTitle: true, ), body: SafeArea( - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), - decoration: BoxDecoration( - color: CustomTheme.boxColor, - border: Border.all(color: CustomTheme.boxBorder), - borderRadius: BorderRadius.circular(12), - ), - child: const Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - "Select Winner", - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, + child: Column( + children: [ + Expanded( + child: Container( + margin: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 10, + ), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 10, + ), + decoration: BoxDecoration( + color: CustomTheme.boxColor, + border: Border.all(color: CustomTheme.boxBorder), + borderRadius: BorderRadius.circular(12), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "Select Winner:", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + Expanded( + child: ListView.builder( + itemCount: allPlayers.length, + itemBuilder: (context, index) { + //TODO: Implement Custom RadioListTile, see text_icon_list_tile + return RadioListTile( + title: Text(allPlayers[index].name), + value: allPlayers[index], + ); + }, + ), + ), + ], ), ), - //TODO: Add FutureBuilder - //TODO: Implement ListView.builder with RadioListTiles and Players from Game - //TODO Implement Save button with snackbar to confirm save/show error - CustomWidthButton(text: "Save", sizeRelativeToWidth: 0.95), - ], - ), + ), + CustomWidthButton( + text: "Save", + sizeRelativeToWidth: 0.95, + onPressed: null, + ), + SizedBox(height: 10), + ], ), ), ); } + + List getAllPlayers(Game game) { + if (game.group == null && game.players != null) { + return [...game.players!]; + } else if (game.group != null && game.players != null) { + return [...game.players!, ...game.group!.members]; + } + return [...game.group!.members]; + } } From 424a258df17dc87e9a115a3fa23a0b84e1210815 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 23 Nov 2025 20:22:03 +0100 Subject: [PATCH 04/27] Update GameResultView with dummy Game data in CustomNavigationBar --- .../main_menu/custom_navigation_bar.dart | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/custom_navigation_bar.dart b/lib/presentation/views/main_menu/custom_navigation_bar.dart index 18561c4..b20f80e 100644 --- a/lib/presentation/views/main_menu/custom_navigation_bar.dart +++ b/lib/presentation/views/main_menu/custom_navigation_bar.dart @@ -1,5 +1,8 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; +import 'package:game_tracker/data/dto/game.dart'; +import 'package:game_tracker/data/dto/group.dart'; +import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/views/main_menu/game_history_view.dart'; import 'package:game_tracker/presentation/views/main_menu/game_result_view.dart'; import 'package:game_tracker/presentation/views/main_menu/groups_view.dart'; @@ -57,7 +60,24 @@ class _CustomNavigationBarState extends State await Navigator.push( context, MaterialPageRoute( - builder: (_) => const GameResultView(), + builder: (_) => GameResultView( + game: Game( + name: "Test Game", + players: [ + Player(name: "Petrus"), + Player(name: "Peter"), + Player(name: "Petra"), + ], + group: Group( + name: "Die Petris", + members: [ + Player(name: "Petralia"), + Player(name: "Petrenlia"), + Player(name: "Petrumlia"), + ], + ), + ), + ), ), //TODO Replace with Settingsview ); setState(() { From bd616c510a59d1cf278a8030f3f14239496a1a02 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 23 Nov 2025 20:22:26 +0100 Subject: [PATCH 05/27] update GameResultView to accept and use a given Game instance --- .../views/main_menu/game_result_view.dart | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index e39a4f3..9278641 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/data/dto/game.dart'; -import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart'; class GameResultView extends StatefulWidget { - const GameResultView({super.key}); + final Game game; - //TODO: Handle given game + const GameResultView({super.key, required this.game}); @override State createState() => _GameResultViewState(); @@ -16,26 +15,10 @@ class GameResultView extends StatefulWidget { class _GameResultViewState extends State { late final List allPlayers; - final exampleGame = Game( - name: "Test Game", - players: [ - Player(name: "Petrus"), - Player(name: "Peter"), - Player(name: "Petra"), - ], - group: Group( - name: "Die Petris", - members: [ - Player(name: "Petralia"), - Player(name: "Petrenlia"), - Player(name: "Petrumlia"), - ], - ), - ); @override void initState() { - allPlayers = getAllPlayers(exampleGame); + allPlayers = getAllPlayers(widget.game); super.initState(); } From 07d81d687bffd43034696fdca0f39f142785cbce Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Tue, 25 Nov 2025 17:23:03 +0100 Subject: [PATCH 06/27] Implement CustomRadioListTile and update GameResultView to select a winner currently without saving to the db --- .../views/main_menu/game_result_view.dart | 50 +++++++++++++++---- .../widgets/tiles/custom_radio_list_tile.dart | 49 ++++++++++++++++++ 2 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 lib/presentation/widgets/tiles/custom_radio_list_tile.dart diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index 9278641..aa15c2a 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -3,6 +3,8 @@ import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/data/dto/game.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart'; +import 'package:game_tracker/presentation/widgets/tiles/custom_radio_list_tile.dart'; +import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; class GameResultView extends StatefulWidget { final Game game; @@ -15,6 +17,7 @@ class GameResultView extends StatefulWidget { class _GameResultViewState extends State { late final List allPlayers; + Player? _player; @override void initState() { @@ -64,16 +67,36 @@ class _GameResultViewState extends State { fontWeight: FontWeight.bold, ), ), - Expanded( - child: ListView.builder( - itemCount: allPlayers.length, - itemBuilder: (context, index) { - //TODO: Implement Custom RadioListTile, see text_icon_list_tile - return RadioListTile( - title: Text(allPlayers[index].name), - value: allPlayers[index], - ); - }, + Visibility( + visible: allPlayers.isNotEmpty, + replacement: TopCenteredMessage( + icon: Icons.info, + title: "Info", + message: "No players in this game.", + ), + child: Expanded( + child: RadioGroup( + groupValue: _player, + onChanged: (Player? value) { + setState(() { + _player = value; + }); + }, + child: ListView.builder( + itemCount: allPlayers.length, + itemBuilder: (context, index) { + return CustomRadioListTile( + text: allPlayers[index].name, + value: allPlayers[index], + onContainerTap: (value) { + setState(() { + _player = value; + }); + }, + ); + }, + ), + ), ), ), ], @@ -83,7 +106,12 @@ class _GameResultViewState extends State { CustomWidthButton( text: "Save", sizeRelativeToWidth: 0.95, - onPressed: null, + onPressed: _player != null + ? () { + print("Selected Winner: ${_player!.name}"); + Navigator.pop(context); + } + : null, ), SizedBox(height: 10), ], diff --git a/lib/presentation/widgets/tiles/custom_radio_list_tile.dart b/lib/presentation/widgets/tiles/custom_radio_list_tile.dart new file mode 100644 index 0000000..1350239 --- /dev/null +++ b/lib/presentation/widgets/tiles/custom_radio_list_tile.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:game_tracker/core/custom_theme.dart'; + +class CustomRadioListTile extends StatelessWidget { + final String text; + final T value; + final ValueChanged onContainerTap; + + const CustomRadioListTile({ + super.key, + required this.text, + required this.value, + required this.onContainerTap, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => onContainerTap(value), + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 5, vertical: 5), + padding: const EdgeInsets.symmetric(horizontal: 2), + decoration: BoxDecoration( + color: CustomTheme.boxColor, + border: Border.all(color: CustomTheme.boxBorder), + borderRadius: BorderRadius.circular(12), + ), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 5), + child: Row( + children: [ + Radio(value: value, activeColor: CustomTheme.primaryColor), + Expanded( + child: Text( + text, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ), + ), + ); + } +} From 00fd6880e98cf53ba1ff868e2bf561db7d97072b Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Tue, 25 Nov 2025 17:24:35 +0100 Subject: [PATCH 07/27] add todo comment --- lib/presentation/views/main_menu/game_result_view.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index aa15c2a..94d7182 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -108,7 +108,9 @@ class _GameResultViewState extends State { sizeRelativeToWidth: 0.95, onPressed: _player != null ? () { - print("Selected Winner: ${_player!.name}"); + print( + "Selected Winner: ${_player!.name}", + ); //TODO: Add winner to db Navigator.pop(context); } : null, From d97871d15b134ef6bb2c9034ffd2a0853f233bb3 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Tue, 25 Nov 2025 17:29:21 +0100 Subject: [PATCH 08/27] fix lint --- .../views/main_menu/custom_navigation_bar.dart | 16 ++++++++-------- .../views/main_menu/game_result_view.dart | 14 +++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/presentation/views/main_menu/custom_navigation_bar.dart b/lib/presentation/views/main_menu/custom_navigation_bar.dart index b20f80e..4003a5e 100644 --- a/lib/presentation/views/main_menu/custom_navigation_bar.dart +++ b/lib/presentation/views/main_menu/custom_navigation_bar.dart @@ -62,18 +62,18 @@ class _CustomNavigationBarState extends State MaterialPageRoute( builder: (_) => GameResultView( game: Game( - name: "Test Game", + name: 'Test Game', players: [ - Player(name: "Petrus"), - Player(name: "Peter"), - Player(name: "Petra"), + Player(name: 'Petrus'), + Player(name: 'Peter'), + Player(name: 'Petra'), ], group: Group( - name: "Die Petris", + name: 'Die Petris', members: [ - Player(name: "Petralia"), - Player(name: "Petrenlia"), - Player(name: "Petrumlia"), + Player(name: 'Petralia'), + Player(name: 'Petrenlia'), + Player(name: 'Petrumlia'), ], ), ), diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index 94d7182..2dcabc4 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -61,7 +61,7 @@ class _GameResultViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( - "Select Winner:", + 'Select Winner:', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, @@ -69,10 +69,10 @@ class _GameResultViewState extends State { ), Visibility( visible: allPlayers.isNotEmpty, - replacement: TopCenteredMessage( + replacement: const TopCenteredMessage( icon: Icons.info, - title: "Info", - message: "No players in this game.", + title: 'Info', + message: 'No players in this game.', ), child: Expanded( child: RadioGroup( @@ -104,18 +104,18 @@ class _GameResultViewState extends State { ), ), CustomWidthButton( - text: "Save", + text: 'Save', sizeRelativeToWidth: 0.95, onPressed: _player != null ? () { print( - "Selected Winner: ${_player!.name}", + 'Selected Winner: ${_player!.name}', ); //TODO: Add winner to db Navigator.pop(context); } : null, ), - SizedBox(height: 10), + const SizedBox(height: 10), ], ), ), From 479e9a2575195b2bb580464ba1f98ccacf2ffc83 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Tue, 25 Nov 2025 22:01:49 +0100 Subject: [PATCH 09/27] add spacing between title and list and rename appbar title to game name --- .../views/main_menu/game_result_view.dart | 7 ++--- .../widgets/tiles/custom_radio_list_tile.dart | 27 +++++++++---------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index 2dcabc4..07f200c 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -17,7 +17,7 @@ class GameResultView extends StatefulWidget { class _GameResultViewState extends State { late final List allPlayers; - Player? _player; + Player? _player; //TODO: Set last winner as selected @override void initState() { @@ -32,8 +32,8 @@ class _GameResultViewState extends State { appBar: AppBar( backgroundColor: CustomTheme.backgroundColor, scrolledUnderElevation: 0, - title: const Text( - 'Game Result', + title: Text( + widget.game.name, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), centerTitle: true, @@ -67,6 +67,7 @@ class _GameResultViewState extends State { fontWeight: FontWeight.bold, ), ), + SizedBox(height: 2), Visibility( visible: allPlayers.isNotEmpty, replacement: const TopCenteredMessage( diff --git a/lib/presentation/widgets/tiles/custom_radio_list_tile.dart b/lib/presentation/widgets/tiles/custom_radio_list_tile.dart index 1350239..5081bad 100644 --- a/lib/presentation/widgets/tiles/custom_radio_list_tile.dart +++ b/lib/presentation/widgets/tiles/custom_radio_list_tile.dart @@ -25,23 +25,20 @@ class CustomRadioListTile extends StatelessWidget { border: Border.all(color: CustomTheme.boxBorder), borderRadius: BorderRadius.circular(12), ), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 5), - child: Row( - children: [ - Radio(value: value, activeColor: CustomTheme.primaryColor), - Expanded( - child: Text( - text, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), + child: Row( + children: [ + Radio(value: value, activeColor: CustomTheme.primaryColor), + Expanded( + child: Text( + text, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, ), ), - ], - ), + ), + ], ), ), ); From 86ec4de5c063732a2ddbeca7bd7f8747b9c32242 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Tue, 25 Nov 2025 22:03:38 +0100 Subject: [PATCH 10/27] add textoverflow behaviour --- lib/presentation/views/main_menu/game_result_view.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index 07f200c..4103379 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -34,7 +34,11 @@ class _GameResultViewState extends State { scrolledUnderElevation: 0, title: Text( widget.game.name, - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + overflow: TextOverflow.ellipsis, + ), ), centerTitle: true, ), From 9ba3dd7909028ef6365607f395e72ada5f4a3794 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Tue, 25 Nov 2025 23:22:02 +0100 Subject: [PATCH 11/27] added missing consts --- lib/presentation/views/main_menu/game_result_view.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index 4103379..f86ded1 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -34,7 +34,7 @@ class _GameResultViewState extends State { scrolledUnderElevation: 0, title: Text( widget.game.name, - style: TextStyle( + style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, overflow: TextOverflow.ellipsis, @@ -71,7 +71,7 @@ class _GameResultViewState extends State { fontWeight: FontWeight.bold, ), ), - SizedBox(height: 2), + const SizedBox(height: 2), Visibility( visible: allPlayers.isNotEmpty, replacement: const TopCenteredMessage( From e77896c1d4f39a49b59a33dc7d91de6980149357 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 5 Dec 2025 19:25:31 +0100 Subject: [PATCH 12/27] removed settings icon leading to game result view --- .../main_menu/custom_navigation_bar.dart | 26 ++----------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/lib/presentation/views/main_menu/custom_navigation_bar.dart b/lib/presentation/views/main_menu/custom_navigation_bar.dart index 4003a5e..7b08017 100644 --- a/lib/presentation/views/main_menu/custom_navigation_bar.dart +++ b/lib/presentation/views/main_menu/custom_navigation_bar.dart @@ -1,12 +1,9 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; -import 'package:game_tracker/data/dto/game.dart'; -import 'package:game_tracker/data/dto/group.dart'; -import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/views/main_menu/game_history_view.dart'; -import 'package:game_tracker/presentation/views/main_menu/game_result_view.dart'; import 'package:game_tracker/presentation/views/main_menu/groups_view.dart'; import 'package:game_tracker/presentation/views/main_menu/home_view.dart'; +import 'package:game_tracker/presentation/views/main_menu/settings_view.dart'; import 'package:game_tracker/presentation/views/main_menu/statistics_view.dart'; import 'package:game_tracker/presentation/widgets/navbar_item.dart'; @@ -59,26 +56,7 @@ class _CustomNavigationBarState extends State onPressed: () async { await Navigator.push( context, - MaterialPageRoute( - builder: (_) => GameResultView( - game: Game( - name: 'Test Game', - players: [ - Player(name: 'Petrus'), - Player(name: 'Peter'), - Player(name: 'Petra'), - ], - group: Group( - name: 'Die Petris', - members: [ - Player(name: 'Petralia'), - Player(name: 'Petrenlia'), - Player(name: 'Petrumlia'), - ], - ), - ), - ), - ), //TODO Replace with Settingsview + MaterialPageRoute(builder: (_) => SettingsView()), ); setState(() { tabKeyCount++; From 9ac6b6e04c6e68dd9728e8faccb90aaa25d41c53 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 5 Dec 2025 19:25:52 +0100 Subject: [PATCH 13/27] added ontap feature & argument --- .../widgets/tiles/game_history_tile.dart | 193 +++++++++--------- 1 file changed, 91 insertions(+), 102 deletions(-) diff --git a/lib/presentation/widgets/tiles/game_history_tile.dart b/lib/presentation/widgets/tiles/game_history_tile.dart index 3cdd1ad..83da859 100644 --- a/lib/presentation/widgets/tiles/game_history_tile.dart +++ b/lib/presentation/widgets/tiles/game_history_tile.dart @@ -6,142 +6,132 @@ import 'package:intl/intl.dart'; class GameHistoryTile extends StatefulWidget { final Game game; + final VoidCallback onTap; - const GameHistoryTile({ - super.key, - required this.game, - }); + const GameHistoryTile({super.key, required this.game, required this.onTap}); @override State createState() => _GameHistoryTileState(); } class _GameHistoryTileState extends State { - @override Widget build(BuildContext context) { final group = widget.game.group; final winner = widget.game.winner; final allPlayers = _getAllPlayers(); - return Container( - margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: CustomTheme.boxColor, - border: Border.all(color: CustomTheme.boxBorder), - borderRadius: BorderRadius.circular(12), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - widget.game.name, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - overflow: TextOverflow.ellipsis, - ), - ), - Text( - _formatDate(widget.game.createdAt), - style: const TextStyle( - fontSize: 12, - color: Colors.grey, - ), - ), - ], - ), - - const SizedBox(height: 8), - - if (group != null) ...[ + return GestureDetector( + onTap: widget.onTap, + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: CustomTheme.boxColor, + border: Border.all(color: CustomTheme.boxBorder), + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Icon( - Icons.group, - size: 16, - color: Colors.grey, - ), - const SizedBox(width: 6), Expanded( child: Text( - group.name, + widget.game.name, style: const TextStyle( - fontSize: 14, - color: Colors.grey, + fontSize: 18, + fontWeight: FontWeight.bold, ), overflow: TextOverflow.ellipsis, ), ), + Text( + _formatDate(widget.game.createdAt), + style: const TextStyle(fontSize: 12, color: Colors.grey), + ), ], ), - const SizedBox(height: 12), - ], - if (winner != null) ...[ - Container( - padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), - decoration: BoxDecoration( - color: Colors.green.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: Colors.green.withValues(alpha: 0.3), - width: 1, - ), - ), - child: Row( + const SizedBox(height: 8), + + if (group != null) ...[ + Row( children: [ - const Icon( - Icons.emoji_events, - size: 20, - color: Colors.amber, - ), - const SizedBox(width: 8), + const Icon(Icons.group, size: 16, color: Colors.grey), + const SizedBox(width: 6), Expanded( child: Text( - 'Winner: ${winner.name}', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Colors.white, - ), + group.name, + style: const TextStyle(fontSize: 14, color: Colors.grey), overflow: TextOverflow.ellipsis, ), ), ], ), - ), - const SizedBox(height: 12), - ], + const SizedBox(height: 12), + ], - if (allPlayers.isNotEmpty) ...[ - const Text( - 'Players', - style: TextStyle( - fontSize: 13, - color: Colors.grey, - fontWeight: FontWeight.w500, + if (winner != null) ...[ + Container( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 12, + ), + decoration: BoxDecoration( + color: Colors.green.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: Colors.green.withValues(alpha: 0.3), + width: 1, + ), + ), + child: Row( + children: [ + const Icon( + Icons.emoji_events, + size: 20, + color: Colors.amber, + ), + const SizedBox(width: 8), + Expanded( + child: Text( + 'Winner: ${winner.name}', + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), ), - ), - const SizedBox(height: 6), - Wrap( - spacing: 6, - runSpacing: 6, - children: allPlayers.map((player) { - return TextIconTile( - text: player.name, - iconEnabled: false, - ); - }).toList(), - ), + const SizedBox(height: 12), + ], + + if (allPlayers.isNotEmpty) ...[ + const Text( + 'Players', + style: TextStyle( + fontSize: 13, + color: Colors.grey, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 6), + Wrap( + spacing: 6, + runSpacing: 6, + children: allPlayers.map((player) { + return TextIconTile(text: player.name, iconEnabled: false); + }).toList(), + ), + ], ], - ], + ), ), ); } @@ -187,5 +177,4 @@ class _GameHistoryTileState extends State { return allPlayers; } - -} \ No newline at end of file +} From f7f97fcdcbfabd5ec31875327370078d6504e08f Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 5 Dec 2025 19:26:47 +0100 Subject: [PATCH 14/27] made tapping on game tile redirect to GameResultView --- .../views/main_menu/game_history_view.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/presentation/views/main_menu/game_history_view.dart b/lib/presentation/views/main_menu/game_history_view.dart index ea5ddd7..713b720 100644 --- a/lib/presentation/views/main_menu/game_history_view.dart +++ b/lib/presentation/views/main_menu/game_history_view.dart @@ -5,6 +5,7 @@ import 'package:game_tracker/data/dto/game.dart'; import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/views/main_menu/create_group_view.dart'; +import 'package:game_tracker/presentation/views/main_menu/game_result_view.dart'; import 'package:game_tracker/presentation/widgets/app_skeleton.dart'; import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart'; import 'package:game_tracker/presentation/widgets/tiles/game_history_tile.dart'; @@ -106,6 +107,15 @@ class _GameHistoryViewState extends State { ); } return GameHistoryTile( + onTap: () async { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + GameResultView(game: games[index]), + ), + ); + }, game: games[index], ); // Placeholder }, From 8f2c7493d081342bf26e01b07f3c399777258f8a Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 5 Dec 2025 19:35:04 +0100 Subject: [PATCH 15/27] re-set gameListFuture to reload the games after changing the winner --- lib/presentation/views/main_menu/game_history_view.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/game_history_view.dart b/lib/presentation/views/main_menu/game_history_view.dart index 713b720..1356ee4 100644 --- a/lib/presentation/views/main_menu/game_history_view.dart +++ b/lib/presentation/views/main_menu/game_history_view.dart @@ -115,9 +115,12 @@ class _GameHistoryViewState extends State { GameResultView(game: games[index]), ), ); + setState(() { + _gameListFuture = db.gameDao.getAllGames(); + }); }, game: games[index], - ); // Placeholder + ); }, ), ); From d8551b3a27d96886ceeb0ccedb9752d8c10ca5cb Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 5 Dec 2025 19:35:14 +0100 Subject: [PATCH 16/27] add db functionality --- .../views/main_menu/game_result_view.dart | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index f86ded1..f74910f 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; +import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/dto/game.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart'; import 'package:game_tracker/presentation/widgets/tiles/custom_radio_list_tile.dart'; import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; +import 'package:provider/provider.dart'; class GameResultView extends StatefulWidget { final Game game; @@ -17,11 +19,16 @@ class GameResultView extends StatefulWidget { class _GameResultViewState extends State { late final List allPlayers; + late final AppDatabase db; Player? _player; //TODO: Set last winner as selected @override void initState() { + db = Provider.of(context, listen: false); allPlayers = getAllPlayers(widget.game); + if (widget.game.winner != null) { + _player = allPlayers.firstWhere((p) => p.id == widget.game.winner!.id); + } super.initState(); } @@ -112,11 +119,29 @@ class _GameResultViewState extends State { text: 'Save', sizeRelativeToWidth: 0.95, onPressed: _player != null - ? () { - print( - 'Selected Winner: ${_player!.name}', - ); //TODO: Add winner to db - Navigator.pop(context); + ? () async { + print('Selected Winner: ${_player!.name}'); + bool success = await db.gameDao.setWinner( + gameId: widget.game.id, + winnerId: _player!.id, + ); + if (!context.mounted) return; + if (success) { + Navigator.pop(context); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + backgroundColor: CustomTheme.boxColor, + content: const Center( + child: Text( + 'Error while setting winner, please try again', + style: TextStyle(color: Colors.white), + ), + ), + ), + ); + } + setState(() {}); } : null, ), From dba448b9c1debc43222b2946416c6ca47f3a3f71 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 5 Dec 2025 19:38:28 +0100 Subject: [PATCH 17/27] added const --- .../views/main_menu/custom_navigation_bar.dart | 2 +- lib/presentation/views/main_menu/game_history_view.dart | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/presentation/views/main_menu/custom_navigation_bar.dart b/lib/presentation/views/main_menu/custom_navigation_bar.dart index 7b08017..71a072e 100644 --- a/lib/presentation/views/main_menu/custom_navigation_bar.dart +++ b/lib/presentation/views/main_menu/custom_navigation_bar.dart @@ -56,7 +56,7 @@ class _CustomNavigationBarState extends State onPressed: () async { await Navigator.push( context, - MaterialPageRoute(builder: (_) => SettingsView()), + MaterialPageRoute(builder: (_) => const SettingsView()), ); setState(() { tabKeyCount++; diff --git a/lib/presentation/views/main_menu/game_history_view.dart b/lib/presentation/views/main_menu/game_history_view.dart index 1356ee4..aea958d 100644 --- a/lib/presentation/views/main_menu/game_history_view.dart +++ b/lib/presentation/views/main_menu/game_history_view.dart @@ -22,7 +22,6 @@ class GameHistoryView extends StatefulWidget { class _GameHistoryViewState extends State { late Future> _gameListFuture; late final AppDatabase db; - late bool isLoading = true; late final List skeletonData = List.filled( 4, @@ -51,9 +50,6 @@ class _GameHistoryViewState extends State { Future.wait([_gameListFuture]).then((result) async { await Future.delayed(const Duration(milliseconds: 250)); - setState(() { - isLoading = false; - }); }); } @@ -87,14 +83,14 @@ class _GameHistoryViewState extends State { ), ); } - + final bool isLoading = + snapshot.connectionState == ConnectionState.waiting; final List games = (isLoading ? skeletonData : (snapshot.data ?? []) ..sort( (a, b) => b.createdAt.compareTo(a.createdAt), )) .toList(); - return AppSkeleton( enabled: isLoading, child: ListView.builder( From e3ac91bf48be1b29b568c74042f7b12ee9b2c2b0 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 5 Dec 2025 19:41:01 +0100 Subject: [PATCH 18/27] remove todo --- lib/presentation/views/main_menu/game_result_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index f74910f..7468adb 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -20,7 +20,7 @@ class GameResultView extends StatefulWidget { class _GameResultViewState extends State { late final List allPlayers; late final AppDatabase db; - Player? _player; //TODO: Set last winner as selected + Player? _player; @override void initState() { From f5842f9c4ab3390bb605caae48acdd61020f1ded Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 5 Dec 2025 19:44:36 +0100 Subject: [PATCH 19/27] remove print --- lib/presentation/views/main_menu/game_result_view.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index 7468adb..a32ba95 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -120,7 +120,6 @@ class _GameResultViewState extends State { sizeRelativeToWidth: 0.95, onPressed: _player != null ? () async { - print('Selected Winner: ${_player!.name}'); bool success = await db.gameDao.setWinner( gameId: widget.game.id, winnerId: _player!.id, From 7323f52153bfc85502336b79e06b727c1a5d1624 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 5 Dec 2025 20:33:27 +0100 Subject: [PATCH 20/27] add delay and change empty games message --- .../views/main_menu/game_history_view.dart | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/presentation/views/main_menu/game_history_view.dart b/lib/presentation/views/main_menu/game_history_view.dart index aea958d..e4e135f 100644 --- a/lib/presentation/views/main_menu/game_history_view.dart +++ b/lib/presentation/views/main_menu/game_history_view.dart @@ -46,11 +46,10 @@ class _GameHistoryViewState extends State { void initState() { super.initState(); db = Provider.of(context, listen: false); - _gameListFuture = db.gameDao.getAllGames(); - - Future.wait([_gameListFuture]).then((result) async { - await Future.delayed(const Duration(milliseconds: 250)); - }); + _gameListFuture = Future.delayed( + const Duration(milliseconds: 250), + () => db.gameDao.getAllGames(), + ); } @override @@ -78,8 +77,8 @@ class _GameHistoryViewState extends State { return const Center( child: TopCenteredMessage( icon: Icons.report, - title: 'Error', - message: 'No Games Available', + title: 'Info', + message: 'No games created yet.', ), ); } From 03035138acb3d9580713c67296cfbc9e0f3696df Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 6 Dec 2025 10:00:59 +0100 Subject: [PATCH 21/27] refactor game result view variable naming and layout --- .../views/main_menu/game_result_view.dart | 61 ++++++++----------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index a32ba95..e07b788 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -5,7 +5,6 @@ import 'package:game_tracker/data/dto/game.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart'; import 'package:game_tracker/presentation/widgets/tiles/custom_radio_list_tile.dart'; -import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; import 'package:provider/provider.dart'; class GameResultView extends StatefulWidget { @@ -20,14 +19,16 @@ class GameResultView extends StatefulWidget { class _GameResultViewState extends State { late final List allPlayers; late final AppDatabase db; - Player? _player; + Player? _selectedPlayer; @override void initState() { db = Provider.of(context, listen: false); allPlayers = getAllPlayers(widget.game); if (widget.game.winner != null) { - _player = allPlayers.firstWhere((p) => p.id == widget.game.winner!.id); + _selectedPlayer = allPlayers.firstWhere( + (p) => p.id == widget.game.winner!.id, + ); } super.initState(); } @@ -78,36 +79,28 @@ class _GameResultViewState extends State { fontWeight: FontWeight.bold, ), ), - const SizedBox(height: 2), - Visibility( - visible: allPlayers.isNotEmpty, - replacement: const TopCenteredMessage( - icon: Icons.info, - title: 'Info', - message: 'No players in this game.', - ), - child: Expanded( - child: RadioGroup( - groupValue: _player, - onChanged: (Player? value) { - setState(() { - _player = value; - }); + const SizedBox(height: 10), + Expanded( + child: RadioGroup( + groupValue: _selectedPlayer, + onChanged: (Player? value) { + setState(() { + _selectedPlayer = value; + }); + }, + child: ListView.builder( + itemCount: allPlayers.length, + itemBuilder: (context, index) { + return CustomRadioListTile( + text: allPlayers[index].name, + value: allPlayers[index], + onContainerTap: (value) { + setState(() { + _selectedPlayer = value; + }); + }, + ); }, - child: ListView.builder( - itemCount: allPlayers.length, - itemBuilder: (context, index) { - return CustomRadioListTile( - text: allPlayers[index].name, - value: allPlayers[index], - onContainerTap: (value) { - setState(() { - _player = value; - }); - }, - ); - }, - ), ), ), ), @@ -118,11 +111,11 @@ class _GameResultViewState extends State { CustomWidthButton( text: 'Save', sizeRelativeToWidth: 0.95, - onPressed: _player != null + onPressed: _selectedPlayer != null ? () async { bool success = await db.gameDao.setWinner( gameId: widget.game.id, - winnerId: _player!.id, + winnerId: _selectedPlayer!.id, ); if (!context.mounted) return; if (success) { From 306a783d67f8fa2b82c90d4b68893bdabb30bbc7 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 6 Dec 2025 11:22:34 +0100 Subject: [PATCH 22/27] removed dots after TopCenteredMessage text --- lib/presentation/views/main_menu/game_history_view.dart | 2 +- lib/presentation/views/main_menu/groups_view.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/presentation/views/main_menu/game_history_view.dart b/lib/presentation/views/main_menu/game_history_view.dart index e4e135f..3cecd2f 100644 --- a/lib/presentation/views/main_menu/game_history_view.dart +++ b/lib/presentation/views/main_menu/game_history_view.dart @@ -78,7 +78,7 @@ class _GameHistoryViewState extends State { child: TopCenteredMessage( icon: Icons.report, title: 'Info', - message: 'No games created yet.', + message: 'No games created yet', ), ); } diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 4601ef9..ce47f90 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -56,7 +56,7 @@ class _GroupsViewState extends State { child: TopCenteredMessage( icon: Icons.report, title: 'Error', - message: 'Group data couldn\'t\nbe loaded.', + message: 'Group data couldn\'t\nbe loaded', ), ); } @@ -66,7 +66,7 @@ class _GroupsViewState extends State { child: TopCenteredMessage( icon: Icons.info, title: 'Info', - message: 'No groups created yet.', + message: 'No groups created yet', ), ); } From 697767f0de46ffb39853892bbd9091c38cd7d27e Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 6 Dec 2025 13:31:08 +0100 Subject: [PATCH 23/27] made winner deselectable and added auto save on select --- .../views/main_menu/game_result_view.dart | 49 ++++++------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index e07b788..80a0774 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -3,7 +3,6 @@ import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/dto/game.dart'; import 'package:game_tracker/data/dto/player.dart'; -import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart'; import 'package:game_tracker/presentation/widgets/tiles/custom_radio_list_tile.dart'; import 'package:provider/provider.dart'; @@ -94,10 +93,24 @@ class _GameResultViewState extends State { return CustomRadioListTile( text: allPlayers[index].name, value: allPlayers[index], - onContainerTap: (value) { + onContainerTap: (value) async { setState(() { - _selectedPlayer = value; + if (_selectedPlayer == value) { + _selectedPlayer = null; + } else { + _selectedPlayer = value; + } }); + if (_selectedPlayer == null) { + await db.gameDao.removeWinner( + gameId: widget.game.id, + ); + } else { + await db.gameDao.setWinner( + gameId: widget.game.id, + winnerId: _selectedPlayer!.id, + ); + } }, ); }, @@ -108,36 +121,6 @@ class _GameResultViewState extends State { ), ), ), - CustomWidthButton( - text: 'Save', - sizeRelativeToWidth: 0.95, - onPressed: _selectedPlayer != null - ? () async { - bool success = await db.gameDao.setWinner( - gameId: widget.game.id, - winnerId: _selectedPlayer!.id, - ); - if (!context.mounted) return; - if (success) { - Navigator.pop(context); - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - backgroundColor: CustomTheme.boxColor, - content: const Center( - child: Text( - 'Error while setting winner, please try again', - style: TextStyle(color: Colors.white), - ), - ), - ), - ); - } - setState(() {}); - } - : null, - ), - const SizedBox(height: 10), ], ), ), From b1bb8b919f883fdc2ca54a4805f295314ce08d5a Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 6 Dec 2025 13:34:11 +0100 Subject: [PATCH 24/27] changed MaterialPageRoute to CupertinoPageRoute for ios animation --- lib/presentation/views/main_menu/game_history_view.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/game_history_view.dart b/lib/presentation/views/main_menu/game_history_view.dart index 3cecd2f..31d1b56 100644 --- a/lib/presentation/views/main_menu/game_history_view.dart +++ b/lib/presentation/views/main_menu/game_history_view.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/data/db/database.dart'; @@ -105,7 +106,8 @@ class _GameHistoryViewState extends State { onTap: () async { await Navigator.push( context, - MaterialPageRoute( + CupertinoPageRoute( + fullscreenDialog: true, builder: (context) => GameResultView(game: games[index]), ), From 91a727396419933c6c9533793034a432cdb0f385 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 6 Dec 2025 14:12:34 +0100 Subject: [PATCH 25/27] madio radio list tile toggleable --- lib/presentation/widgets/tiles/custom_radio_list_tile.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/presentation/widgets/tiles/custom_radio_list_tile.dart b/lib/presentation/widgets/tiles/custom_radio_list_tile.dart index 5081bad..11e8b40 100644 --- a/lib/presentation/widgets/tiles/custom_radio_list_tile.dart +++ b/lib/presentation/widgets/tiles/custom_radio_list_tile.dart @@ -27,7 +27,11 @@ class CustomRadioListTile extends StatelessWidget { ), child: Row( children: [ - Radio(value: value, activeColor: CustomTheme.primaryColor), + Radio( + value: value, + activeColor: CustomTheme.primaryColor, + toggleable: true, + ), Expanded( child: Text( text, From 1ed6290628104b1170939423093398f773e963ac Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 6 Dec 2025 14:20:37 +0100 Subject: [PATCH 26/27] Refactor winner selection and persistence logic in GameResultView --- .../views/main_menu/game_result_view.dart | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index 80a0774..8b093c1 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -82,10 +82,11 @@ class _GameResultViewState extends State { Expanded( child: RadioGroup( groupValue: _selectedPlayer, - onChanged: (Player? value) { + onChanged: (Player? value) async { setState(() { _selectedPlayer = value; }); + await _handleWinnerSaving(); }, child: ListView.builder( itemCount: allPlayers.length, @@ -95,22 +96,15 @@ class _GameResultViewState extends State { value: allPlayers[index], onContainerTap: (value) async { setState(() { + // Check if the already selected player is the same as the newly tapped player. if (_selectedPlayer == value) { + // If yes deselected the player by setting it to null. _selectedPlayer = null; - } else { - _selectedPlayer = value; - } + } else + // If no assign the newly tapped player to the selected player. + (_selectedPlayer = value); }); - if (_selectedPlayer == null) { - await db.gameDao.removeWinner( - gameId: widget.game.id, - ); - } else { - await db.gameDao.setWinner( - gameId: widget.game.id, - winnerId: _selectedPlayer!.id, - ); - } + await _handleWinnerSaving(); }, ); }, @@ -127,6 +121,17 @@ class _GameResultViewState extends State { ); } + Future _handleWinnerSaving() async { + if (_selectedPlayer == null) { + await db.gameDao.removeWinner(gameId: widget.game.id); + } else { + await db.gameDao.setWinner( + gameId: widget.game.id, + winnerId: _selectedPlayer!.id, + ); + } + } + List getAllPlayers(Game game) { if (game.group == null && game.players != null) { return [...game.players!]; From dbbe04d4ccf32a28f790f327546a5eb91b994932 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 6 Dec 2025 14:21:17 +0100 Subject: [PATCH 27/27] add braces to if/else statement in `game_result_view.dart` --- lib/presentation/views/main_menu/game_result_view.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/game_result_view.dart b/lib/presentation/views/main_menu/game_result_view.dart index 8b093c1..f13553b 100644 --- a/lib/presentation/views/main_menu/game_result_view.dart +++ b/lib/presentation/views/main_menu/game_result_view.dart @@ -100,9 +100,10 @@ class _GameResultViewState extends State { if (_selectedPlayer == value) { // If yes deselected the player by setting it to null. _selectedPlayer = null; - } else + } else { // If no assign the newly tapped player to the selected player. (_selectedPlayer = value); + } }); await _handleWinnerSaving(); },