diff --git a/lib/pages/spaces_management/create_subspace/views/create_subspace_model_dialog.dart b/lib/pages/spaces_management/create_subspace/views/create_subspace_model_dialog.dart index 483382af..501ad5a1 100644 --- a/lib/pages/spaces_management/create_subspace/views/create_subspace_model_dialog.dart +++ b/lib/pages/spaces_management/create_subspace/views/create_subspace_model_dialog.dart @@ -12,6 +12,9 @@ import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_ import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; +import 'widgets/ok_cancel_sub_space_widget.dart'; +import 'widgets/textfield_sub_space_dialog_widget.dart'; + class CreateSubSpaceDialog extends StatefulWidget { final String dialogTitle; final List? existingSubSpaces; @@ -33,14 +36,7 @@ class CreateSubSpaceDialog extends StatefulWidget { } class _CreateSubSpaceDialogState extends State { - late final TextEditingController _subspaceNameController; - - @override - void initState() { - _subspaceNameController = TextEditingController(); - super.initState(); - } - + final TextEditingController _subspaceNameController = TextEditingController(); @override void dispose() { _subspaceNameController.dispose(); @@ -96,84 +92,9 @@ class _CreateSubSpaceDialogState extends State { ], ), const SizedBox(height: 16), - Container( - width: context.screenWidth * 0.35, - padding: const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ), - decoration: BoxDecoration( - color: ColorsManager.boxColor, - borderRadius: BorderRadius.circular(10), - ), - child: Wrap( - spacing: 8, - runSpacing: 8, - alignment: WrapAlignment.start, - crossAxisAlignment: WrapCrossAlignment.center, - children: [ - ...state.subSpaces.asMap().entries.map( - (entry) { - final index = entry.key; - final subSpace = entry.value; - - final lowerName = - subSpace.subspaceName.toLowerCase(); - - final duplicateIndices = state.subSpaces - .asMap() - .entries - .where((e) => - e.value.subspaceName.toLowerCase() == - lowerName) - .map((e) => e.key) - .toList(); - final isDuplicate = duplicateIndices.length > 1 && - duplicateIndices.indexOf(index) != 0; - return SubspaceChip( - subSpace: SubspaceTemplateModel( - subspaceName: entry.value.subspaceName, - disabled: entry.value.disabled, - ), - isDuplicate: isDuplicate, - onDeleted: () => context.read().add( - RemoveSubSpace(subSpace), - ), - ); - }, - ), - SizedBox( - width: 200, - child: TextField( - controller: _subspaceNameController, - decoration: InputDecoration( - border: InputBorder.none, - hintText: state.subSpaces.isEmpty - ? 'Please enter the name' - : null, - hintStyle: context.textTheme.bodySmall?.copyWith( - color: ColorsManager.lightGrayColor, - ), - ), - onSubmitted: (value) { - final trimmedValue = value.trim(); - if (trimmedValue.isNotEmpty) { - context.read().add( - AddSubSpace( - SubspaceModel( - subspaceName: trimmedValue, - disabled: false, - ), - ), - ); - _subspaceNameController.clear(); - } - }, - style: context.textTheme.bodyMedium, - ), - ), - ], - ), + TextFieldSubSpaceDialogWidget( + subspaceNameController: _subspaceNameController, + subSpaces: state.subSpaces, ), if (state.errorMessage.isNotEmpty) Padding( @@ -186,58 +107,10 @@ class _CreateSubSpaceDialogState extends State { ), ), const SizedBox(height: 16), - Row( - children: [ - Expanded( - child: CancelButton( - label: 'Cancel', - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - ), - const SizedBox(width: 10), - Expanded( - child: DefaultButton( - onPressed: state.errorMessage.isEmpty - ? () async { - final trimmedValue = - _subspaceNameController.text.trim(); - - final subSpacesBloc = - context.read(); - if (trimmedValue.isNotEmpty) { - subSpacesBloc.add( - AddSubSpace( - SubspaceModel( - subspaceName: trimmedValue, - disabled: false, - ), - ), - ); - _subspaceNameController.clear(); - } - - await Future.delayed( - const Duration(milliseconds: 10)); - final subSpaces = - subSpacesBloc.state.subSpaces; - // if (subSpaces.isNotEmpty) { - widget.onSave?.call(subSpaces); - // } - - Navigator.of(context).pop(); - } - : null, - backgroundColor: ColorsManager.secondaryColor, - borderRadius: 10, - foregroundColor: state.errorMessage.isNotEmpty - ? ColorsManager.whiteColorsWithOpacity - : ColorsManager.whiteColors, - child: const Text('OK'), - ), - ), - ], + OkCancelSubSpaceWidget( + subspaceNameController: _subspaceNameController, + errorMessage: state.errorMessage, + onSave: widget.onSave, ), ], ), diff --git a/lib/pages/spaces_management/create_subspace/views/widgets/ok_cancel_sub_space_widget.dart b/lib/pages/spaces_management/create_subspace/views/widgets/ok_cancel_sub_space_widget.dart new file mode 100644 index 00000000..3c3db8f0 --- /dev/null +++ b/lib/pages/spaces_management/create_subspace/views/widgets/ok_cancel_sub_space_widget.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/spaces_management/all_spaces/model/subspace_model.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/pages/common/buttons/cancel_button.dart'; +import 'package:syncrow_web/pages/common/buttons/default_button.dart'; + +import '../../bloc/subspace_bloc.dart'; +import '../../bloc/subspace_event.dart'; + +class OkCancelSubSpaceWidget extends StatelessWidget { + const OkCancelSubSpaceWidget({ + super.key, + required this.subspaceNameController, + required this.onSave, + required this.errorMessage, + }); + + final TextEditingController subspaceNameController; + final void Function(List?)? onSave; + final String errorMessage; + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: CancelButton( + label: 'Cancel', + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + ), + const SizedBox(width: 10), + Expanded( + child: DefaultButton( + onPressed: errorMessage.isEmpty + ? () async { + final trimmedValue = subspaceNameController.text.trim(); + + final subSpacesBloc = context.read(); + if (trimmedValue.isNotEmpty) { + subSpacesBloc.add( + AddSubSpace( + SubspaceModel( + subspaceName: trimmedValue, + disabled: false, + ), + ), + ); + subspaceNameController.clear(); + } + + await Future.delayed(const Duration(milliseconds: 10)); + final subSpaces = subSpacesBloc.state.subSpaces; + onSave?.call(subSpaces); + + Navigator.of(context).pop(); + } + : null, + backgroundColor: ColorsManager.secondaryColor, + borderRadius: 10, + foregroundColor: errorMessage.isNotEmpty + ? ColorsManager.whiteColorsWithOpacity + : ColorsManager.whiteColors, + child: const Text('OK'), + ), + ), + ], + ); + } +} diff --git a/lib/pages/spaces_management/create_subspace/views/widgets/textfield_sub_space_dialog_widget.dart b/lib/pages/spaces_management/create_subspace/views/widgets/textfield_sub_space_dialog_widget.dart new file mode 100644 index 00000000..f655e178 --- /dev/null +++ b/lib/pages/spaces_management/create_subspace/views/widgets/textfield_sub_space_dialog_widget.dart @@ -0,0 +1,98 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; + +import '../../../../../utils/color_manager.dart'; +import '../../../all_spaces/model/subspace_model.dart'; +import '../../../create_subspace_model/widgets/subspace_chip.dart'; +import '../../../space_model/models/subspace_template_model.dart'; +import '../../bloc/subspace_bloc.dart'; +import '../../bloc/subspace_event.dart'; + +class TextFieldSubSpaceDialogWidget extends StatelessWidget { + const TextFieldSubSpaceDialogWidget({ + super.key, + required TextEditingController subspaceNameController, + required this.subSpaces, + }) : _subspaceNameController = subspaceNameController; + + final TextEditingController _subspaceNameController; + final List subSpaces; + @override + Widget build(BuildContext context) { + return Container( + width: context.screenWidth * 0.35, + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ), + decoration: BoxDecoration( + color: ColorsManager.boxColor, + borderRadius: BorderRadius.circular(10), + ), + child: Wrap( + spacing: 8, + runSpacing: 8, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + ...subSpaces.asMap().entries.map( + (entry) { + final index = entry.key; + final subSpace = entry.value; + + final lowerName = subSpace.subspaceName.toLowerCase(); + + final duplicateIndices = subSpaces + .asMap() + .entries + .where((e) => e.value.subspaceName.toLowerCase() == lowerName) + .map((e) => e.key) + .toList(); + final isDuplicate = duplicateIndices.length > 1 && + duplicateIndices.indexOf(index) != 0; + return SubspaceChip( + subSpace: SubspaceTemplateModel( + subspaceName: entry.value.subspaceName, + disabled: entry.value.disabled, + ), + isDuplicate: isDuplicate, + onDeleted: () => context.read().add( + RemoveSubSpace(subSpace), + ), + ); + }, + ), + SizedBox( + width: 200, + child: TextField( + controller: _subspaceNameController, + decoration: InputDecoration( + border: InputBorder.none, + hintText: subSpaces.isEmpty ? 'Please enter the name' : null, + hintStyle: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.lightGrayColor, + ), + ), + onSubmitted: (value) { + final trimmedValue = value.trim(); + if (trimmedValue.isNotEmpty) { + context.read().add( + AddSubSpace( + SubspaceModel( + subspaceName: trimmedValue, + disabled: false, + ), + ), + ); + _subspaceNameController.clear(); + } + }, + style: context.textTheme.bodyMedium, + ), + ), + ], + ), + ); + } +}