diff --git a/lib/presentation/views/main_menu/custom_navigation_bar.dart b/lib/presentation/views/main_menu/custom_navigation_bar.dart index a110419..b17f63d 100644 --- a/lib/presentation/views/main_menu/custom_navigation_bar.dart +++ b/lib/presentation/views/main_menu/custom_navigation_bar.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/l10n/generated/app_localizations.dart'; -import 'package:game_tracker/presentation/views/main_menu/group_view/groups_view.dart'; +import 'package:game_tracker/presentation/views/main_menu/group_view/group_view.dart'; import 'package:game_tracker/presentation/views/main_menu/home_view.dart'; import 'package:game_tracker/presentation/views/main_menu/match_view/match_view.dart'; import 'package:game_tracker/presentation/views/main_menu/settings_view/settings_view.dart'; diff --git a/lib/presentation/views/main_menu/group_view/create_group_view.dart b/lib/presentation/views/main_menu/group_view/create_group_view.dart index e69de29..678872a 100644 --- a/lib/presentation/views/main_menu/group_view/create_group_view.dart +++ b/lib/presentation/views/main_menu/group_view/create_group_view.dart @@ -0,0 +1,185 @@ +import 'package:flutter/material.dart'; +import 'package:game_tracker/core/custom_theme.dart'; +import 'package:game_tracker/core/enums.dart'; +import 'package:game_tracker/data/db/database.dart'; +import 'package:game_tracker/data/dto/group.dart'; +import 'package:game_tracker/data/dto/player.dart'; +import 'package:game_tracker/l10n/generated/app_localizations.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'; + +class CreateGroupView extends StatefulWidget { + const CreateGroupView({super.key, this.groupToEdit}); + + /// The group to edit, if any + final Group? groupToEdit; + + @override + State createState() => _CreateGroupViewState(); +} + +class _CreateGroupViewState extends State { + late final AppDatabase db; + + /// GlobalKey for ScaffoldMessenger to show snackbars + final _scaffoldMessengerKey = GlobalKey(); + + /// Controller for the group name input field + final _groupNameController = TextEditingController(); + + /// List of currently selected players + List selectedPlayers = []; + + /// List of initially selected players (when editing a group) + List initialSelectedPlayers = []; + + @override + void initState() { + super.initState(); + db = Provider.of(context, listen: false); + if(widget.groupToEdit != null) { + _groupNameController.text = widget.groupToEdit!.name; + setState(() { + initialSelectedPlayers = widget.groupToEdit!.members; + selectedPlayers = widget.groupToEdit!.members; + }); + } + _groupNameController.addListener(() { + setState(() {}); + }); + } + + @override + void dispose() { + _groupNameController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final loc = AppLocalizations.of(context); + return ScaffoldMessenger( + key: _scaffoldMessengerKey, + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: CustomTheme.backgroundColor, + appBar: AppBar(title: Text(widget.groupToEdit == null ? loc.create_new_group : loc.edit_group), actions: widget.groupToEdit == null ? [] : [IconButton(icon: const Icon(Icons.delete), onPressed: () async { + if(widget.groupToEdit != null) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(loc.delete_group), + content: Text(loc.this_cannot_be_undone), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: Text(loc.cancel), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text(loc.delete), + ), + ], + ), + ).then((confirmed) async { + if (confirmed == true && context.mounted) { + bool success = await db.groupDao.deleteGroup(groupId: widget.groupToEdit!.id); + if (!context.mounted) return; + if (success) { + Navigator.pop(context); + } else { + if (!mounted) return; + showSnackbar(message: loc.error_deleting_group); + } + } + }); + } + },)],), + body: SafeArea( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: CustomTheme.standardMargin, + child: TextInputField( + controller: _groupNameController, + hintText: loc.group_name, + ), + ), + Expanded( + child: PlayerSelection( + initialSelectedPlayers: initialSelectedPlayers, + onChanged: (value) { + setState(() { + selectedPlayers = [...value]; + }); + }, + ), + ), + CustomWidthButton( + text: widget.groupToEdit == null ? loc.create_group : loc.edit_group, + sizeRelativeToWidth: 0.95, + buttonType: ButtonType.primary, + onPressed: + (_groupNameController.text.isEmpty || + (selectedPlayers.length < 2)) + ? null + : () async { + late Group? updatedGroup; + late bool success; + if (widget.groupToEdit == null) { + success = await db.groupDao.addGroup( + group: Group( + name: _groupNameController.text.trim(), + members: selectedPlayers, + ), + ); + } else { + updatedGroup = Group( + id: widget.groupToEdit!.id, + name: _groupNameController.text.trim(), + members: selectedPlayers, + ); + //TODO: Implement group editing in database + /* + success = await db.groupDao.updateGroup( + group: updatedGroup, + ); + */ + success = true; + } + if (!context.mounted) return; + if (success) { + Navigator.pop(context, updatedGroup); + } else { + showSnackbar(message: widget.groupToEdit == null ? loc.error_creating_group : loc.error_editing_group); + } + }, + ), + const SizedBox(height: 20), + ], + ), + ), + ), + ); + } + /// Displays a snackbar with the given message and optional action. + /// + /// [message] The message to display in the snackbar. + void showSnackbar({ + required String message, + }) { + final messenger = _scaffoldMessengerKey.currentState; + if (messenger != null) { + messenger.hideCurrentSnackBar(); + messenger.showSnackBar( + SnackBar( + content: Text(message, style: const TextStyle(color: Colors.white)), + backgroundColor: CustomTheme.boxColor, + ), + ); + } + } +} diff --git a/lib/presentation/views/main_menu/group_view/group_create_view.dart b/lib/presentation/views/main_menu/group_view/group_create_view.dart deleted file mode 100644 index 74b3974..0000000 --- a/lib/presentation/views/main_menu/group_view/group_create_view.dart +++ /dev/null @@ -1,184 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:game_tracker/core/custom_theme.dart'; -import 'package:game_tracker/core/enums.dart'; -import 'package:game_tracker/data/db/database.dart'; -import 'package:game_tracker/data/dto/group.dart'; -import 'package:game_tracker/data/dto/player.dart'; -import 'package:game_tracker/l10n/generated/app_localizations.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'; - -class GroupCreateView extends StatefulWidget { - const GroupCreateView({super.key, this.groupToEdit}); - - /// The group to edit, if any - final Group? groupToEdit; - - @override - State createState() => _GroupCreateViewState(); -} - -class _GroupCreateViewState extends State { - late final AppDatabase db; - - /// GlobalKey for ScaffoldMessenger to show snackbars - final _scaffoldMessengerKey = GlobalKey(); - - /// Controller for the group name input field - final _groupNameController = TextEditingController(); - - /// List of currently selected players - List selectedPlayers = []; - - /// List of initially selected players (when editing a group) - List initialSelectedPlayers = []; - - @override - void initState() { - super.initState(); - db = Provider.of(context, listen: false); - if(widget.groupToEdit != null) { - _groupNameController.text = widget.groupToEdit!.name; - setState(() { - initialSelectedPlayers = widget.groupToEdit!.members; - selectedPlayers = widget.groupToEdit!.members; - }); - } - _groupNameController.addListener(() { - setState(() {}); - }); - } - - @override - void dispose() { - _groupNameController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final loc = AppLocalizations.of(context); - return ScaffoldMessenger( - key: _scaffoldMessengerKey, - child: Scaffold( - backgroundColor: CustomTheme.backgroundColor, - appBar: AppBar(title: Text(widget.groupToEdit == null ? loc.create_new_group : loc.edit_group), actions: widget.groupToEdit == null ? [] : [IconButton(icon: const Icon(Icons.delete), onPressed: () async { - if(widget.groupToEdit != null) { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text(loc.delete_group), - content: Text(loc.this_cannot_be_undone), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: Text(loc.cancel), - ), - TextButton( - onPressed: () => Navigator.of(context).pop(true), - child: Text(loc.delete), - ), - ], - ), - ).then((confirmed) async { - if (confirmed == true && context.mounted) { - bool success = await db.groupDao.deleteGroup(groupId: widget.groupToEdit!.id); - if (!context.mounted) return; - if (success) { - Navigator.pop(context); - } else { - if (!mounted) return; - showSnackbar(message: loc.error_deleting_group); - } - } - }); - } - },)],), - body: SafeArea( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: CustomTheme.standardMargin, - child: TextInputField( - controller: _groupNameController, - hintText: loc.group_name, - ), - ), - Expanded( - child: PlayerSelection( - initialSelectedPlayers: initialSelectedPlayers, - onChanged: (value) { - setState(() { - selectedPlayers = [...value]; - }); - }, - ), - ), - CustomWidthButton( - text: widget.groupToEdit == null ? loc.create_group : loc.edit_group, - sizeRelativeToWidth: 0.95, - buttonType: ButtonType.primary, - onPressed: - (_groupNameController.text.isEmpty || - (selectedPlayers.length < 2)) - ? null - : () async { - late Group? updatedGroup; - late bool success; - if (widget.groupToEdit == null) { - success = await db.groupDao.addGroup( - group: Group( - name: _groupNameController.text.trim(), - members: selectedPlayers, - ), - ); - } else { - updatedGroup = Group( - id: widget.groupToEdit!.id, - name: _groupNameController.text.trim(), - members: selectedPlayers, - ); - //TODO: Implement group editing in database - /* - success = await db.groupDao.updateGroup( - group: updatedGroup, - ); - */ - success = true; - } - if (!context.mounted) return; - if (success) { - Navigator.pop(context, updatedGroup); - } else { - showSnackbar(message: widget.groupToEdit == null ? loc.error_creating_group : loc.error_editing_group); - } - }, - ), - const SizedBox(height: 20), - ], - ), - ), - ), - ); - } - /// Displays a snackbar with the given message and optional action. - /// - /// [message] The message to display in the snackbar. - void showSnackbar({ - required String message, - }) { - final messenger = _scaffoldMessengerKey.currentState; - if (messenger != null) { - messenger.hideCurrentSnackBar(); - messenger.showSnackBar( - SnackBar( - content: Text(message, style: const TextStyle(color: Colors.white)), - backgroundColor: CustomTheme.boxColor, - ), - ); - } - } -} diff --git a/lib/presentation/views/main_menu/group_view/group_detail_view.dart b/lib/presentation/views/main_menu/group_view/group_detail_view.dart index 7fe88b7..81a1c6e 100644 --- a/lib/presentation/views/main_menu/group_view/group_detail_view.dart +++ b/lib/presentation/views/main_menu/group_view/group_detail_view.dart @@ -6,7 +6,7 @@ import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/match.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/l10n/generated/app_localizations.dart'; -import 'package:game_tracker/presentation/views/main_menu/group_view/group_create_view.dart'; +import 'package:game_tracker/presentation/views/main_menu/group_view/create_group_view.dart'; import 'package:game_tracker/presentation/widgets/app_skeleton.dart'; import 'package:game_tracker/presentation/widgets/buttons/animated_dialog_button.dart'; import 'package:game_tracker/presentation/widgets/buttons/main_menu_button.dart'; @@ -188,7 +188,7 @@ class _GroupDetailViewState extends State { context, adaptivePageRoute( builder: (context) { - return GroupCreateView( + return CreateGroupView( groupToEdit: _group, ); }, diff --git a/lib/presentation/views/main_menu/group_view/groups_view.dart b/lib/presentation/views/main_menu/group_view/group_view.dart similarity index 98% rename from lib/presentation/views/main_menu/group_view/groups_view.dart rename to lib/presentation/views/main_menu/group_view/group_view.dart index 6462205..a995f12 100644 --- a/lib/presentation/views/main_menu/group_view/groups_view.dart +++ b/lib/presentation/views/main_menu/group_view/group_view.dart @@ -7,7 +7,7 @@ import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/l10n/generated/app_localizations.dart'; import 'package:game_tracker/presentation/views/main_menu/group_view/group_detail_view.dart'; -import 'package:game_tracker/presentation/views/main_menu/group_view/group_create_view.dart'; +import 'package:game_tracker/presentation/views/main_menu/group_view/create_group_view.dart'; import 'package:game_tracker/presentation/widgets/app_skeleton.dart'; import 'package:game_tracker/presentation/widgets/buttons/main_menu_button.dart'; import 'package:game_tracker/presentation/widgets/tiles/group_tile.dart'; @@ -105,7 +105,7 @@ class _GroupsViewState extends State { context, adaptivePageRoute( builder: (context) { - return const GroupCreateView(); + return const CreateGroupView(); }, ), );