diff --git a/lib/presentation/views/main_menu/create_game/create_game_view.dart b/lib/presentation/views/main_menu/create_game/create_game_view.dart index 4c892b9..5f3b97b 100644 --- a/lib/presentation/views/main_menu/create_game/create_game_view.dart +++ b/lib/presentation/views/main_menu/create_game/create_game_view.dart @@ -4,10 +4,11 @@ import 'package:game_tracker/core/enums.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/views/main_menu/create_game/choose_group_view.dart'; import 'package:game_tracker/presentation/views/main_menu/create_game/choose_ruleset_view.dart'; -import 'package:game_tracker/presentation/widgets/app_skeleton.dart'; import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart'; +import 'package:game_tracker/presentation/widgets/player_selection.dart'; import 'package:game_tracker/presentation/widgets/text_input/text_input_field.dart'; import 'package:provider/provider.dart'; @@ -19,12 +20,23 @@ class CreateGameView extends StatefulWidget { } class _CreateGameViewState extends State { + /// Reference to the app database late final AppDatabase db; + + /// Futures to load all groups and players from the database late Future> _allGroupsFuture; + + /// Future to load all players from the database + late Future> _allPlayersFuture; + + /// Controller for the game name input field final TextEditingController _gameNameController = TextEditingController(); /// List of all groups from the database - late final List groupsList; + List groupsList = []; + + /// List of all players from the database + List playerList = []; /// The currently selected group Group? selectedGroup; @@ -40,8 +52,6 @@ class _CreateGameViewState extends State { /// the [ChooseRulesetView] int selectedRulesetIndex = -1; - bool isLoading = true; - /// List of available rulesets with their display names and descriptions /// as tuples of (Ruleset, String, String) List<(Ruleset, String, String)> rulesets = [ @@ -73,16 +83,11 @@ class _CreateGameViewState extends State { db = Provider.of(context, listen: false); _allGroupsFuture = db.groupDao.getAllGroups(); + _allPlayersFuture = db.playerDao.getAllPlayers(); - Future.wait([_allGroupsFuture]).then((result) async { - await Future.delayed(const Duration(milliseconds: 250)); - groupsList = result[0]; - - if (mounted) { - setState(() { - isLoading = false; - }); - } + Future.wait([_allGroupsFuture, _allPlayersFuture]).then((result) async { + groupsList = result[0] as List; + playerList = result[1] as List; }); } @@ -100,147 +105,149 @@ class _CreateGameViewState extends State { centerTitle: true, ), body: SafeArea( - child: AppSkeleton( - enabled: isLoading, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: const EdgeInsets.symmetric( - horizontal: 12, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + child: TextInputField( + controller: _gameNameController, + hintText: 'Game name', + onChanged: (value) { + setState(() {}); + }, + ), + ), + GestureDetector( + onTap: () async { + selectedRuleset = await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ChooseRulesetView( + rulesets: rulesets, + initialRulesetIndex: selectedRulesetIndex, + ), + ), + ); + selectedRulesetIndex = rulesets.indexWhere( + (r) => r.$1 == selectedRuleset, + ); + setState(() {}); + }, + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 5), + padding: const EdgeInsets.symmetric( vertical: 10, + horizontal: 15, ), - child: TextInputField( - controller: _gameNameController, - hintText: 'Game name', - onChanged: (value) { - setState(() {}); - }, - ), - ), - - GestureDetector( - onTap: () async { - selectedRuleset = await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ChooseRulesetView( - rulesets: rulesets, - initialRulesetIndex: selectedRulesetIndex, - ), - ), - ); - selectedRulesetIndex = rulesets.indexWhere( - (r) => r.$1 == selectedRuleset, - ); - setState(() {}); - }, - child: Container( - margin: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 5, - ), - padding: const EdgeInsets.symmetric( - vertical: 10, - horizontal: 15, - ), - decoration: CustomTheme.standardBoxDecoration, - child: Row( - children: [ - const Text( - 'Ruleset', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - const Spacer(), - Text( - selectedRuleset == null - ? 'None' - : translateRulesetToString(selectedRuleset!), - ), - const SizedBox(width: 10), - const Icon(Icons.arrow_forward_ios, size: 16), - ], - ), - ), - ), - GestureDetector( - onTap: () async { - selectedGroup = await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ChooseGroupView( - groups: groupsList, - initialGroupIndex: selectedGroupIndex, - ), - ), - ); - selectedGroupIndex = groupsList.indexWhere( - (g) => g.id == selectedGroup?.id, - ); - setState(() {}); - }, - child: Container( - margin: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 5, - ), - padding: const EdgeInsets.symmetric( - vertical: 10, - horizontal: 15, - ), - decoration: CustomTheme.standardBoxDecoration, - child: Row( - children: [ - const Text( - 'Group', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - const Spacer(), - Text( - selectedGroup == null ? 'None' : selectedGroup!.name, - ), - const SizedBox(width: 10), - const Icon(Icons.arrow_forward_ios, size: 16), - ], - ), - ), - ), - Container( decoration: CustomTheme.standardBoxDecoration, - width: MediaQuery.of(context).size.width * 0.95, - height: 400, - padding: const EdgeInsets.all(12), - margin: const EdgeInsets.symmetric(vertical: 10), - child: const Center(child: Text('PlayerComponent')), + child: Row( + children: [ + const Text( + 'Ruleset', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const Spacer(), + Text( + selectedRuleset == null + ? 'None' + : translateRulesetToString(selectedRuleset!), + ), + const SizedBox(width: 10), + const Icon(Icons.arrow_forward_ios, size: 16), + ], + ), ), - const Spacer(), - CustomWidthButton( - text: 'Create game', - sizeRelativeToWidth: 0.95, - buttonType: ButtonType.primary, - onPressed: - (_gameNameController.text.isEmpty || - selectedGroup == null || - selectedRuleset == null) - ? null - : () async { - Game game = Game( - name: _gameNameController.text.trim(), - createdAt: DateTime.now(), - group: selectedGroup!, - ); - // TODO: Replace with navigation to GameResultView() - print('Created game: $game'); - Navigator.pop(context); - }, + ), + GestureDetector( + onTap: () async { + selectedGroup = await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ChooseGroupView( + groups: groupsList, + initialGroupIndex: selectedGroupIndex, + ), + ), + ); + selectedGroupIndex = groupsList.indexWhere( + (g) => g.id == selectedGroup?.id, + ); + print('selectedGroup: $selectedGroup'); + print( + playerList + .where( + (p) => !selectedGroup!.members.any((m) => m.id == p.id), + ) + .toList(), + ); + setState(() {}); + }, + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 5), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 15, + ), + decoration: CustomTheme.standardBoxDecoration, + child: Row( + children: [ + const Text( + 'Group', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const Spacer(), + Text(selectedGroup == null ? 'None' : selectedGroup!.name), + const SizedBox(width: 10), + const Icon(Icons.arrow_forward_ios, size: 16), + ], + ), ), - const SizedBox(height: 20), - ], - ), + ), + Expanded( + child: PlayerSelection( + key: ValueKey(selectedGroup?.id ?? 'no_group'), + initialPlayers: selectedGroup == null + ? playerList + : playerList + .where( + (p) => !selectedGroup!.members.any( + (m) => m.id == p.id, + ), + ) + .toList(), + onChanged: (value) { + print(value); + }, + ), + ), + + CustomWidthButton( + text: 'Create game', + sizeRelativeToWidth: 0.95, + buttonType: ButtonType.primary, + onPressed: + (_gameNameController.text.isEmpty || + selectedGroup == null || + selectedRuleset == null) + ? null + : () async { + Game game = Game( + name: _gameNameController.text.trim(), + createdAt: DateTime.now(), + group: selectedGroup!, + ); + // TODO: Replace with navigation to GameResultView() + print('Created game: $game'); + Navigator.pop(context); + }, + ), + const SizedBox(height: 20), + ], ), ), ); diff --git a/lib/presentation/widgets/player_selection.dart b/lib/presentation/widgets/player_selection.dart index 592226c..092a613 100644 --- a/lib/presentation/widgets/player_selection.dart +++ b/lib/presentation/widgets/player_selection.dart @@ -11,8 +11,13 @@ import 'package:provider/provider.dart'; class PlayerSelection extends StatefulWidget { final Function(List value) onChanged; + final List initialPlayers; - const PlayerSelection({super.key, required this.onChanged}); + const PlayerSelection({ + super.key, + required this.onChanged, + this.initialPlayers = const [], + }); @override State createState() => _PlayerSelectionState(); @@ -46,9 +51,14 @@ class _PlayerSelectionState extends State { suggestedPlayers = skeletonData; _allPlayersFuture.then((loadedPlayers) { setState(() { - loadedPlayers.sort((a, b) => a.name.compareTo(b.name)); - allPlayers = [...loadedPlayers]; - suggestedPlayers = [...loadedPlayers]; + if (widget.initialPlayers.isNotEmpty) { + allPlayers = [...widget.initialPlayers]; + suggestedPlayers = [...widget.initialPlayers]; + } else { + loadedPlayers.sort((a, b) => a.name.compareTo(b.name)); + allPlayers = [...loadedPlayers]; + suggestedPlayers = [...loadedPlayers]; + } }); }); }