From d47dc349bcd8cfafd7e3b6735c472cb071a42c8d Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Thu, 3 Jul 2025 12:04:03 +0300 Subject: [PATCH] Enhance SubspaceNameDisplayWidget to handle duplicate names during editing. Introduced logic to check for existing subspace names and provide user feedback. Refactored state management for editing and submission processes, improving overall user experience and code clarity. --- .../widgets/subspace_name_display_widget.dart | 108 +++++++++++++----- 1 file changed, 80 insertions(+), 28 deletions(-) diff --git a/lib/pages/space_management_v2/modules/space_details/presentation/widgets/subspace_name_display_widget.dart b/lib/pages/space_management_v2/modules/space_details/presentation/widgets/subspace_name_display_widget.dart index 9169efda..bbc9549d 100644 --- a/lib/pages/space_management_v2/modules/space_details/presentation/widgets/subspace_name_display_widget.dart +++ b/lib/pages/space_management_v2/modules/space_details/presentation/widgets/subspace_name_display_widget.dart @@ -18,7 +18,9 @@ class SubspaceNameDisplayWidget extends StatefulWidget { class _SubspaceNameDisplayWidgetState extends State { late final TextEditingController _controller; late final FocusNode _focusNode; - bool isEditing = false; + bool _isEditing = false; + bool _hasDuplicateName = false; + @override void initState() { _controller = TextEditingController(text: widget.subSpace.name); @@ -33,6 +35,41 @@ class _SubspaceNameDisplayWidgetState extends State { super.dispose(); } + bool _checkForDuplicateName(String name) { + final bloc = context.read(); + return bloc.state.subspaces + .where((s) => s.uuid != widget.subSpace.uuid) + .any((s) => s.name.toLowerCase() == name.toLowerCase()); + } + + void _handleNameChange(String value) { + setState(() { + _hasDuplicateName = _checkForDuplicateName(value); + }); + } + + void _tryToFinishEditing() { + if (!_hasDuplicateName) { + _onFinishEditing(); + } + } + + void _tryToSubmit(String value) { + if (_hasDuplicateName) return; + + final bloc = context.read(); + bloc.add( + UpdateSpaceDetailsSubspaces( + bloc.state.subspaces + .map( + (e) => e.uuid == widget.subSpace.uuid ? e.copyWith(name: value) : e, + ) + .toList(), + ), + ); + _onFinishEditing(); + } + @override Widget build(BuildContext context) { final textStyle = context.textTheme.bodySmall?.copyWith( @@ -40,7 +77,7 @@ class _SubspaceNameDisplayWidgetState extends State { ); return InkWell( onTap: () { - setState(() => isEditing = true); + setState(() => _isEditing = true); _focusNode.requestFocus(); }, child: Chip( @@ -49,36 +86,48 @@ class _SubspaceNameDisplayWidgetState extends State { borderRadius: BorderRadius.circular(10), ), label: Visibility( - visible: isEditing, + visible: _isEditing, replacement: Text( widget.subSpace.name, style: textStyle, ), - child: SizedBox( - width: context.screenWidth * 0.065, - height: context.screenHeight * 0.025, - child: TextField( - focusNode: _focusNode, - controller: _controller, - style: textStyle, - decoration: const InputDecoration.collapsed(hintText: ''), - onTapOutside: (_) => _onFinishEditing(), - onSubmitted: (value) { - final bloc = context.read(); - bloc.add( - UpdateSpaceDetailsSubspaces( - bloc.state.subspaces - .map( - (e) => e.uuid == widget.subSpace.uuid - ? e.copyWith(name: value) - : e, - ) - .toList(), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: context.screenWidth * 0.065, + height: context.screenHeight * 0.025, + child: TextField( + focusNode: _focusNode, + controller: _controller, + style: textStyle?.copyWith( + color: _hasDuplicateName ? Colors.red : null, ), - ); - _onFinishEditing(); - }, - ), + decoration: const InputDecoration.collapsed( + hintText: '', + ), + onChanged: _handleNameChange, + onTapOutside: (_) => _tryToFinishEditing(), + onSubmitted: _tryToSubmit, + ), + ), + if (_hasDuplicateName) + AnimatedSwitcher( + duration: const Duration(milliseconds: 250), + child: Visibility( + key: ValueKey(_hasDuplicateName), + visible: _hasDuplicateName, + child: Text( + 'Name already exists', + style: textStyle?.copyWith( + color: Colors.red, + fontSize: 8, + ), + ), + ), + ), + ], ), ), ), @@ -86,7 +135,10 @@ class _SubspaceNameDisplayWidgetState extends State { } void _onFinishEditing() { - setState(() => isEditing = false); + setState(() { + _isEditing = false; + _hasDuplicateName = false; + }); _focusNode.unfocus(); } }