diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 2230a91..d9cd1ab 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -1,5 +1,8 @@ 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'; @@ -17,23 +20,42 @@ 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: Player(name: 'Skeleton Player 1'), + ), + ); + @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: 250)); - if (mounted) { - setState(() { - isLoading = false; - }); - } - }); + Future.wait([_gameCountFuture, _groupCountFuture, _recentGamesFuture]).then( + (_) async { + await Future.delayed(const Duration(milliseconds: 250)); + if (mounted) { + setState(() { + isLoading = false; + }); + } + }, + ); } @override @@ -48,12 +70,21 @@ class _HomeViewState extends State { ), enabled: isLoading, enableSwitchAnimation: true, - switchAnimationConfig: const SwitchAnimationConfig( - duration: Duration(milliseconds: 200), + switchAnimationConfig: SwitchAnimationConfig( + duration: const 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( @@ -103,32 +134,91 @@ class _HomeViewState extends State { 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), - ], + content: Padding( + padding: const EdgeInsets.symmetric(horizontal: 40.0), + child: FutureBuilder( + future: _recentGamesFuture, + builder: + ( + BuildContext context, + AsyncSnapshot> snapshot, + ) { + if (snapshot.hasError) { + return const Center( + heightFactor: 4, + child: Text( + 'Error while loading recent games.', + ), + ); + } + if (snapshot.connectionState == + ConnectionState.done && + (!snapshot.hasData || + snapshot.data!.isEmpty)) { + return const Center( + heightFactor: 4, + child: Text('No recent games available.'), + ); + } + final List games = + (isLoading + ? skeletonData + : (snapshot.data ?? []) + ..sort( + (a, b) => b.createdAt.compareTo( + a.createdAt, + ), + )) + .take(2) + .toList(); + if (games.isNotEmpty) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GameTile( + gameTitle: games[0].name, + gameType: 'Winner', + ruleset: 'Ruleset', + players: _getPlayerText(games[0]), + winner: games[0].winner == null + ? 'Game in progress...' + : games[0].winner!.name, + ), + const Padding( + padding: EdgeInsets.symmetric( + vertical: 8.0, + ), + child: Divider(), + ), + if (games.length > 1) ...[ + GameTile( + gameTitle: games[1].name, + gameType: 'Winner', + ruleset: 'Ruleset', + players: _getPlayerText(games[1]), + winner: games[1].winner == null + ? 'Game in progress...' + : games[1].winner!.name, + ), + const SizedBox(height: 8), + ] else ...[ + const Center( + heightFactor: 4, + child: Text( + 'No second game available.', + ), + ), + ], + ], + ); + } else { + return const Center( + heightFactor: 4, + child: Text('No recent games available.'), + ); + } + }, ), ), ), @@ -189,4 +279,15 @@ class _HomeViewState extends State { }, ); } + + String _getPlayerText(Game game) { + if (game.group == null) { + final playerCount = game.players?.length ?? 0; + return '$playerCount Players'; + } + if (game.players == null || game.players!.isEmpty) { + return game.group!.name; + } + return '${game.group!.name} + ${game.players!.length}'; + } }