From e88211245c8f3d0387b3c62d869372accab9155e Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sun, 9 Nov 2025 23:33:29 +0100 Subject: [PATCH 1/4] Implemented first version of home view --- .../views/main_menu/home_view.dart | 45 +++++++++- lib/presentation/widgets/game_tile.dart | 82 +++++++++++++++++++ lib/presentation/widgets/info_tile.dart | 61 ++++++++++++++ .../widgets/quick_create_button.dart | 34 ++++++++ lib/presentation/widgets/quick_info_tile.dart | 2 +- 5 files changed, 221 insertions(+), 3 deletions(-) create mode 100644 lib/presentation/widgets/game_tile.dart create mode 100644 lib/presentation/widgets/info_tile.dart create mode 100644 lib/presentation/widgets/quick_create_button.dart diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 1a95b27..fb03c5f 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:game_tracker/presentation/widgets/game_tile.dart'; +import 'package:game_tracker/presentation/widgets/info_tile.dart'; +import 'package:game_tracker/presentation/widgets/quick_create_button.dart'; import 'package:game_tracker/presentation/widgets/quick_info_tile.dart'; class HomeView extends StatelessWidget { @@ -6,9 +9,10 @@ class HomeView extends StatelessWidget { @override Widget build(BuildContext context) { - return const Column( + return Column( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Row( + const Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ QuickInfoTile(title: 'Games', icon: Icons.casino, value: 42), @@ -19,6 +23,43 @@ class HomeView extends StatelessWidget { ), ], ), + const InfoTile( + title: 'Recent Games', + padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0), + icon: Icons.timer, + content: GameTile(), + ), + InfoTile( + title: 'Quick Create', + height: 210, + padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0), + icon: Icons.add_box_rounded, + content: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + QuickCreateButton(text: 'Cabo', onPressed: () {}), + QuickCreateButton(text: 'Uno', onPressed: () {}), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + QuickCreateButton(text: 'Phase 10', onPressed: () {}), + QuickCreateButton(text: 'Category 5', onPressed: () {}), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + QuickCreateButton(text: 'Category 6', onPressed: () {}), + QuickCreateButton(text: 'Category 7', onPressed: () {}), + ], + ), + ], + ), + ), ], ); } diff --git a/lib/presentation/widgets/game_tile.dart b/lib/presentation/widgets/game_tile.dart new file mode 100644 index 0000000..546531c --- /dev/null +++ b/lib/presentation/widgets/game_tile.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:game_tracker/core/custom_theme.dart'; + +class GameTile extends StatefulWidget { + const GameTile({super.key}); + + @override + State createState() => _GameTileState(); +} + +class _GameTileState extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(12), + height: 120, + width: 250, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: CustomTheme.boxColor, + border: Border.all(color: CustomTheme.boxBorder), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Row( + children: [ + Text( + 'Gametitle', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + SizedBox(width: 5), + Text( + 'Gametype', + style: TextStyle(fontSize: 14, color: Colors.grey), + ), + ], + ), + const SizedBox(height: 5), + Container( + padding: const EdgeInsets.symmetric(horizontal: 4), + height: 20, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: CustomTheme.primaryColor, + ), + child: const Text( + 'Ruleset', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + const Center( + child: Text( + '5 Player', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + const Spacer(), + Center( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 4), + width: 220, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: Colors.yellow.shade300, + ), + child: const Text( + 'In Progress', + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black87, + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/widgets/info_tile.dart b/lib/presentation/widgets/info_tile.dart new file mode 100644 index 0000000..a323556 --- /dev/null +++ b/lib/presentation/widgets/info_tile.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:game_tracker/core/custom_theme.dart'; + +class InfoTile extends StatefulWidget { + final String title; + final IconData icon; + final Widget content; + final EdgeInsets? padding; + final double? height; + const InfoTile({ + super.key, + required this.title, + required this.icon, + required this.content, + this.padding, + this.height, + }); + + @override + State createState() => _InfoTileState(); +} + +class _InfoTileState extends State { + @override + Widget build(BuildContext context) { + return Padding( + padding: widget.padding ?? const EdgeInsets.all(0), + child: Container( + padding: const EdgeInsets.all(12), + height: widget.height ?? 200, + width: 380, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: CustomTheme.boxColor, + border: Border.all(color: CustomTheme.boxBorder), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + children: [ + Icon(widget.icon), + const SizedBox(width: 5), + Text( + widget.title, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 10), + widget.content, + ], + ), + ), + ); + } +} diff --git a/lib/presentation/widgets/quick_create_button.dart b/lib/presentation/widgets/quick_create_button.dart new file mode 100644 index 0000000..bdf2945 --- /dev/null +++ b/lib/presentation/widgets/quick_create_button.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:game_tracker/core/custom_theme.dart'; + +class QuickCreateButton extends StatefulWidget { + final String text; + final VoidCallback? onPressed; + const QuickCreateButton({ + super.key, + required this.text, + required this.onPressed, + }); + + @override + State createState() => _QuickCreateButtonState(); +} + +class _QuickCreateButtonState extends State { + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: widget.onPressed, + + style: ElevatedButton.styleFrom( + minimumSize: const Size(140, 40), + backgroundColor: CustomTheme.primaryColor, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + ), + child: Text( + widget.text, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ); + } +} diff --git a/lib/presentation/widgets/quick_info_tile.dart b/lib/presentation/widgets/quick_info_tile.dart index 69ab5c6..6831c65 100644 --- a/lib/presentation/widgets/quick_info_tile.dart +++ b/lib/presentation/widgets/quick_info_tile.dart @@ -33,7 +33,7 @@ class _QuickInfoTileState extends State { children: [ Row( children: [ - const Icon(Icons.casino), + Icon(widget.icon), const SizedBox(width: 5), Text( widget.title, From 6cbc64c0421f4291e3b9252f3aebd8348f79b8c9 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Tue, 11 Nov 2025 15:34:16 +0100 Subject: [PATCH 2/4] Simplified game tile --- lib/presentation/widgets/game_tile.dart | 126 +++++++++++++----------- 1 file changed, 67 insertions(+), 59 deletions(-) diff --git a/lib/presentation/widgets/game_tile.dart b/lib/presentation/widgets/game_tile.dart index 546531c..c79a6b7 100644 --- a/lib/presentation/widgets/game_tile.dart +++ b/lib/presentation/widgets/game_tile.dart @@ -2,7 +2,20 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; class GameTile extends StatefulWidget { - const GameTile({super.key}); + final String gameTitle; + final String gameType; + final String ruleset; + final String players; + final String winner; + + const GameTile({ + super.key, + required this.gameTitle, + required this.gameType, + required this.ruleset, + required this.players, + required this.winner, + }); @override State createState() => _GameTileState(); @@ -11,72 +24,67 @@ class GameTile extends StatefulWidget { class _GameTileState extends State { @override Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(12), - height: 120, - width: 250, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: CustomTheme.boxColor, - border: Border.all(color: CustomTheme.boxBorder), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Row( - children: [ - Text( - 'Gametitle', - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - SizedBox(width: 5), - Text( - 'Gametype', - style: TextStyle(fontSize: 14, color: Colors.grey), - ), - ], + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + widget.gameTitle, + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(width: 5), + Text( + widget.gameType, + style: const TextStyle(fontSize: 14, color: Colors.grey), + ), + ], + ), + const SizedBox(height: 5), + Container( + padding: const EdgeInsets.symmetric(horizontal: 4), + height: 20, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: CustomTheme.primaryColor, ), - const SizedBox(height: 5), - Container( + child: Text( + widget.ruleset, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ), + Center( + heightFactor: 1.5, + child: Text( + widget.players, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ), + Center( + child: Container( padding: const EdgeInsets.symmetric(horizontal: 4), - height: 20, + width: 220, decoration: BoxDecoration( borderRadius: BorderRadius.circular(4), - color: CustomTheme.primaryColor, + color: Colors.yellow.shade300, ), - child: const Text( - 'Ruleset', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - const Center( - child: Text( - '5 Player', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - const Spacer(), - Center( - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 4), - width: 220, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - color: Colors.yellow.shade300, - ), - child: const Text( - 'In Progress', - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.bold, - color: Colors.black87, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.emoji_events, color: Colors.black, size: 20), + Text( + widget.winner, + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black87, + ), ), - ), + ], ), ), - ], - ), + ), + ], ); } } From 4f8ba002d3f1f2cb966aabe59eeaaeaa9a351153 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Tue, 11 Nov 2025 15:34:31 +0100 Subject: [PATCH 3/4] Overhauled layout building --- .../views/main_menu/home_view.dart | 135 ++++++++++++------ lib/presentation/widgets/info_tile.dart | 61 -------- .../widgets/quick_create_button.dart | 5 +- lib/presentation/widgets/tiles/info_tile.dart | 60 ++++++++ .../widgets/{ => tiles}/quick_info_tile.dart | 12 +- 5 files changed, 161 insertions(+), 112 deletions(-) delete mode 100644 lib/presentation/widgets/info_tile.dart create mode 100644 lib/presentation/widgets/tiles/info_tile.dart rename lib/presentation/widgets/{ => tiles}/quick_info_tile.dart (84%) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index fb03c5f..bbed244 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -1,66 +1,111 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/presentation/widgets/game_tile.dart'; -import 'package:game_tracker/presentation/widgets/info_tile.dart'; import 'package:game_tracker/presentation/widgets/quick_create_button.dart'; -import 'package:game_tracker/presentation/widgets/quick_info_tile.dart'; +import 'package:game_tracker/presentation/widgets/tiles/info_tile.dart'; +import 'package:game_tracker/presentation/widgets/tiles/quick_info_tile.dart'; class HomeView extends StatelessWidget { const HomeView({super.key}); @override Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - QuickInfoTile(title: 'Games', icon: Icons.casino, value: 42), - QuickInfoTile( - title: 'Groups', - icon: Icons.groups_rounded, - value: 5, - ), - ], - ), - const InfoTile( - title: 'Recent Games', - padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0), - icon: Icons.timer, - content: GameTile(), - ), - InfoTile( - title: 'Quick Create', - height: 210, - padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0), - icon: Icons.add_box_rounded, - content: Column( + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.center, children: [ - QuickCreateButton(text: 'Cabo', onPressed: () {}), - QuickCreateButton(text: 'Uno', onPressed: () {}), + QuickInfoTile( + width: constraints.maxWidth * 0.45, + height: constraints.maxHeight * 0.15, + title: 'Games', + icon: Icons.casino, + value: 42, + ), + SizedBox(width: constraints.maxWidth * 0.05), + QuickInfoTile( + width: constraints.maxWidth * 0.45, + height: constraints.maxHeight * 0.15, + title: 'Groups', + icon: Icons.groups_rounded, + value: 5, + ), ], ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - QuickCreateButton(text: 'Phase 10', onPressed: () {}), - QuickCreateButton(text: 'Category 5', onPressed: () {}), - ], + Padding( + padding: const EdgeInsets.symmetric(vertical: 24.0), + child: InfoTile( + width: constraints.maxWidth * 0.95, + title: 'Recent Games', + icon: Icons.timer, + content: const Padding( + padding: EdgeInsets.symmetric(horizontal: 40.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GameTile( + gameTitle: 'Gamenight', + gameType: 'Cabo', + ruleset: 'Lowest Points', + players: '5 Players', + winner: 'Leonard', + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 8.0), + child: Divider(), + ), + GameTile( + gameTitle: 'Schoolbreak', + gameType: 'Uno', + ruleset: 'Highest Points', + players: 'The Gang', + winner: 'Lina', + ), + SizedBox(height: 8), + ], + ), + ), + ), ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - QuickCreateButton(text: 'Category 6', onPressed: () {}), - QuickCreateButton(text: 'Category 7', onPressed: () {}), - ], + InfoTile( + width: constraints.maxWidth * 0.95, + title: 'Quick Create', + icon: Icons.add_box_rounded, + content: Column( + spacing: 8, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + QuickCreateButton(text: 'Category 1', onPressed: () {}), + QuickCreateButton(text: 'Category 2', onPressed: () {}), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + QuickCreateButton(text: 'Category 3', onPressed: () {}), + QuickCreateButton(text: 'Category 4', onPressed: () {}), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + QuickCreateButton(text: 'Category 5', onPressed: () {}), + QuickCreateButton(text: 'Category 6', onPressed: () {}), + ], + ), + ], + ), ), ], ), - ), - ], + ); + }, ); } } diff --git a/lib/presentation/widgets/info_tile.dart b/lib/presentation/widgets/info_tile.dart deleted file mode 100644 index a323556..0000000 --- a/lib/presentation/widgets/info_tile.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:game_tracker/core/custom_theme.dart'; - -class InfoTile extends StatefulWidget { - final String title; - final IconData icon; - final Widget content; - final EdgeInsets? padding; - final double? height; - const InfoTile({ - super.key, - required this.title, - required this.icon, - required this.content, - this.padding, - this.height, - }); - - @override - State createState() => _InfoTileState(); -} - -class _InfoTileState extends State { - @override - Widget build(BuildContext context) { - return Padding( - padding: widget.padding ?? const EdgeInsets.all(0), - child: Container( - padding: const EdgeInsets.all(12), - height: widget.height ?? 200, - width: 380, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: CustomTheme.boxColor, - border: Border.all(color: CustomTheme.boxBorder), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Row( - children: [ - Icon(widget.icon), - const SizedBox(width: 5), - Text( - widget.title, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 10), - widget.content, - ], - ), - ), - ); - } -} diff --git a/lib/presentation/widgets/quick_create_button.dart b/lib/presentation/widgets/quick_create_button.dart index bdf2945..3860f1c 100644 --- a/lib/presentation/widgets/quick_create_button.dart +++ b/lib/presentation/widgets/quick_create_button.dart @@ -19,15 +19,14 @@ class _QuickCreateButtonState extends State { Widget build(BuildContext context) { return ElevatedButton( onPressed: widget.onPressed, - style: ElevatedButton.styleFrom( - minimumSize: const Size(140, 40), + minimumSize: const Size(140, 45), backgroundColor: CustomTheme.primaryColor, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), child: Text( widget.text, - style: const TextStyle(fontWeight: FontWeight.bold), + style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ), ); } diff --git a/lib/presentation/widgets/tiles/info_tile.dart b/lib/presentation/widgets/tiles/info_tile.dart new file mode 100644 index 0000000..168262e --- /dev/null +++ b/lib/presentation/widgets/tiles/info_tile.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:game_tracker/core/custom_theme.dart'; + +class InfoTile extends StatefulWidget { + final String title; + final IconData icon; + final Widget content; + final EdgeInsets? padding; + final double? height; + final double? width; + const InfoTile({ + super.key, + required this.title, + required this.icon, + required this.content, + this.padding, + this.height, + this.width, + }); + + @override + State createState() => _InfoTileState(); +} + +class _InfoTileState extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: widget.padding ?? const EdgeInsets.all(12), + height: widget.height, + width: widget.width ?? 380, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: CustomTheme.boxColor, + border: Border.all(color: CustomTheme.boxBorder), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + children: [ + Icon(widget.icon), + const SizedBox(width: 5), + Text( + widget.title, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 10), + widget.content, + ], + ), + ); + } +} diff --git a/lib/presentation/widgets/quick_info_tile.dart b/lib/presentation/widgets/tiles/quick_info_tile.dart similarity index 84% rename from lib/presentation/widgets/quick_info_tile.dart rename to lib/presentation/widgets/tiles/quick_info_tile.dart index 6831c65..423b8d3 100644 --- a/lib/presentation/widgets/quick_info_tile.dart +++ b/lib/presentation/widgets/tiles/quick_info_tile.dart @@ -5,11 +5,17 @@ class QuickInfoTile extends StatefulWidget { final String title; final IconData icon; final int value; + final double? height; + final double? width; + final EdgeInsets? padding; const QuickInfoTile({ super.key, required this.title, required this.icon, required this.value, + this.height, + this.width, + this.padding, }); @override @@ -20,9 +26,9 @@ class _QuickInfoTileState extends State { @override Widget build(BuildContext context) { return Container( - padding: const EdgeInsets.all(12), - height: 110, - width: 180, + padding: widget.padding ?? const EdgeInsets.all(12), + height: widget.height ?? 110, + width: widget.width ?? 180, decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), color: CustomTheme.boxColor, From dd754eb5696bfb02998b6463d97211bee82c058a Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Tue, 11 Nov 2025 21:03:10 +0100 Subject: [PATCH 4/4] Implemented retrieving game and group count from the db --- lib/data/dao/game_dao.dart | 9 +++ lib/data/dao/group_dao.dart | 9 +++ .../views/main_menu/home_view.dart | 60 +++++++++++++++---- 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/lib/data/dao/game_dao.dart b/lib/data/dao/game_dao.dart index e59fae4..3b6529a 100644 --- a/lib/data/dao/game_dao.dart +++ b/lib/data/dao/game_dao.dart @@ -22,4 +22,13 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { final result = await query.getSingle(); return Game(id: result.id, name: result.name); } + + /// Retrieves the number of games in the database. + Future getGameCount() async { + final count = + await (selectOnly(gameTable)..addColumns([gameTable.id.count()])) + .map((row) => row.read(gameTable.id.count())) + .getSingle(); + return count ?? 0; + } } diff --git a/lib/data/dao/group_dao.dart b/lib/data/dao/group_dao.dart index c1932d3..7dc144d 100644 --- a/lib/data/dao/group_dao.dart +++ b/lib/data/dao/group_dao.dart @@ -56,4 +56,13 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { ); return rowsAffected > 0; } + + /// Retrieves the number of groups in the database. + Future getGroupCount() async { + final count = + await (selectOnly(groupTable)..addColumns([groupTable.id.count()])) + .map((row) => row.read(groupTable.id.count())) + .getSingle(); + return count ?? 0; + } } diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index bbed244..42cb822 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -1,12 +1,30 @@ import 'package:flutter/material.dart'; +import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/presentation/widgets/game_tile.dart'; import 'package:game_tracker/presentation/widgets/quick_create_button.dart'; import 'package:game_tracker/presentation/widgets/tiles/info_tile.dart'; import 'package:game_tracker/presentation/widgets/tiles/quick_info_tile.dart'; +import 'package:provider/provider.dart'; -class HomeView extends StatelessWidget { +class HomeView extends StatefulWidget { const HomeView({super.key}); + @override + State createState() => _HomeViewState(); +} + +class _HomeViewState extends State { + late Future _gameCountFuture; + late Future _groupCountFuture; + + @override + initState() { + super.initState(); + final db = Provider.of(context, listen: false); + _gameCountFuture = db.gameDao.getGameCount(); + _groupCountFuture = db.groupDao.getGroupCount(); + } + @override Widget build(BuildContext context) { return LayoutBuilder( @@ -18,20 +36,36 @@ class HomeView extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - QuickInfoTile( - width: constraints.maxWidth * 0.45, - height: constraints.maxHeight * 0.15, - title: 'Games', - icon: Icons.casino, - value: 42, + FutureBuilder( + future: _gameCountFuture, + builder: (context, snapshot) { + final int count = (snapshot.hasData) ? snapshot.data! : 0; + return QuickInfoTile( + width: constraints.maxWidth * 0.45, + height: constraints.maxHeight * 0.15, + title: 'Games', + icon: Icons.groups_rounded, + value: count, + ); + }, ), SizedBox(width: constraints.maxWidth * 0.05), - QuickInfoTile( - width: constraints.maxWidth * 0.45, - height: constraints.maxHeight * 0.15, - title: 'Groups', - icon: Icons.groups_rounded, - value: 5, + FutureBuilder( + future: _groupCountFuture, + builder: (context, snapshot) { + final int count = + (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) + ? snapshot.data! + : 0; + return QuickInfoTile( + width: constraints.maxWidth * 0.45, + height: constraints.maxHeight * 0.15, + title: 'Groups', + icon: Icons.groups_rounded, + value: count, + ); + }, ), ], ),