From 2ee4d8e6fa3dd36de8810703c6d09c44d0fdf427 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Fri, 14 Nov 2025 20:58:01 +0100 Subject: [PATCH 01/28] implemented basic layout & functionality for add group button & group tiles --- .../views/main_menu/groups_view.dart | 82 ++++++++++++++++++- .../widgets/full_width_button.dart | 29 +++++++ lib/presentation/widgets/group_tile.dart | 56 +++++++++++++ .../widgets/top_centered_message.dart | 29 ++++--- 4 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 lib/presentation/widgets/full_width_button.dart create mode 100644 lib/presentation/widgets/group_tile.dart diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 485d516..a3e66d3 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -1,10 +1,86 @@ -import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +//import 'package:game_tracker/data/dto/group.dart'; +//import 'package:game_tracker/data/dto/player.dart'; +import 'package:game_tracker/presentation/widgets/full_width_button.dart'; +import 'package:game_tracker/presentation/widgets/group_tile.dart'; +import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; -class GroupsView extends StatelessWidget { +class Group { + final String id; + final String name; + final List members; + + Group({required this.id, required this.name, required this.members}); +} + +class Player { + final String id; + final String name; + + Player({required this.id, required this.name}); +} + +class GroupsView extends StatefulWidget { const GroupsView({super.key}); + @override + State createState() => _GroupsViewState(); +} + +class _GroupsViewState extends State { + Future> _getMockGroups() async { + await Future.delayed(const Duration(seconds: 1)); + final player1 = Player(id: 'p1', name: 'Felix'); + final player2 = Player(id: 'p2', name: 'Yannick'); + final player3 = Player(id: 'p3', name: 'Mathis'); + final player4 = Player(id: 'p4', name: 'Petrus'); + + return [ + Group( + id: 'g1', + name: 'Weekend Warriors', + members: [player1, player2, player4], + ), + Group(id: 'g2', name: 'Strategy Masters', members: [player3, player4]), + Group( + id: 'g3', + name: 'The Cardboard Crew', + members: [player1, player2, player3, player4], + ), + Group(id: 'g4', name: 'The Group', members: [player1, player3, player4]), + ]; + } + @override Widget build(BuildContext context) { - return const Center(child: Text('Groups View')); + return Column( + children: [ + FutureBuilder( + future: _getMockGroups(), + builder: (BuildContext context, AsyncSnapshot> snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center( + child: TopCenteredMessage( + message: "Data not yet available, show sceleton", + ), + ); + } else if (snapshot.hasError) { + return Center( + child: TopCenteredMessage( + message: "Error while loading group data.", + ), + ); + } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + return Center( + child: TopCenteredMessage(message: "No groups created yet."), + ); + } + return GroupTile(group: snapshot.data![0]); + //return ListView.builder() + }, + ), + FullWidthButton(text: "Create Group", onPressed: () {}), + ], + ); } } diff --git a/lib/presentation/widgets/full_width_button.dart b/lib/presentation/widgets/full_width_button.dart new file mode 100644 index 0000000..6df700b --- /dev/null +++ b/lib/presentation/widgets/full_width_button.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:game_tracker/core/custom_theme.dart'; + +class FullWidthButton extends StatelessWidget { + const FullWidthButton({super.key, required this.text, this.onPressed}); + + final String text; + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: onPressed, + style: ElevatedButton.styleFrom( + minimumSize: Size(MediaQuery.of(context).size.width * 0.8, 60), + backgroundColor: CustomTheme.primaryColor, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + ), + child: Text( + text, + style: const TextStyle( + fontWeight: FontWeight.w500, + fontSize: 22, + color: Colors.white, + ), + ), + ); + } +} diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/group_tile.dart new file mode 100644 index 0000000..5959f04 --- /dev/null +++ b/lib/presentation/widgets/group_tile.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +//import 'package:game_tracker/data/dto/group.dart'; + +class Group { + final String id; + final String name; + final List members; + + Group({required this.id, required this.name, required this.members}); +} + +class Player { + final String id; + final String name; + + Player({required this.id, required this.name}); +} + +class GroupTile extends StatelessWidget { + const GroupTile({super.key, required this.group}); + + final Group group; + + @override + Widget build(BuildContext context) { + return Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("${group.name}", overflow: TextOverflow.ellipsis), + Text("${group.members.length}"), + Icon(Icons.group), + ], + ), + Wrap( + spacing: 8.0, + runSpacing: -4.0, + children: [ + for (var member in group.members) + Container( + color: Colors.grey, + padding: const EdgeInsets.all(4.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + ), + child: Text(member.name), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/presentation/widgets/top_centered_message.dart b/lib/presentation/widgets/top_centered_message.dart index 6fe34ff..df8dcb1 100644 --- a/lib/presentation/widgets/top_centered_message.dart +++ b/lib/presentation/widgets/top_centered_message.dart @@ -1,14 +1,21 @@ import 'package:flutter/material.dart'; -Widget TopCenteredMessage(String message) { - return Container( - padding: EdgeInsets.only(top: 100), - margin: EdgeInsets.only(left: 10, right: 10), - alignment: Alignment.topCenter, - child: Text( - "$message", - style: TextStyle(fontSize: 20), - textAlign: TextAlign.center, - ), - ); +class TopCenteredMessage extends StatelessWidget { + const TopCenteredMessage({super.key, required this.message}); + + final String message; + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.only(top: 100), + margin: const EdgeInsets.symmetric(horizontal: 10), + alignment: Alignment.topCenter, + child: Text( + message, + style: const TextStyle(fontSize: 20), + textAlign: TextAlign.center, + ), + ); + } } From 1081fb8be7d61395bf0b1fab8addff48612dcb72 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 15 Nov 2025 16:08:47 +0100 Subject: [PATCH 02/28] rearrange imports and fix wrong syntax in widget call --- lib/presentation/views/main_menu/game_history_view.dart | 8 +++++--- lib/presentation/views/main_menu/groups_view.dart | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/presentation/views/main_menu/game_history_view.dart b/lib/presentation/views/main_menu/game_history_view.dart index de75ae6..f620cd7 100644 --- a/lib/presentation/views/main_menu/game_history_view.dart +++ b/lib/presentation/views/main_menu/game_history_view.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; -import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; import 'package:game_tracker/presentation/widgets/double_row_info_tile.dart'; +import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; class GameHistoryView extends StatefulWidget { const GameHistoryView({super.key}); @@ -178,9 +178,11 @@ class _GameHistoryViewState extends State { Widget gameHistoryListView(allGameData, suggestedGameData) { if (suggestedGameData.isEmpty && allGameData.isEmpty) { - return TopCenteredMessage("Keine Spiele erstellt"); + return TopCenteredMessage(message: "Keine Spiele erstellt"); } else if (suggestedGameData.isEmpty) { - return TopCenteredMessage("Kein Spiel mit den Suchparametern gefunden."); + return TopCenteredMessage( + message: "Kein Spiel mit den Suchparametern gefunden.", + ); } return ListView.builder( itemCount: suggestedGameData.length, diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index a3e66d3..70f70dc 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; //import 'package:game_tracker/data/dto/group.dart'; //import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/full_width_button.dart'; -import 'package:game_tracker/presentation/widgets/group_tile.dart'; import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; class Group { @@ -75,7 +74,8 @@ class _GroupsViewState extends State { child: TopCenteredMessage(message: "No groups created yet."), ); } - return GroupTile(group: snapshot.data![0]); + return Center(child: Text("whatever")); + //return GroupTile(group: snapshot.data![0]); //return ListView.builder() }, ), From d08c79fc262b9298442962285072813a8d145a89 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 15 Nov 2025 20:22:09 +0100 Subject: [PATCH 03/28] implemented groups view with create group button --- .../views/main_menu/groups_view.dart | 115 +++++++++++++----- .../widgets/full_width_button.dart | 2 +- lib/presentation/widgets/group_tile.dart | 73 +++++++---- 3 files changed, 134 insertions(+), 56 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 70f70dc..76034a6 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; //import 'package:game_tracker/data/dto/group.dart'; //import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/full_width_button.dart'; +import 'package:game_tracker/presentation/widgets/group_tile.dart'; import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; class Group { @@ -38,7 +39,15 @@ class _GroupsViewState extends State { Group( id: 'g1', name: 'Weekend Warriors', - members: [player1, player2, player4], + members: [ + player1, + player2, + player4, + player3, + player1, + player4, + player2, + ], ), Group(id: 'g2', name: 'Strategy Masters', members: [player3, player4]), Group( @@ -46,41 +55,85 @@ class _GroupsViewState extends State { name: 'The Cardboard Crew', members: [player1, player2, player3, player4], ), - Group(id: 'g4', name: 'The Group', members: [player1, player3, player4]), + Group( + id: 'g4', + name: 'Gamers', + members: [player1, player3, player1, player4], + ), + Group( + id: 'g4', + name: 'The Group', + members: [player4, player1, player3, player4, player3], + ), + Group( + id: 'g4', + name: 'Friends', + members: [player4, player1, player3, player4], + ), + Group( + id: 'g4', + name: 'Sample Group', + members: [player1, player1, player4, player3], + ), + Group( + id: 'g4', + name: 'The Group', + members: [player1, player1, player3, player4], + ), + Group( + id: 'g4', + name: 'The Best', + members: [player1, player3, player1, player4, player1], + ), ]; } @override Widget build(BuildContext context) { - return Column( - children: [ - FutureBuilder( - future: _getMockGroups(), - builder: (BuildContext context, AsyncSnapshot> snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center( - child: TopCenteredMessage( - message: "Data not yet available, show sceleton", - ), - ); - } else if (snapshot.hasError) { - return Center( - child: TopCenteredMessage( - message: "Error while loading group data.", - ), - ); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { - return Center( - child: TopCenteredMessage(message: "No groups created yet."), - ); - } - return Center(child: Text("whatever")); - //return GroupTile(group: snapshot.data![0]); - //return ListView.builder() - }, - ), - FullWidthButton(text: "Create Group", onPressed: () {}), - ], + return SafeArea( + child: Stack( + children: [ + FutureBuilder( + future: _getMockGroups(), + builder: + (BuildContext context, AsyncSnapshot> snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center( + child: TopCenteredMessage( + message: 'Data not yet available, show sceleton', + ), + ); + } else if (snapshot.hasError) { + return const Center( + child: TopCenteredMessage( + message: 'Error while loading group data.', + ), + ); + } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + return const Center( + child: TopCenteredMessage( + message: 'No groups created yet.', + ), + ); + } + //return Center(child: Text('whatever')); + //return GroupTile(group: snapshot.data![0]); + return ListView.builder( + padding: const EdgeInsets.only(bottom: 85), + itemCount: snapshot.data!.length, + itemBuilder: (BuildContext context, int index) { + return GroupTile(group: snapshot.data![index]); + }, + ); + }, + ), + Positioned( + bottom: 16, + right: 16, + child: FullWidthButton(text: 'Create Group', onPressed: () {}), + ), + ], + ), ); } } diff --git a/lib/presentation/widgets/full_width_button.dart b/lib/presentation/widgets/full_width_button.dart index 6df700b..2af6abe 100644 --- a/lib/presentation/widgets/full_width_button.dart +++ b/lib/presentation/widgets/full_width_button.dart @@ -12,7 +12,7 @@ class FullWidthButton extends StatelessWidget { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( - minimumSize: Size(MediaQuery.of(context).size.width * 0.8, 60), + minimumSize: Size(MediaQuery.of(context).size.width * 0.90, 60), backgroundColor: CustomTheme.primaryColor, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/group_tile.dart index 5959f04..783abcd 100644 --- a/lib/presentation/widgets/group_tile.dart +++ b/lib/presentation/widgets/group_tile.dart @@ -1,20 +1,6 @@ import 'package:flutter/material.dart'; -//import 'package:game_tracker/data/dto/group.dart'; - -class Group { - final String id; - final String name; - final List members; - - Group({required this.id, required this.name, required this.members}); -} - -class Player { - final String id; - final String name; - - Player({required this.id, required this.name}); -} +import 'package:game_tracker/core/custom_theme.dart'; +import 'package:game_tracker/presentation/views/main_menu/groups_view.dart'; class GroupTile extends StatelessWidget { const GroupTile({super.key, required this.group}); @@ -24,31 +10,70 @@ class GroupTile extends StatelessWidget { @override Widget build(BuildContext context) { return Container( + width: MediaQuery.of(context).size.width * 0.90, + margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + decoration: BoxDecoration( + color: CustomTheme.secondaryColor, + borderRadius: BorderRadius.circular(12), + ), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("${group.name}", overflow: TextOverflow.ellipsis), - Text("${group.members.length}"), - Icon(Icons.group), + Text( + group.name, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20, + color: Colors.white, + ), + ), + const Spacer(), + Text( + '${group.members.length}', + style: const TextStyle( + fontWeight: FontWeight.w900, + fontSize: 20, + color: Colors.white, + ), + ), + SizedBox(width: 3), + const Icon(Icons.group), ], ), + SizedBox(height: 5), Wrap( - spacing: 8.0, - runSpacing: -4.0, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + spacing: 12.0, + runSpacing: 8.0, children: [ for (var member in group.members) Container( - color: Colors.grey, - padding: const EdgeInsets.all(4.0), + padding: const EdgeInsets.symmetric( + vertical: 5, + horizontal: 10, + ), decoration: BoxDecoration( + color: Colors.black26, borderRadius: BorderRadius.circular(12), ), - child: Text(member.name), + child: Text( + member.name, + style: TextStyle( + fontSize: 17, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), ), ], ), + SizedBox(height: 2.5), ], ), ); From d36348c59c1b87afbdf4f1e7f065dff86aa0a301 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 15 Nov 2025 21:24:52 +0100 Subject: [PATCH 04/28] added skeleton loading --- .../views/main_menu/groups_view.dart | 65 ++++++++++++++----- lib/presentation/widgets/group_tile.dart | 2 +- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 76034a6..e52cf58 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/presentation/widgets/full_width_button.dart'; import 'package:game_tracker/presentation/widgets/group_tile.dart'; import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; +import 'package:skeletonizer/skeletonizer.dart'; class Group { final String id; @@ -29,7 +30,7 @@ class GroupsView extends StatefulWidget { class _GroupsViewState extends State { Future> _getMockGroups() async { - await Future.delayed(const Duration(seconds: 1)); + await Future.delayed(const Duration(seconds: 4)); final player1 = Player(id: 'p1', name: 'Felix'); final player2 = Player(id: 'p2', name: 'Yannick'); final player3 = Player(id: 'p3', name: 'Mathis'); @@ -88,45 +89,73 @@ class _GroupsViewState extends State { ]; } + final player = Player(id: 'p1', name: 'Felix'); + late final List skeletonData = List.filled( + 7, + Group( + id: 'g1', + name: 'Weekend Warriors', + members: [player, player, player, player], + ), + ); + @override Widget build(BuildContext context) { return SafeArea( child: Stack( children: [ - FutureBuilder( + FutureBuilder>( future: _getMockGroups(), builder: (BuildContext context, AsyncSnapshot> snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center( - child: TopCenteredMessage( - message: 'Data not yet available, show sceleton', - ), - ); - } else if (snapshot.hasError) { + if (snapshot.hasError) { return const Center( child: TopCenteredMessage( message: 'Error while loading group data.', ), ); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + } + if (snapshot.connectionState == ConnectionState.done && + (!snapshot.hasData || snapshot.data!.isEmpty)) { return const Center( child: TopCenteredMessage( message: 'No groups created yet.', ), ); } - //return Center(child: Text('whatever')); - //return GroupTile(group: snapshot.data![0]); - return ListView.builder( - padding: const EdgeInsets.only(bottom: 85), - itemCount: snapshot.data!.length, - itemBuilder: (BuildContext context, int index) { - return GroupTile(group: snapshot.data![index]); - }, + final bool isLoading = + snapshot.connectionState == ConnectionState.waiting; + final List groups = isLoading + ? skeletonData + : (snapshot.data ?? []); + return Skeletonizer( + effect: PulseEffect( + from: Colors.grey[100]!, + to: Colors.grey[400]!, + duration: const Duration(milliseconds: 800), + ), + enabled: isLoading, + enableSwitchAnimation: true, + switchAnimationConfig: const SwitchAnimationConfig( + duration: Duration(milliseconds: 200), + switchInCurve: Curves.linear, + switchOutCurve: Curves.linear, + transitionBuilder: + AnimatedSwitcher.defaultTransitionBuilder, + layoutBuilder: AnimatedSwitcher.defaultLayoutBuilder, + ), + child: ListView.builder( + padding: const EdgeInsets.only(bottom: 85), + itemCount: groups.length, + itemBuilder: (BuildContext context, int index) { + return GroupTile(group: groups[index]); + }, + ), ); }, ), + + // Dein Button bleibt wie gehabt Positioned( bottom: 16, right: 16, diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/group_tile.dart index 783abcd..87d997b 100644 --- a/lib/presentation/widgets/group_tile.dart +++ b/lib/presentation/widgets/group_tile.dart @@ -59,7 +59,7 @@ class GroupTile extends StatelessWidget { horizontal: 10, ), decoration: BoxDecoration( - color: Colors.black26, + color: Colors.black38, borderRadius: BorderRadius.circular(12), ), child: Text( From 352fdc13f1698eb26d5f37f5b001b1a6dca80c1b Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 15 Nov 2025 21:25:12 +0100 Subject: [PATCH 05/28] added skeletonizer package requirement --- pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pubspec.yaml b/pubspec.yaml index 5fa8019..ab6e30b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,6 +18,7 @@ dependencies: drift_flutter: ^0.2.4 path_provider: ^2.1.5 provider: ^6.1.5 + skeletonizer: ^2.1.0+1 dev_dependencies: flutter_test: From d07bc6e8bbbb5eb3494e7359daa237933eaa8a6e Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 15 Nov 2025 21:43:03 +0100 Subject: [PATCH 06/28] increased skeleton item count & added daos as import --- .../views/main_menu/groups_view.dart | 22 +++---------------- lib/presentation/widgets/group_tile.dart | 2 +- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index e52cf58..623f7df 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -1,26 +1,11 @@ import 'package:flutter/material.dart'; -//import 'package:game_tracker/data/dto/group.dart'; -//import 'package:game_tracker/data/dto/player.dart'; +import 'package:game_tracker/data/dto/group.dart'; +import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/full_width_button.dart'; import 'package:game_tracker/presentation/widgets/group_tile.dart'; import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; import 'package:skeletonizer/skeletonizer.dart'; -class Group { - final String id; - final String name; - final List members; - - Group({required this.id, required this.name, required this.members}); -} - -class Player { - final String id; - final String name; - - Player({required this.id, required this.name}); -} - class GroupsView extends StatefulWidget { const GroupsView({super.key}); @@ -91,7 +76,7 @@ class _GroupsViewState extends State { final player = Player(id: 'p1', name: 'Felix'); late final List skeletonData = List.filled( - 7, + 8, Group( id: 'g1', name: 'Weekend Warriors', @@ -155,7 +140,6 @@ class _GroupsViewState extends State { }, ), - // Dein Button bleibt wie gehabt Positioned( bottom: 16, right: 16, diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/group_tile.dart index 87d997b..bb96493 100644 --- a/lib/presentation/widgets/group_tile.dart +++ b/lib/presentation/widgets/group_tile.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; -import 'package:game_tracker/presentation/views/main_menu/groups_view.dart'; +import 'package:game_tracker/data/dto/group.dart'; class GroupTile extends StatelessWidget { const GroupTile({super.key, required this.group}); From 511124e323b48d9d52469289acdca6f1bfa82d13 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 15 Nov 2025 21:57:31 +0100 Subject: [PATCH 07/28] reduced mock data loading time --- lib/presentation/views/main_menu/groups_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 623f7df..4865d0a 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -15,7 +15,7 @@ class GroupsView extends StatefulWidget { class _GroupsViewState extends State { Future> _getMockGroups() async { - await Future.delayed(const Duration(seconds: 4)); + await Future.delayed(const Duration(seconds: 2)); final player1 = Player(id: 'p1', name: 'Felix'); final player2 = Player(id: 'p2', name: 'Yannick'); final player3 = Player(id: 'p3', name: 'Mathis'); From ac6f3d0f929a0f34afaa23bc737ca4feec0ec791 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 15 Nov 2025 22:10:51 +0100 Subject: [PATCH 08/28] added missing const's --- lib/presentation/widgets/group_tile.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/group_tile.dart index bb96493..a874bc7 100644 --- a/lib/presentation/widgets/group_tile.dart +++ b/lib/presentation/widgets/group_tile.dart @@ -41,11 +41,11 @@ class GroupTile extends StatelessWidget { color: Colors.white, ), ), - SizedBox(width: 3), + const SizedBox(width: 3), const Icon(Icons.group), ], ), - SizedBox(height: 5), + const SizedBox(height: 5), Wrap( alignment: WrapAlignment.start, crossAxisAlignment: WrapCrossAlignment.start, @@ -64,7 +64,7 @@ class GroupTile extends StatelessWidget { ), child: Text( member.name, - style: TextStyle( + style: const TextStyle( fontSize: 17, fontWeight: FontWeight.bold, color: Colors.white, @@ -73,7 +73,7 @@ class GroupTile extends StatelessWidget { ), ], ), - SizedBox(height: 2.5), + const SizedBox(height: 2.5), ], ), ); From 7c34e517794c3679dc166a2381ef1757e6516684 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sat, 15 Nov 2025 22:33:00 +0100 Subject: [PATCH 09/28] fixed black bar behind nav bar by removing safearea --- lib/presentation/views/main_menu/groups_view.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 4865d0a..0d5b993 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/full_width_button.dart'; @@ -86,8 +87,10 @@ class _GroupsViewState extends State { @override Widget build(BuildContext context) { - return SafeArea( - child: Stack( + return Scaffold( + backgroundColor: CustomTheme.backgroundColor, + body: Stack( + alignment: Alignment.center, children: [ FutureBuilder>( future: _getMockGroups(), @@ -141,8 +144,7 @@ class _GroupsViewState extends State { ), Positioned( - bottom: 16, - right: 16, + bottom: 80, child: FullWidthButton(text: 'Create Group', onPressed: () {}), ), ], From b475237b9ea59a38f0ce906d53e7e5a47632b82e Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 16:25:50 +0100 Subject: [PATCH 10/28] ignored text for players in skeleton loading --- lib/presentation/widgets/group_tile.dart | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/group_tile.dart index a874bc7..a317248 100644 --- a/lib/presentation/widgets/group_tile.dart +++ b/lib/presentation/widgets/group_tile.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/data/dto/group.dart'; +import 'package:skeletonizer/skeletonizer.dart'; class GroupTile extends StatelessWidget { const GroupTile({super.key, required this.group}); @@ -62,12 +63,14 @@ class GroupTile extends StatelessWidget { color: Colors.black38, borderRadius: BorderRadius.circular(12), ), - child: Text( - member.name, - style: const TextStyle( - fontSize: 17, - fontWeight: FontWeight.bold, - color: Colors.white, + child: Skeleton.ignore( + child: Text( + member.name, + style: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.bold, + color: Colors.white, + ), ), ), ), From 168d7748a98e2864b1b518a4d2617b867638bc19 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 16:26:08 +0100 Subject: [PATCH 11/28] added todo for getAllGroups tests --- test/db_tests/group_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/test/db_tests/group_test.dart b/test/db_tests/group_test.dart index a8fbcd5..d9e2c32 100644 --- a/test/db_tests/group_test.dart +++ b/test/db_tests/group_test.dart @@ -36,6 +36,7 @@ void main() { await database.close(); }); + //TODO: test getAllGroups method test('group and group members gets added correctly', () async { await database.groupDao.addGroup(group: testgroup); From 640830d8ab39e07339bf6a966d620f67f205fde9 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 16:26:28 +0100 Subject: [PATCH 12/28] fixed getAllGroups not returning members --- lib/data/dao/group_dao.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/data/dao/group_dao.dart b/lib/data/dao/group_dao.dart index 1f0e2c8..ffcb84a 100644 --- a/lib/data/dao/group_dao.dart +++ b/lib/data/dao/group_dao.dart @@ -14,9 +14,14 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { Future> getAllGroups() async { final query = select(groupTable); final result = await query.get(); - return result - .map((row) => Group(id: row.id, name: row.name, members: [])) - .toList(); + return Future.wait( + result.map((groupData) async { + final members = await db.playerGroupDao.getPlayersOfGroupById( + groupId: groupData.id, + ); + return Group(id: groupData.id, name: groupData.name, members: members); + }), + ); } /// Retrieves a [Group] by its [groupId], including its members. From 2dad822d79582686d82548a3af0e77d12ec0e2ad Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 16:34:51 +0100 Subject: [PATCH 13/28] add sample groups with sample members at app startup --- lib/main.dart | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index 98c40f8..b19eb45 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,8 @@ 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/group.dart'; +import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/views/main_menu/custom_navigation_bar.dart'; import 'package:provider/provider.dart'; @@ -19,6 +21,7 @@ class GameTracker extends StatelessWidget { @override Widget build(BuildContext context) { + addSampleGroupData(context); return MaterialApp( debugShowCheckedModeBanner: false, title: 'Game Tracker', @@ -39,4 +42,74 @@ class GameTracker extends StatelessWidget { home: const CustomNavigationBar(), ); } + + Future addSampleGroupData(BuildContext context) async { + final db = Provider.of(context, listen: false); + if (await db.groupDao.getGroupCount() == 0) { + final List allPlayers = [ + Player(id: '1', name: 'Alex'), + Player(id: '2', name: 'Ben'), + Player(id: '3', name: 'Chris'), + Player(id: '4', name: 'Daniel'), + Player(id: '5', name: 'Max Mustermann'), + Player(id: '6', name: 'Sebastian'), + Player(id: '7', name: 'Jonathan'), + Player(id: '8', name: 'Alexander'), + ]; + + // 2. Erstelle und füge 8 Gruppen mit unterschiedlicher Spieleranzahl hinzu + await db.groupDao.addGroup( + group: Group( + id: '1', + name: 'Anfänger', + members: allPlayers.sublist(0, 3), + ), + ); // 3 Spieler + await db.groupDao.addGroup( + group: Group( + id: '2', + name: 'Die glorreichen Sieben', + members: allPlayers.sublist(0, 7), + ), + ); // 7 Spieler + await db.groupDao.addGroup( + group: Group( + id: '3', + name: 'Profis', + members: allPlayers.sublist(4, 8), + ), + ); // 4 Spieler + await db.groupDao.addGroup( + group: Group( + id: '4', + name: 'Duo Infernale', + members: [allPlayers[0], allPlayers[7]], + ), + ); // 2 Spieler + await db.groupDao.addGroup( + group: Group( + id: '5', + name: 'Die fantastischen Fünf', + members: allPlayers.sublist(1, 6), + ), + ); // 5 Spieler + await db.groupDao.addGroup( + group: Group( + id: '6', + name: 'Feierabend-Zocker', + members: allPlayers.sublist(0, 6), + ), + ); // 6 Spieler + await db.groupDao.addGroup( + group: Group(id: '7', name: 'Alle Mann an Bord!', members: allPlayers), + ); // 8 Spieler + await db.groupDao.addGroup( + group: Group( + id: '8', + name: 'Testgruppe Alpha', + members: [allPlayers[1], allPlayers[3]], + ), + ); + } + } } From 2dd4f52336dfab9db96fda0de03bb80ad107fa28 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 16:42:18 +0100 Subject: [PATCH 14/28] removed sample groups from groups view --- .../views/main_menu/groups_view.dart | 82 ++++--------------- 1 file changed, 18 insertions(+), 64 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 0d5b993..c5f8def 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_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/group.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/full_width_button.dart'; import 'package:game_tracker/presentation/widgets/group_tile.dart'; import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; +import 'package:provider/provider.dart'; import 'package:skeletonizer/skeletonizer.dart'; class GroupsView extends StatefulWidget { @@ -15,76 +17,25 @@ class GroupsView extends StatefulWidget { } class _GroupsViewState extends State { - Future> _getMockGroups() async { - await Future.delayed(const Duration(seconds: 2)); - final player1 = Player(id: 'p1', name: 'Felix'); - final player2 = Player(id: 'p2', name: 'Yannick'); - final player3 = Player(id: 'p3', name: 'Mathis'); - final player4 = Player(id: 'p4', name: 'Petrus'); + late Future> _allGroupsFuture; - return [ - Group( - id: 'g1', - name: 'Weekend Warriors', - members: [ - player1, - player2, - player4, - player3, - player1, - player4, - player2, - ], - ), - Group(id: 'g2', name: 'Strategy Masters', members: [player3, player4]), - Group( - id: 'g3', - name: 'The Cardboard Crew', - members: [player1, player2, player3, player4], - ), - Group( - id: 'g4', - name: 'Gamers', - members: [player1, player3, player1, player4], - ), - Group( - id: 'g4', - name: 'The Group', - members: [player4, player1, player3, player4, player3], - ), - Group( - id: 'g4', - name: 'Friends', - members: [player4, player1, player3, player4], - ), - Group( - id: 'g4', - name: 'Sample Group', - members: [player1, player1, player4, player3], - ), - Group( - id: 'g4', - name: 'The Group', - members: [player1, player1, player3, player4], - ), - Group( - id: 'g4', - name: 'The Best', - members: [player1, player3, player1, player4, player1], - ), - ]; - } - - final player = Player(id: 'p1', name: 'Felix'); + final player = Player(id: 'p1', name: 'Sample'); late final List skeletonData = List.filled( 8, Group( - id: 'g1', - name: 'Weekend Warriors', + id: '0', + name: 'Sample Game', members: [player, player, player, player], ), ); + @override + void initState() { + super.initState(); + final db = Provider.of(context, listen: false); + _allGroupsFuture = db.groupDao.getAllGroups(); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -93,7 +44,7 @@ class _GroupsViewState extends State { alignment: Alignment.center, children: [ FutureBuilder>( - future: _getMockGroups(), + future: _allGroupsFuture, builder: (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.hasError) { @@ -134,8 +85,11 @@ class _GroupsViewState extends State { ), child: ListView.builder( padding: const EdgeInsets.only(bottom: 85), - itemCount: groups.length, + itemCount: groups.length + 1, itemBuilder: (BuildContext context, int index) { + if (index == groups.length) { + return const SizedBox(height: 60); + } return GroupTile(group: groups[index]); }, ), From 3bd522df6e3b355f81af29e5b9464fef68e13afa Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 18:29:27 +0100 Subject: [PATCH 15/28] change colors to fit home page --- lib/presentation/views/main_menu/groups_view.dart | 4 ++-- lib/presentation/widgets/group_tile.dart | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index c5f8def..6a3f404 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -69,8 +69,8 @@ class _GroupsViewState extends State { : (snapshot.data ?? []); return Skeletonizer( effect: PulseEffect( - from: Colors.grey[100]!, - to: Colors.grey[400]!, + from: Colors.grey[800]!, + to: Colors.grey[600]!, duration: const Duration(milliseconds: 800), ), enabled: isLoading, diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/group_tile.dart index a317248..f61d3ce 100644 --- a/lib/presentation/widgets/group_tile.dart +++ b/lib/presentation/widgets/group_tile.dart @@ -15,7 +15,8 @@ class GroupTile extends StatelessWidget { margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), decoration: BoxDecoration( - color: CustomTheme.secondaryColor, + color: CustomTheme.boxColor, + border: Border.all(color: CustomTheme.boxBorder), borderRadius: BorderRadius.circular(12), ), child: Column( @@ -30,7 +31,6 @@ class GroupTile extends StatelessWidget { style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 20, - color: Colors.white, ), ), const Spacer(), @@ -39,11 +39,10 @@ class GroupTile extends StatelessWidget { style: const TextStyle( fontWeight: FontWeight.w900, fontSize: 20, - color: Colors.white, ), ), const SizedBox(width: 3), - const Icon(Icons.group), + Icon(Icons.group), ], ), const SizedBox(height: 5), @@ -69,7 +68,6 @@ class GroupTile extends StatelessWidget { style: const TextStyle( fontSize: 17, fontWeight: FontWeight.bold, - color: Colors.white, ), ), ), From a707990356ef3d9292b6ce43e3a95b4f381c9061 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 18:36:38 +0100 Subject: [PATCH 16/28] added new color: onBoxColor --- lib/core/custom_theme.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/core/custom_theme.dart b/lib/core/custom_theme.dart index 438aab5..16e9585 100644 --- a/lib/core/custom_theme.dart +++ b/lib/core/custom_theme.dart @@ -5,6 +5,7 @@ class CustomTheme { static Color secondaryColor = const Color(0xFFAFA2FF); static Color backgroundColor = const Color(0xFF0B0B0B); static Color boxColor = const Color(0xFF101010); + static Color onBoxColor = const Color(0xFF181818); static Color boxBorder = const Color(0xFF272727); static AppBarTheme appBarTheme = AppBarTheme( From d931e85e9f1eca94a9f64f97863520b8a88142b6 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 18:36:54 +0100 Subject: [PATCH 17/28] changed member tile color --- lib/presentation/widgets/group_tile.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/group_tile.dart index f61d3ce..11d3e47 100644 --- a/lib/presentation/widgets/group_tile.dart +++ b/lib/presentation/widgets/group_tile.dart @@ -59,7 +59,7 @@ class GroupTile extends StatelessWidget { horizontal: 10, ), decoration: BoxDecoration( - color: Colors.black38, + color: CustomTheme.onBoxColor, borderRadius: BorderRadius.circular(12), ), child: Skeleton.ignore( From a6f40456d8fe0297bdd7ef697a0715d0dc2bd851 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 18:44:56 +0100 Subject: [PATCH 18/28] added missing const --- lib/presentation/widgets/group_tile.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/group_tile.dart index 11d3e47..ce6ba34 100644 --- a/lib/presentation/widgets/group_tile.dart +++ b/lib/presentation/widgets/group_tile.dart @@ -42,7 +42,7 @@ class GroupTile extends StatelessWidget { ), ), const SizedBox(width: 3), - Icon(Icons.group), + const Icon(Icons.group), ], ), const SizedBox(height: 5), From 8d8d4319d248ec6a7934bdc126df419ed4923e3a Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 19:37:51 +0100 Subject: [PATCH 19/28] change Mediaquery.of to .sizeOf --- lib/presentation/widgets/full_width_button.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/presentation/widgets/full_width_button.dart b/lib/presentation/widgets/full_width_button.dart index 2af6abe..bd18c64 100644 --- a/lib/presentation/widgets/full_width_button.dart +++ b/lib/presentation/widgets/full_width_button.dart @@ -12,7 +12,7 @@ class FullWidthButton extends StatelessWidget { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( - minimumSize: Size(MediaQuery.of(context).size.width * 0.90, 60), + minimumSize: Size(MediaQuery.sizeOf(context).width * 0.9, 60), backgroundColor: CustomTheme.primaryColor, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), From 38466c6056a8e05d6d8eded63dcc37ac68cdd691 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 19:38:08 +0100 Subject: [PATCH 20/28] added title and icon to gamehistoryview --- lib/presentation/views/main_menu/game_history_view.dart | 8 +++++++- 1 file changed, 7 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 f620cd7..3642a88 100644 --- a/lib/presentation/views/main_menu/game_history_view.dart +++ b/lib/presentation/views/main_menu/game_history_view.dart @@ -178,9 +178,15 @@ class _GameHistoryViewState extends State { Widget gameHistoryListView(allGameData, suggestedGameData) { if (suggestedGameData.isEmpty && allGameData.isEmpty) { - return TopCenteredMessage(message: "Keine Spiele erstellt"); + return TopCenteredMessage( + icon: Icons.info, + title: "Info", + message: "Keine Spiele erstellt", + ); } else if (suggestedGameData.isEmpty) { return TopCenteredMessage( + icon: Icons.search, + title: "Info", message: "Kein Spiel mit den Suchparametern gefunden.", ); } From deab074885001a0f4ef6451ebdaeaa1fdfff6294 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 19:38:26 +0100 Subject: [PATCH 21/28] changed font sizes & tile width --- lib/presentation/widgets/{ => tiles}/group_tile.dart | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) rename lib/presentation/widgets/{ => tiles}/group_tile.dart (90%) diff --git a/lib/presentation/widgets/group_tile.dart b/lib/presentation/widgets/tiles/group_tile.dart similarity index 90% rename from lib/presentation/widgets/group_tile.dart rename to lib/presentation/widgets/tiles/group_tile.dart index ce6ba34..448c68c 100644 --- a/lib/presentation/widgets/group_tile.dart +++ b/lib/presentation/widgets/tiles/group_tile.dart @@ -11,8 +11,7 @@ class GroupTile extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - width: MediaQuery.of(context).size.width * 0.90, - margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), decoration: BoxDecoration( color: CustomTheme.boxColor, @@ -30,7 +29,7 @@ class GroupTile extends StatelessWidget { overflow: TextOverflow.ellipsis, style: const TextStyle( fontWeight: FontWeight.bold, - fontSize: 20, + fontSize: 18, ), ), const Spacer(), @@ -38,11 +37,11 @@ class GroupTile extends StatelessWidget { '${group.members.length}', style: const TextStyle( fontWeight: FontWeight.w900, - fontSize: 20, + fontSize: 18, ), ), const SizedBox(width: 3), - const Icon(Icons.group), + const Icon(Icons.group, size: 22), ], ), const SizedBox(height: 5), @@ -66,7 +65,7 @@ class GroupTile extends StatelessWidget { child: Text( member.name, style: const TextStyle( - fontSize: 17, + fontSize: 14, fontWeight: FontWeight.bold, ), ), From 258f610e289b0c7bae92babbac77111d4bc11b85 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 19:39:34 +0100 Subject: [PATCH 22/28] added icons & titles to top contered messages --- lib/presentation/views/main_menu/groups_view.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 6a3f404..7b79a53 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -4,7 +4,7 @@ import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/widgets/full_width_button.dart'; -import 'package:game_tracker/presentation/widgets/group_tile.dart'; +import 'package:game_tracker/presentation/widgets/tiles/group_tile.dart'; import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; import 'package:provider/provider.dart'; import 'package:skeletonizer/skeletonizer.dart'; @@ -50,7 +50,9 @@ class _GroupsViewState extends State { if (snapshot.hasError) { return const Center( child: TopCenteredMessage( - message: 'Error while loading group data.', + icon: Icons.report, + title: "Error", + message: 'Group data couldn\'t\nbe loaded.', ), ); } @@ -58,6 +60,8 @@ class _GroupsViewState extends State { (!snapshot.hasData || snapshot.data!.isEmpty)) { return const Center( child: TopCenteredMessage( + icon: Icons.info, + title: "Info", message: 'No groups created yet.', ), ); From c1e032208cd79d6d28d01b2963ef8f70b89e786d Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 19:39:48 +0100 Subject: [PATCH 23/28] added icons, titles and changed font size --- .../widgets/top_centered_message.dart | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/lib/presentation/widgets/top_centered_message.dart b/lib/presentation/widgets/top_centered_message.dart index df8dcb1..af317d8 100644 --- a/lib/presentation/widgets/top_centered_message.dart +++ b/lib/presentation/widgets/top_centered_message.dart @@ -1,9 +1,16 @@ import 'package:flutter/material.dart'; class TopCenteredMessage extends StatelessWidget { - const TopCenteredMessage({super.key, required this.message}); + const TopCenteredMessage({ + super.key, + required this.icon, + required this.title, + required this.message, + }); + final String title; final String message; + final IconData icon; @override Widget build(BuildContext context) { @@ -11,10 +18,21 @@ class TopCenteredMessage extends StatelessWidget { padding: const EdgeInsets.only(top: 100), margin: const EdgeInsets.symmetric(horizontal: 10), alignment: Alignment.topCenter, - child: Text( - message, - style: const TextStyle(fontSize: 20), - textAlign: TextAlign.center, + child: Column( + children: [ + Icon(icon, size: 45), + SizedBox(height: 10), + Text( + title, + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + textAlign: TextAlign.center, + ), + Text( + message, + style: const TextStyle(fontSize: 16), + textAlign: TextAlign.center, + ), + ], ), ); } From accc1899493beddb472312248e4c15227dc9f60f Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 19:50:54 +0100 Subject: [PATCH 24/28] decreased number of tiles in skeleton --- lib/presentation/views/main_menu/groups_view.dart | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 7b79a53..11e2544 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -21,11 +21,11 @@ class _GroupsViewState extends State { final player = Player(id: 'p1', name: 'Sample'); late final List skeletonData = List.filled( - 8, + 7, Group( id: '0', name: 'Sample Game', - members: [player, player, player, player], + members: [player, player, player, player, player, player], ), ); @@ -68,16 +68,17 @@ class _GroupsViewState extends State { } final bool isLoading = snapshot.connectionState == ConnectionState.waiting; - final List groups = isLoading - ? skeletonData - : (snapshot.data ?? []); + final List groups = skeletonData; + //final List groups = isLoading + // ? skeletonData + // : (snapshot.data ?? []); return Skeletonizer( effect: PulseEffect( from: Colors.grey[800]!, to: Colors.grey[600]!, duration: const Duration(milliseconds: 800), ), - enabled: isLoading, + enabled: true, enableSwitchAnimation: true, switchAnimationConfig: const SwitchAnimationConfig( duration: Duration(milliseconds: 200), From 4befc85c9f9492b6bb3ce0eaa412aba9cf7a1354 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 19:52:31 +0100 Subject: [PATCH 25/28] added missing const --- lib/presentation/widgets/top_centered_message.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/presentation/widgets/top_centered_message.dart b/lib/presentation/widgets/top_centered_message.dart index af317d8..a5deea2 100644 --- a/lib/presentation/widgets/top_centered_message.dart +++ b/lib/presentation/widgets/top_centered_message.dart @@ -21,7 +21,7 @@ class TopCenteredMessage extends StatelessWidget { child: Column( children: [ Icon(icon, size: 45), - SizedBox(height: 10), + const SizedBox(height: 10), Text( title, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), From 9ffb7d6ca3c684379eeb34d1e6893fe3a9cceac4 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 19:53:32 +0100 Subject: [PATCH 26/28] changed skeleton to only show when loading --- lib/presentation/views/main_menu/groups_view.dart | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 11e2544..8b3bffe 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -68,17 +68,16 @@ class _GroupsViewState extends State { } final bool isLoading = snapshot.connectionState == ConnectionState.waiting; - final List groups = skeletonData; - //final List groups = isLoading - // ? skeletonData - // : (snapshot.data ?? []); + final List groups = isLoading + ? skeletonData + : (snapshot.data ?? []); return Skeletonizer( effect: PulseEffect( from: Colors.grey[800]!, to: Colors.grey[600]!, duration: const Duration(milliseconds: 800), ), - enabled: true, + enabled: isLoading, enableSwitchAnimation: true, switchAnimationConfig: const SwitchAnimationConfig( duration: Duration(milliseconds: 200), From a1d57fc42424dd625e7f79b83de54c49c156a20f Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 20:04:59 +0100 Subject: [PATCH 27/28] removed sample data for group view --- lib/main.dart | 73 --------------------------------------------------- 1 file changed, 73 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b19eb45..98c40f8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,6 @@ 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/group.dart'; -import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/presentation/views/main_menu/custom_navigation_bar.dart'; import 'package:provider/provider.dart'; @@ -21,7 +19,6 @@ class GameTracker extends StatelessWidget { @override Widget build(BuildContext context) { - addSampleGroupData(context); return MaterialApp( debugShowCheckedModeBanner: false, title: 'Game Tracker', @@ -42,74 +39,4 @@ class GameTracker extends StatelessWidget { home: const CustomNavigationBar(), ); } - - Future addSampleGroupData(BuildContext context) async { - final db = Provider.of(context, listen: false); - if (await db.groupDao.getGroupCount() == 0) { - final List allPlayers = [ - Player(id: '1', name: 'Alex'), - Player(id: '2', name: 'Ben'), - Player(id: '3', name: 'Chris'), - Player(id: '4', name: 'Daniel'), - Player(id: '5', name: 'Max Mustermann'), - Player(id: '6', name: 'Sebastian'), - Player(id: '7', name: 'Jonathan'), - Player(id: '8', name: 'Alexander'), - ]; - - // 2. Erstelle und füge 8 Gruppen mit unterschiedlicher Spieleranzahl hinzu - await db.groupDao.addGroup( - group: Group( - id: '1', - name: 'Anfänger', - members: allPlayers.sublist(0, 3), - ), - ); // 3 Spieler - await db.groupDao.addGroup( - group: Group( - id: '2', - name: 'Die glorreichen Sieben', - members: allPlayers.sublist(0, 7), - ), - ); // 7 Spieler - await db.groupDao.addGroup( - group: Group( - id: '3', - name: 'Profis', - members: allPlayers.sublist(4, 8), - ), - ); // 4 Spieler - await db.groupDao.addGroup( - group: Group( - id: '4', - name: 'Duo Infernale', - members: [allPlayers[0], allPlayers[7]], - ), - ); // 2 Spieler - await db.groupDao.addGroup( - group: Group( - id: '5', - name: 'Die fantastischen Fünf', - members: allPlayers.sublist(1, 6), - ), - ); // 5 Spieler - await db.groupDao.addGroup( - group: Group( - id: '6', - name: 'Feierabend-Zocker', - members: allPlayers.sublist(0, 6), - ), - ); // 6 Spieler - await db.groupDao.addGroup( - group: Group(id: '7', name: 'Alle Mann an Bord!', members: allPlayers), - ); // 8 Spieler - await db.groupDao.addGroup( - group: Group( - id: '8', - name: 'Testgruppe Alpha', - members: [allPlayers[1], allPlayers[3]], - ), - ); - } - } } From 10a45ac1f0cae5c0b00a8476a0a9e21fd4831df4 Mon Sep 17 00:00:00 2001 From: mathiskirchner Date: Sun, 16 Nov 2025 20:11:10 +0100 Subject: [PATCH 28/28] removed unneccessary double quotes --- lib/presentation/views/main_menu/groups_view.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/presentation/views/main_menu/groups_view.dart b/lib/presentation/views/main_menu/groups_view.dart index 8b3bffe..7f1f32d 100644 --- a/lib/presentation/views/main_menu/groups_view.dart +++ b/lib/presentation/views/main_menu/groups_view.dart @@ -51,7 +51,7 @@ class _GroupsViewState extends State { return const Center( child: TopCenteredMessage( icon: Icons.report, - title: "Error", + title: 'Error', message: 'Group data couldn\'t\nbe loaded.', ), ); @@ -61,7 +61,7 @@ class _GroupsViewState extends State { return const Center( child: TopCenteredMessage( icon: Icons.info, - title: "Info", + title: 'Info', message: 'No groups created yet.', ), );