diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 34e4be3..194849e 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -1,9 +1,13 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/data/db/database.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/quick_create_button.dart'; import 'package:game_tracker/presentation/widgets/tiles/game_tile.dart'; import 'package:game_tracker/presentation/widgets/tiles/info_tile.dart'; import 'package:game_tracker/presentation/widgets/tiles/quick_info_tile.dart'; +import 'package:game_tracker/presentation/widgets/top_centered_message.dart'; import 'package:provider/provider.dart'; import 'package:skeletonizer/skeletonizer.dart'; @@ -17,23 +21,43 @@ class HomeView extends StatefulWidget { class _HomeViewState extends State { late Future _gameCountFuture; late Future _groupCountFuture; + late Future> _recentGamesFuture; bool isLoading = true; + late final List skeletonData = List.filled( + 2, + Game( + name: 'Skeleton Game', + group: Group( + name: 'Skeleton Group', + members: [ + Player(name: 'Skeleton Player 1'), + Player(name: 'Skeleton Player 2'), + ], + ), + winner: + "Winner ID", //TODO: Should be player object, but isnt yet, waiting for pr + ), + ); + @override initState() { super.initState(); final db = Provider.of(context, listen: false); _gameCountFuture = db.gameDao.getGameCount(); _groupCountFuture = db.groupDao.getGroupCount(); + _recentGamesFuture = db.gameDao.getAllGames(); - Future.wait([_gameCountFuture, _groupCountFuture]).then((_) async { - await Future.delayed(const Duration(milliseconds: 50)); - if (mounted) { - setState(() { - isLoading = false; - }); - } - }); + Future.wait([_gameCountFuture, _groupCountFuture, _recentGamesFuture]).then( + (_) async { + await Future.delayed(const Duration(milliseconds: 50)); + if (mounted) { + setState(() { + isLoading = false; + }); + } + }, + ); } @override @@ -48,12 +72,21 @@ class _HomeViewState extends State { ), enabled: isLoading, enableSwitchAnimation: true, - switchAnimationConfig: const SwitchAnimationConfig( + switchAnimationConfig: SwitchAnimationConfig( duration: Duration(milliseconds: 200), switchInCurve: Curves.linear, switchOutCurve: Curves.linear, transitionBuilder: AnimatedSwitcher.defaultTransitionBuilder, - layoutBuilder: AnimatedSwitcher.defaultLayoutBuilder, + layoutBuilder: + (Widget? currentChild, List previousChildren) { + return Stack( + alignment: Alignment.topCenter, + children: [ + ...previousChildren, + if (currentChild != null) currentChild, + ], + ); + }, ), child: SingleChildScrollView( child: Column( @@ -97,41 +130,70 @@ class _HomeViewState extends State { ), ], ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16.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', + FutureBuilder( + future: _recentGamesFuture, + builder: (context, snapshot) { + if (snapshot.hasError) { + return const Center( + child: TopCenteredMessage( + icon: Icons.report, + title: 'Error', + message: 'Group data couldn\'t\nbe loaded.', + ), + ); + } + if (snapshot.connectionState == ConnectionState.done && + (!snapshot.hasData || snapshot.data!.isEmpty)) { + return const Center( + child: TopCenteredMessage( + icon: Icons.info, + title: 'Info', + message: 'No games created yet.', + ), + ); + } + final List games = + isLoading ? skeletonData : (snapshot.data ?? []) + ..sort((a, b) => b.createdAt.compareTo(a.createdAt)); + return Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: InfoTile( + width: constraints.maxWidth * 0.95, + title: 'Recent Games', + icon: Icons.timer, + content: Padding( + padding: EdgeInsets.symmetric(horizontal: 40.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GameTile( + gameTitle: games[0].name, + gameType: "Gametype", + ruleset: 'Ruleset', + players: _getPlayerText(games[0]), + winner: + 'Leonard', //TODO: Replace Winner with real Winner + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 8.0), + child: Divider(), + ), + GameTile( + gameTitle: games[1].name, + gameType: 'Gametype', + ruleset: 'Ruleset', + players: _getPlayerText(games[1]), + winner: + 'Lina', //TODO: Replace Winner with real Winner + ), + SizedBox(height: 8), + ], ), - 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), - ], + ), ), - ), - ), + ); + }, ), InfoTile( width: constraints.maxWidth * 0.95, @@ -189,4 +251,14 @@ class _HomeViewState extends State { }, ); } + + String _getPlayerText(Game game) { + if (game.group == null) { + return game.players?.map((p) => p.name).join(', ') ?? 'No Players'; + } + if (game.players == null || game.players!.isEmpty) { + return game.group!.name; + } + return '${game.group!.name} + ${game.players!.length}'; + } }