diff --git a/lib/data/dao/game_dao.dart b/lib/data/dao/game_dao.dart index f07e2c7..98ac6c3 100644 --- a/lib/data/dao/game_dao.dart +++ b/lib/data/dao/game_dao.dart @@ -176,4 +176,25 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { final rowsAffected = await query.go(); return rowsAffected > 0; } + + /// Retrieves all games with their respective match counts. + /// Returns a list of tuples (Game, matchCount). + Future> getGameUsage() async { + final games = await getAllGames(); + + final results = <(Game, int)>[]; + + for (final game in games) { + final matchCount = + await (selectOnly(db.matchTable) + ..where(db.matchTable.gameId.equals(game.id)) + ..addColumns([db.matchTable.id.count()])) + .map((row) => row.read(db.matchTable.id.count())) + .getSingle(); + + results.add((game, matchCount ?? 0)); + } + + return results; + } } diff --git a/lib/presentation/views/main_menu/match_view/create_match/choose_game_view.dart b/lib/presentation/views/main_menu/match_view/create_match/choose_game_view.dart index 42d5253..fca65bb 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/choose_game_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/choose_game_view.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:tallee/core/adaptive_page_route.dart'; import 'package:tallee/core/common.dart'; import 'package:tallee/core/custom_theme.dart'; +import 'package:tallee/data/db/database.dart'; import 'package:tallee/data/models/game.dart'; import 'package:tallee/l10n/generated/app_localizations.dart'; import 'package:tallee/presentation/views/main_menu/match_view/create_match/create_game/create_game_view.dart'; @@ -34,6 +36,10 @@ class ChooseGameView extends StatefulWidget { } class _ChooseGameViewState extends State { + late final AppDatabase db; + + late List<(Game, int)> gameCounts = []; + /// Controller for the search bar final TextEditingController searchBarController = TextEditingController(); @@ -45,6 +51,9 @@ class _ChooseGameViewState extends State { @override void initState() { + db = Provider.of(context, listen: false); + fetchGameCounts(); + selectedGameId = widget.initialGameId; // Start with all games visible @@ -150,6 +159,7 @@ class _ChooseGameViewState extends State { adaptivePageRoute( builder: (context) => CreateGameView( gameToEdit: game, + canDelete: canDeleteGame(game), onGameChanged: () { widget.onGamesUpdated?.call(); }, @@ -209,4 +219,16 @@ class _ChooseGameViewState extends State { void _refreshFromSource() { _applySearchFilter(searchBarController.text); } + + Future fetchGameCounts() async { + gameCounts = await db.gameDao.getGameUsage(); + } + + // A game can only be deleted if there are no matches using it + bool canDeleteGame(Game game) { + final count = gameCounts + .firstWhere((gc) => gc.$1.id == game.id, orElse: () => (game, 0)) + .$2; + return count == 0; + } } diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_game/create_game_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_game/create_game_view.dart index c27ecac..ba4d101 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_game/create_game_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_game/create_game_view.dart @@ -23,15 +23,18 @@ import 'package:tallee/presentation/widgets/tiles/choose_tile.dart'; class CreateGameView extends StatefulWidget { const CreateGameView({ super.key, - this.gameToEdit, required this.onGameChanged, + this.gameToEdit, + this.canDelete = false, }); + /// Callback to invoke when the game is created or edited + final VoidCallback onGameChanged; + /// An optional game to prefill the fields final Game? gameToEdit; - /// Callback to invoke when the game is created or edited - final VoidCallback onGameChanged; + final bool canDelete; @override State createState() => _CreateGameViewState(); @@ -41,7 +44,6 @@ class _CreateGameViewState extends State { /// GlobalKey for ScaffoldMessenger to show snackbars final _scaffoldMessengerKey = GlobalKey(); - /// The database instance for accessing game data. late final AppDatabase db; /// The currently selected ruleset for the game. @@ -133,13 +135,12 @@ class _CreateGameViewState extends State { backgroundColor: CustomTheme.backgroundColor, appBar: AppBar( title: Text(isEditing ? loc.edit_game : loc.create_game), - actions: widget.gameToEdit == null - ? [] - : [ - IconButton( - icon: const Icon(Icons.delete), - onPressed: () async { - if (widget.gameToEdit != null) { + actions: [ + if (isEditMode()) + IconButton( + icon: const Icon(Icons.delete), + onPressed: widget.canDelete + ? () async { showDialog( context: context, builder: (context) => CustomAlertDialog( @@ -176,9 +177,9 @@ class _CreateGameViewState extends State { } }); } - }, - ), - ], + : null, + ), + ], ), body: SafeArea( child: Column(