Merge pull request #147 from SyncrowIOT/SP-1433-FE-Text-Alignment-Issue-in-UI-Component-in-adding-subspace-in-a-space

Sp 1433 fe text alignment issue in UI component in adding subspace in a space
This commit is contained in:
Faris Armoush
2025-04-21 09:48:38 +03:00
committed by GitHub
4 changed files with 181 additions and 198 deletions

View File

@ -592,8 +592,6 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
return CreateSubSpaceDialog(
spaceName: name,
dialogTitle: isEdit ? 'Edit Sub-space' : 'Create Sub-space',
spaceTags: spaceTags,
isEdit: isEdit,
products: products,
existingSubSpaces: existingSubSpaces,
onSave: (slectedSubspaces) {

View File

@ -4,169 +4,155 @@ 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';
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;
class CreateSubSpaceDialog extends StatefulWidget {
final String dialogTitle;
final List<SubspaceModel>? existingSubSpaces;
final String? spaceName;
final List<Tag>? spaceTags;
final List<ProductModel>? products;
final Function(List<SubspaceModel>?)? onSave;
final void Function(List<SubspaceModel>?)? onSave;
const CreateSubSpaceDialog(
{Key? key,
required this.isEdit,
const CreateSubSpaceDialog({
required this.dialogTitle,
this.existingSubSpaces,
required this.spaceName,
required this.spaceTags,
required this.products,
required this.onSave})
: super(key: key);
required this.onSave,
this.existingSubSpaces,
super.key,
});
@override
State<CreateSubSpaceDialog> createState() => _CreateSubSpaceDialogState();
}
class _CreateSubSpaceDialogState extends State<CreateSubSpaceDialog> {
late final TextEditingController _subspaceNameController;
@override
void initState() {
_subspaceNameController = TextEditingController();
super.initState();
}
@override
void dispose() {
_subspaceNameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
final textController = TextEditingController();
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: BlocProvider(
return BlocProvider(
create: (_) {
final bloc = SubSpaceBloc();
if (existingSubSpaces != null) {
for (var subSpace in existingSubSpaces!) {
if (widget.existingSubSpaces != null) {
for (final subSpace in widget.existingSubSpaces ?? []) {
bloc.add(AddSubSpace(subSpace));
}
}
return bloc;
},
child: Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: BlocBuilder<SubSpaceBloc, SubSpaceState>(
builder: (context, state) {
return Container(
width: context.screenWidth * 0.35,
color: ColorsManager.whiteColors,
child: SizedBox(
width: screenWidth * 0.35,
child: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
dialogTitle,
style: Theme.of(context)
.textTheme
.headlineLarge
?.copyWith(color: ColorsManager.blackColor),
widget.dialogTitle,
style: context.textTheme.headlineLarge?.copyWith(
color: ColorsManager.blackColor,
),
),
const SizedBox(height: 16),
Container(
width: screenWidth * 0.35,
width: context.screenWidth * 0.35,
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 16.0),
vertical: 10,
horizontal: 16,
),
decoration: BoxDecoration(
color: ColorsManager.boxColor,
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) {
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)
e.value.subspaceName.toLowerCase() == lowerName)
.map((e) => e.key)
.toList();
final isDuplicate =
duplicateIndices.length > 1 &&
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,
return SubspaceChip(
subSpace: SubspaceTemplateModel(
subspaceName: entry.value.subspaceName,
disabled: entry.value.disabled,
),
isDuplicate: isDuplicate,
onDeleted: () => context.read<SubSpaceBloc>().add(
RemoveSubSpace(subSpace),
),
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,
),
),
onDeleted: () => context
.read<SubSpaceBloc>()
.add(RemoveSubSpace(subSpace)),
);
},
),
SizedBox(
width: 200,
child: TextField(
controller: textController,
controller: _subspaceNameController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: state.subSpaces.isEmpty
? 'Please enter the name'
: null,
hintStyle: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(
color: ColorsManager
.lightGrayColor)),
hintStyle: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.lightGrayColor,
),
),
onSubmitted: (value) {
if (value.trim().isNotEmpty) {
final trimmedValue = value.trim();
if (trimmedValue.isNotEmpty) {
context.read<SubSpaceBloc>().add(
AddSubSpace(SubspaceModel(
subspaceName: value.trim(),
disabled: false)));
textController.clear();
AddSubSpace(
SubspaceModel(
subspaceName: trimmedValue,
disabled: false,
),
),
);
_subspaceNameController.clear();
}
},
style:
Theme.of(context).textTheme.bodyMedium),
style: context.textTheme.bodyMedium,
),
),
],
),
@ -174,13 +160,12 @@ class CreateSubSpaceDialog extends StatelessWidget {
if (state.errorMessage.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(state.errorMessage,
style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(
child: Text(
state.errorMessage,
style: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.warningRed,
)),
),
),
),
const SizedBox(height: 16),
Row(
@ -196,16 +181,14 @@ class CreateSubSpaceDialog extends StatelessWidget {
const SizedBox(width: 10),
Expanded(
child: DefaultButton(
onPressed: (state.errorMessage.isNotEmpty)
? null
: () async {
final subSpaces = context
.read<SubSpaceBloc>()
.state
.subSpaces;
onSave!(subSpaces);
onPressed: state.errorMessage.isEmpty
? () {
final subSpacesBloc = context.read<SubSpaceBloc>();
final subSpaces = subSpacesBloc.state.subSpaces;
widget.onSave?.call(subSpaces);
Navigator.of(context).pop();
},
}
: null,
backgroundColor: ColorsManager.secondaryColor,
borderRadius: 10,
foregroundColor: state.errorMessage.isNotEmpty
@ -218,8 +201,7 @@ class CreateSubSpaceDialog extends StatelessWidget {
),
],
),
),
));
);
},
),
),

View File

@ -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<SubSpaceModelBloc>().add(
RemoveSubSpaceModel(subSpace),
),
);
},
),

View File

@ -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<SubSpaceModelBloc>().add(
RemoveSubSpaceModel(subSpace),
),
onDeleted: onDeleted,
);
}
}