From 726c173a7659e3b12f58c4507c94106916f170d1 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Thu, 17 Apr 2025 09:33:10 +0300 Subject: [PATCH 1/8] SP-1433-FE-Text-Alignment-Issue-in-UI-Component-in-adding-subspace-in-a-space --- .../views/create_subspace_model_dialog.dart | 78 ++++++------------- .../create_subspace_model_chips_box.dart | 6 ++ .../widgets/subspace_chip.dart | 9 +-- 3 files changed, 33 insertions(+), 60 deletions(-) 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 0a2a01e5..fd7b890a 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 @@ -8,6 +8,8 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart'; import 'package:syncrow_web/pages/spaces_management/create_subspace/bloc/subspace_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/create_subspace/bloc/subspace_event.dart'; import 'package:syncrow_web/pages/spaces_management/create_subspace/bloc/subspace_state.dart'; +import 'package:syncrow_web/pages/spaces_management/create_subspace_model/widgets/subspace_chip.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart'; import 'package:syncrow_web/utils/color_manager.dart'; class CreateSubSpaceDialog extends StatelessWidget { @@ -20,15 +22,14 @@ class CreateSubSpaceDialog extends StatelessWidget { final Function(List?)? onSave; const CreateSubSpaceDialog( - {Key? key, + {super.key, required this.isEdit, required this.dialogTitle, this.existingSubSpaces, required this.spaceName, required this.spaceTags, required this.products, - required this.onSave}) - : super(key: key); + required this.onSave}); @override Widget build(BuildContext context) { @@ -78,8 +79,10 @@ class CreateSubSpaceDialog extends StatelessWidget { borderRadius: BorderRadius.circular(10), ), child: Wrap( - spacing: 8.0, - runSpacing: 8.0, + spacing: 8, + runSpacing: 8, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.center, children: [ ...state.subSpaces.asMap().entries.map( (entry) { @@ -97,44 +100,14 @@ class CreateSubSpaceDialog extends StatelessWidget { lowerName) .map((e) => e.key) .toList(); - final isDuplicate = - duplicateIndices.length > 1 && - duplicateIndices.indexOf(index) != 0; - - return Chip( - label: Text(subSpace.subspaceName, - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith( - color: - ColorsManager.spaceColor)), - backgroundColor: ColorsManager.whiteColors, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - side: BorderSide( - color: isDuplicate - ? ColorsManager.red - : ColorsManager.transparentColor, - width: 0, - ), - ), - deleteIcon: Container( - width: 24, - height: 24, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: ColorsManager.lightGrayColor, - width: 1.5, - ), - ), - child: const Icon( - Icons.close, - size: 16, - color: ColorsManager.lightGrayColor, - ), + 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)), @@ -154,19 +127,18 @@ class CreateSubSpaceDialog extends StatelessWidget { .textTheme .bodySmall ?.copyWith( - color: ColorsManager - .lightGrayColor)), + color: + ColorsManager.lightGrayColor)), onSubmitted: (value) { if (value.trim().isNotEmpty) { - context.read().add( - AddSubSpace(SubspaceModel( + context.read().add(AddSubSpace( + SubspaceModel( subspaceName: value.trim(), disabled: false))); textController.clear(); } }, - style: - Theme.of(context).textTheme.bodyMedium), + style: Theme.of(context).textTheme.bodyMedium), ), ], ), @@ -175,12 +147,10 @@ class CreateSubSpaceDialog extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 8.0), child: Text(state.errorMessage, - style: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith( - color: ColorsManager.warningRed, - )), + style: + Theme.of(context).textTheme.bodySmall?.copyWith( + color: ColorsManager.warningRed, + )), ), const SizedBox(height: 16), Row( diff --git a/lib/pages/spaces_management/create_subspace_model/widgets/create_subspace_model_chips_box.dart b/lib/pages/spaces_management/create_subspace_model/widgets/create_subspace_model_chips_box.dart index a18fc8d8..c6b302c0 100644 --- a/lib/pages/spaces_management/create_subspace_model/widgets/create_subspace_model_chips_box.dart +++ b/lib/pages/spaces_management/create_subspace_model/widgets/create_subspace_model_chips_box.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_bloc.dart'; +import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_event.dart'; import 'package:syncrow_web/pages/spaces_management/create_subspace_model/widgets/subspace_chip.dart'; import 'package:syncrow_web/pages/spaces_management/create_subspace_model/widgets/subspaces_textfield.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart'; @@ -51,6 +54,9 @@ class CreateSubspaceModelChipsBox extends StatelessWidget { return SubspaceChip( subSpace: subSpace, isDuplicate: isDuplicate, + onDeleted: () => context.read().add( + RemoveSubSpaceModel(subSpace), + ), ); }, ), diff --git a/lib/pages/spaces_management/create_subspace_model/widgets/subspace_chip.dart b/lib/pages/spaces_management/create_subspace_model/widgets/subspace_chip.dart index b54e0712..098b4804 100644 --- a/lib/pages/spaces_management/create_subspace_model/widgets/subspace_chip.dart +++ b/lib/pages/spaces_management/create_subspace_model/widgets/subspace_chip.dart @@ -1,7 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_bloc.dart'; -import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_event.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; @@ -11,10 +8,12 @@ class SubspaceChip extends StatelessWidget { required this.subSpace, required this.isDuplicate, super.key, + required this.onDeleted, }); final SubspaceTemplateModel subSpace; final bool isDuplicate; + final void Function() onDeleted; @override Widget build(BuildContext context) { @@ -50,9 +49,7 @@ class SubspaceChip extends StatelessWidget { ), ), ), - onDeleted: () => context.read().add( - RemoveSubSpaceModel(subSpace), - ), + onDeleted: onDeleted, ); } } From 62bf4f29445760002b708c64ef1785c4fffe23d5 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Thu, 17 Apr 2025 09:34:03 +0300 Subject: [PATCH 2/8] Refactor CreateSubSpaceDialog to use context extension for screen width calculations --- .../views/create_subspace_model_dialog.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 fd7b890a..11c747bc 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 @@ -11,6 +11,7 @@ import 'package:syncrow_web/pages/spaces_management/create_subspace/bloc/subspac import 'package:syncrow_web/pages/spaces_management/create_subspace_model/widgets/subspace_chip.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart'; import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; class CreateSubSpaceDialog extends StatelessWidget { final bool isEdit; @@ -19,7 +20,7 @@ class CreateSubSpaceDialog extends StatelessWidget { final String? spaceName; final List? spaceTags; final List? products; - final Function(List?)? onSave; + final void Function(List?)? onSave; const CreateSubSpaceDialog( {super.key, @@ -33,7 +34,6 @@ class CreateSubSpaceDialog extends StatelessWidget { @override Widget build(BuildContext context) { - final screenWidth = MediaQuery.of(context).size.width; final textController = TextEditingController(); return Dialog( @@ -55,7 +55,7 @@ class CreateSubSpaceDialog extends StatelessWidget { return Container( color: ColorsManager.whiteColors, child: SizedBox( - width: screenWidth * 0.35, + width: context.screenWidth * 0.35, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( @@ -71,7 +71,7 @@ class CreateSubSpaceDialog extends StatelessWidget { ), const SizedBox(height: 16), Container( - width: screenWidth * 0.35, + width: context.screenWidth * 0.35, padding: const EdgeInsets.symmetric( vertical: 10.0, horizontal: 16.0), decoration: BoxDecoration( From 18c886753dfac908b0696945f0300220953646ed Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Thu, 17 Apr 2025 09:35:33 +0300 Subject: [PATCH 3/8] added trailing commas wherever neccessary in `CreateSubSpaceDialog`. --- .../views/create_subspace_model_dialog.dart | 292 +++++++++--------- 1 file changed, 151 insertions(+), 141 deletions(-) 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 11c747bc..336cc354 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 @@ -22,15 +22,16 @@ class CreateSubSpaceDialog extends StatelessWidget { final List? products; final void Function(List?)? onSave; - const CreateSubSpaceDialog( - {super.key, - required this.isEdit, - required this.dialogTitle, - this.existingSubSpaces, - required this.spaceName, - required this.spaceTags, - required this.products, - required this.onSave}); + const CreateSubSpaceDialog({ + super.key, + required this.isEdit, + required this.dialogTitle, + this.existingSubSpaces, + required this.spaceName, + required this.spaceTags, + required this.products, + required this.onSave, + }); @override Widget build(BuildContext context) { @@ -44,7 +45,7 @@ class CreateSubSpaceDialog extends StatelessWidget { create: (_) { final bloc = SubSpaceBloc(); if (existingSubSpaces != null) { - for (var subSpace in existingSubSpaces!) { + for (final subSpace in existingSubSpaces ?? []) { bloc.add(AddSubSpace(subSpace)); } } @@ -53,143 +54,152 @@ class CreateSubSpaceDialog extends StatelessWidget { child: BlocBuilder( builder: (context, state) { return Container( - color: ColorsManager.whiteColors, - child: SizedBox( - width: context.screenWidth * 0.35, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - dialogTitle, - style: Theme.of(context) - .textTheme - .headlineLarge - ?.copyWith(color: ColorsManager.blackColor), - ), - const SizedBox(height: 16), - Container( - width: context.screenWidth * 0.35, - padding: const EdgeInsets.symmetric( - vertical: 10.0, horizontal: 16.0), - 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: textController, - decoration: InputDecoration( - border: InputBorder.none, - hintText: state.subSpaces.isEmpty - ? 'Please enter the name' - : null, - hintStyle: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith( - color: - ColorsManager.lightGrayColor)), - onSubmitted: (value) { - if (value.trim().isNotEmpty) { - context.read().add(AddSubSpace( - SubspaceModel( - subspaceName: value.trim(), - disabled: false))); - textController.clear(); - } - }, - style: Theme.of(context).textTheme.bodyMedium), - ), - ], - ), - ), - if (state.errorMessage.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text(state.errorMessage, - style: - Theme.of(context).textTheme.bodySmall?.copyWith( - color: ColorsManager.warningRed, - )), - ), - const SizedBox(height: 16), - Row( - children: [ - Expanded( - child: CancelButton( - label: 'Cancel', - onPressed: () async { - Navigator.of(context).pop(); - }, - ), + color: ColorsManager.whiteColors, + child: SizedBox( + width: context.screenWidth * 0.35, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + dialogTitle, + style: Theme.of(context).textTheme.headlineLarge?.copyWith( + color: ColorsManager.blackColor, ), - const SizedBox(width: 10), - Expanded( - child: DefaultButton( - onPressed: (state.errorMessage.isNotEmpty) - ? null - : () async { - final subSpaces = context - .read() - .state - .subSpaces; - onSave!(subSpaces); - Navigator.of(context).pop(); - }, - backgroundColor: ColorsManager.secondaryColor, - borderRadius: 10, - foregroundColor: state.errorMessage.isNotEmpty - ? ColorsManager.whiteColorsWithOpacity - : ColorsManager.whiteColors, - child: const Text('OK'), + ), + const SizedBox(height: 16), + Container( + width: context.screenWidth * 0.35, + padding: const EdgeInsets.symmetric( + vertical: 10.0, + horizontal: 16.0, + ), + 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: textController, + decoration: InputDecoration( + border: InputBorder.none, + hintText: state.subSpaces.isEmpty + ? 'Please enter the name' + : null, + hintStyle: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + color: ColorsManager.lightGrayColor, + ), + ), + onSubmitted: (value) { + if (value.trim().isNotEmpty) { + context.read().add( + AddSubSpace( + SubspaceModel( + subspaceName: value.trim(), + disabled: false, + ), + ), + ); + textController.clear(); + } + }, + style: Theme.of(context).textTheme.bodyMedium, ), ), ], ), - ], - ), + ), + if (state.errorMessage.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + state.errorMessage, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: ColorsManager.warningRed, + ), + ), + ), + 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.isNotEmpty) + ? null + : () async { + final subSpaces = context + .read() + .state + .subSpaces; + onSave!(subSpaces); + Navigator.of(context).pop(); + }, + backgroundColor: ColorsManager.secondaryColor, + borderRadius: 10, + foregroundColor: state.errorMessage.isNotEmpty + ? ColorsManager.whiteColorsWithOpacity + : ColorsManager.whiteColors, + child: const Text('OK'), + ), + ), + ], + ), + ], ), - )); + ), + ), + ); }, ), ), From ae95d06482ab2d117c4c4a0817f7491714c62521 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Thu, 17 Apr 2025 09:35:47 +0300 Subject: [PATCH 4/8] Fix constructor parameter order in CreateSubSpaceDialog --- .../create_subspace/views/create_subspace_model_dialog.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 336cc354..3f7cc598 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 @@ -23,14 +23,14 @@ class CreateSubSpaceDialog extends StatelessWidget { final void Function(List?)? onSave; const CreateSubSpaceDialog({ - super.key, required this.isEdit, required this.dialogTitle, - this.existingSubSpaces, required this.spaceName, required this.spaceTags, required this.products, required this.onSave, + this.existingSubSpaces, + super.key, }); @override From a6fc99443b07635eaa76f26ba165abe4346648b6 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Thu, 17 Apr 2025 09:38:54 +0300 Subject: [PATCH 5/8] Refactor CreateSubSpaceDialog layout for improved readability and maintainability --- .../views/create_subspace_model_dialog.dart | 253 +++++++++--------- 1 file changed, 121 insertions(+), 132 deletions(-) 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 3f7cc598..ef20fa56 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 @@ -54,150 +54,139 @@ class CreateSubSpaceDialog extends StatelessWidget { child: BlocBuilder( builder: (context, state) { return Container( + width: context.screenWidth * 0.35, color: ColorsManager.whiteColors, - child: SizedBox( - width: context.screenWidth * 0.35, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - dialogTitle, - style: Theme.of(context).textTheme.headlineLarge?.copyWith( - color: ColorsManager.blackColor, - ), - ), - const SizedBox(height: 16), - Container( - width: context.screenWidth * 0.35, - padding: const EdgeInsets.symmetric( - vertical: 10.0, - horizontal: 16.0, - ), - 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; + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + dialogTitle, + style: context.textTheme.headlineLarge?.copyWith( + color: ColorsManager.blackColor, + ), + ), + 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 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, + 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), ), - isDuplicate: isDuplicate, - onDeleted: () => context.read().add( - RemoveSubSpace(subSpace), - ), - ); - }, - ), - SizedBox( - width: 200, - child: TextField( - controller: textController, - decoration: InputDecoration( - border: InputBorder.none, - hintText: state.subSpaces.isEmpty - ? 'Please enter the name' - : null, - hintStyle: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith( - color: ColorsManager.lightGrayColor, - ), - ), - onSubmitted: (value) { - if (value.trim().isNotEmpty) { - context.read().add( - AddSubSpace( - SubspaceModel( - subspaceName: value.trim(), - disabled: false, - ), - ), - ); - textController.clear(); - } - }, - style: Theme.of(context).textTheme.bodyMedium, + ); + }, + ), + SizedBox( + width: 200, + child: TextField( + controller: textController, + decoration: InputDecoration( + border: InputBorder.none, + hintText: state.subSpaces.isEmpty + ? 'Please enter the name' + : null, + hintStyle: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.lightGrayColor, ), ), - ], + onSubmitted: (value) { + if (value.trim().isNotEmpty) { + context.read().add( + AddSubSpace( + SubspaceModel( + subspaceName: value.trim(), + disabled: false, + ), + ), + ); + textController.clear(); + } + }, + style: context.textTheme.bodyMedium, + ), + ), + ], + ), + ), + if (state.errorMessage.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + state.errorMessage, + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.warningRed, ), ), - if (state.errorMessage.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text( - state.errorMessage, - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: ColorsManager.warningRed, - ), - ), + ), + 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 + ? () { + final subSpacesBloc = context.read(); + final subSpaces = subSpacesBloc.state.subSpaces; + 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'), ), - 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.isNotEmpty) - ? null - : () async { - final subSpaces = context - .read() - .state - .subSpaces; - onSave!(subSpaces); - Navigator.of(context).pop(); - }, - backgroundColor: ColorsManager.secondaryColor, - borderRadius: 10, - foregroundColor: state.errorMessage.isNotEmpty - ? ColorsManager.whiteColorsWithOpacity - : ColorsManager.whiteColors, - child: const Text('OK'), - ), - ), - ], ), ], ), - ), + ], ), ); }, From 2a77483f46dcc1a2e2d7a57ca2c0a3af23e6488a Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Thu, 17 Apr 2025 09:45:14 +0300 Subject: [PATCH 6/8] Refactor `CreateSubSpaceDialog` to improve widget structure and readability --- .../views/create_subspace_model_dialog.dart | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) 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 ef20fa56..e8ef9993 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 @@ -37,20 +37,20 @@ class CreateSubSpaceDialog extends StatelessWidget { Widget build(BuildContext context) { final textController = TextEditingController(); - return Dialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - child: BlocProvider( - create: (_) { - final bloc = SubSpaceBloc(); - if (existingSubSpaces != null) { - for (final subSpace in existingSubSpaces ?? []) { - bloc.add(AddSubSpace(subSpace)); - } + return BlocProvider( + create: (_) { + final bloc = SubSpaceBloc(); + if (existingSubSpaces != null) { + for (final subSpace in existingSubSpaces ?? []) { + bloc.add(AddSubSpace(subSpace)); } - return bloc; - }, + } + return bloc; + }, + child: Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), child: BlocBuilder( builder: (context, state) { return Container( From 024fbcdb837fd4db97a29038d7ce20e617235f2c Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Thu, 17 Apr 2025 11:25:39 +0300 Subject: [PATCH 7/8] Refactor `CreateSubSpaceDialog` to convert to StatefulWidget and manage text controller lifecycle --- .../views/create_subspace_model_dialog.dart | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) 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 e8ef9993..09951bd8 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 @@ -13,7 +13,7 @@ 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'; -class CreateSubSpaceDialog extends StatelessWidget { +class CreateSubSpaceDialog extends StatefulWidget { final bool isEdit; final String dialogTitle; final List? existingSubSpaces; @@ -34,14 +34,31 @@ class CreateSubSpaceDialog extends StatelessWidget { }); @override - Widget build(BuildContext context) { - final textController = TextEditingController(); + State createState() => _CreateSubSpaceDialogState(); +} +class _CreateSubSpaceDialogState extends State { + late final TextEditingController _subspaceNameController; + + @override + void initState() { + _subspaceNameController = TextEditingController(); + super.initState(); + } + + @override + void dispose() { + _subspaceNameController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { return BlocProvider( create: (_) { final bloc = SubSpaceBloc(); - if (existingSubSpaces != null) { - for (final subSpace in existingSubSpaces ?? []) { + if (widget.existingSubSpaces != null) { + for (final subSpace in widget.existingSubSpaces ?? []) { bloc.add(AddSubSpace(subSpace)); } } @@ -62,7 +79,7 @@ class CreateSubSpaceDialog extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Text( - dialogTitle, + widget.dialogTitle, style: context.textTheme.headlineLarge?.copyWith( color: ColorsManager.blackColor, ), @@ -115,7 +132,7 @@ class CreateSubSpaceDialog extends StatelessWidget { SizedBox( width: 200, child: TextField( - controller: textController, + controller: _subspaceNameController, decoration: InputDecoration( border: InputBorder.none, hintText: state.subSpaces.isEmpty @@ -126,16 +143,17 @@ class CreateSubSpaceDialog extends StatelessWidget { ), ), onSubmitted: (value) { - if (value.trim().isNotEmpty) { + final trimmedValue = value.trim(); + if (trimmedValue.isNotEmpty) { context.read().add( AddSubSpace( SubspaceModel( - subspaceName: value.trim(), + subspaceName: trimmedValue, disabled: false, ), ), ); - textController.clear(); + _subspaceNameController.clear(); } }, style: context.textTheme.bodyMedium, @@ -172,7 +190,7 @@ class CreateSubSpaceDialog extends StatelessWidget { ? () { final subSpacesBloc = context.read(); final subSpaces = subSpacesBloc.state.subSpaces; - onSave?.call(subSpaces); + widget.onSave?.call(subSpaces); Navigator.of(context).pop(); } : null, From ce253b2034e41fb43e1a105100708208ac4c54eb Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Thu, 17 Apr 2025 11:27:37 +0300 Subject: [PATCH 8/8] Remove unused parameters from `CreateSubSpaceDialog` constructor --- .../all_spaces/widgets/dialogs/create_space_dialog.dart | 2 -- .../create_subspace/views/create_subspace_model_dialog.dart | 5 ----- 2 files changed, 7 deletions(-) diff --git a/lib/pages/spaces_management/all_spaces/widgets/dialogs/create_space_dialog.dart b/lib/pages/spaces_management/all_spaces/widgets/dialogs/create_space_dialog.dart index 56e1212e..a7f6e2ea 100644 --- a/lib/pages/spaces_management/all_spaces/widgets/dialogs/create_space_dialog.dart +++ b/lib/pages/spaces_management/all_spaces/widgets/dialogs/create_space_dialog.dart @@ -592,8 +592,6 @@ class CreateSpaceDialogState extends State { return CreateSubSpaceDialog( spaceName: name, dialogTitle: isEdit ? 'Edit Sub-space' : 'Create Sub-space', - spaceTags: spaceTags, - isEdit: isEdit, products: products, existingSubSpaces: existingSubSpaces, onSave: (slectedSubspaces) { 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 09951bd8..948028ed 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 @@ -4,7 +4,6 @@ import 'package:syncrow_web/pages/common/buttons/cancel_button.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/subspace_model.dart'; -import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart'; import 'package:syncrow_web/pages/spaces_management/create_subspace/bloc/subspace_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/create_subspace/bloc/subspace_event.dart'; import 'package:syncrow_web/pages/spaces_management/create_subspace/bloc/subspace_state.dart'; @@ -14,19 +13,15 @@ import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; class CreateSubSpaceDialog extends StatefulWidget { - final bool isEdit; final String dialogTitle; final List? existingSubSpaces; final String? spaceName; - final List? spaceTags; final List? products; final void Function(List?)? onSave; const CreateSubSpaceDialog({ - required this.isEdit, required this.dialogTitle, required this.spaceName, - required this.spaceTags, required this.products, required this.onSave, this.existingSubSpaces,