Merge pull request #73 from SyncrowIOT/bugfix/edit-space

Bugfix/edit space
This commit is contained in:
hannathkadher
2025-01-29 12:46:19 +04:00
committed by GitHub
20 changed files with 545 additions and 310 deletions

View File

@ -12,7 +12,6 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_mod
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
import 'package:syncrow_web/pages/spaces_management/assign_tag/views/assign_tag_dialog.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag/views/assign_tag_dialog.dart';
import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart'; import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart';
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/action_button_widget.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class AddDeviceTypeWidget extends StatelessWidget { class AddDeviceTypeWidget extends StatelessWidget {
@ -23,10 +22,12 @@ class AddDeviceTypeWidget extends StatelessWidget {
final List<Tag>? spaceTags; final List<Tag>? spaceTags;
final List<String>? allTags; final List<String>? allTags;
final String spaceName; final String spaceName;
final bool isCreate;
final Function(List<Tag>, List<SubspaceModel>?)? onSave; final Function(List<Tag>, List<SubspaceModel>?)? onSave;
const AddDeviceTypeWidget( const AddDeviceTypeWidget(
{super.key, {super.key,
required this.isCreate,
this.products, this.products,
this.initialSelectedProducts, this.initialSelectedProducts,
this.onProductsSelected, this.onProductsSelected,
@ -74,7 +75,9 @@ class AddDeviceTypeWidget extends StatelessWidget {
padding: padding:
const EdgeInsets.symmetric(horizontal: 20.0), const EdgeInsets.symmetric(horizontal: 20.0),
child: ScrollableGridViewWidget( child: ScrollableGridViewWidget(
initialProductCounts: state.selectedProducts,
products: products, products: products,
isCreate: isCreate,
crossAxisCount: crossAxisCount), crossAxisCount: crossAxisCount),
), ),
), ),
@ -124,17 +127,14 @@ class AddDeviceTypeWidget extends StatelessWidget {
barrierDismissible: false, barrierDismissible: false,
context: context, context: context,
builder: (context) => AssignTagDialog( builder: (context) => AssignTagDialog(
products: products, products: products,
subspaces: subspaces, subspaces: subspaces,
addedProducts: state.selectedProducts, addedProducts: state.selectedProducts,
allTags: allTags, allTags: allTags,
spaceName: spaceName, spaceName: spaceName,
initialTags: initialTags, initialTags: initialTags,
title: dialogTitle, title: dialogTitle,
onSave: (tags, subspaces) { onSave: onSave),
onSave!(tags, subspaces);
},
),
); );
} }
}, },
@ -148,29 +148,4 @@ class AddDeviceTypeWidget extends StatelessWidget {
), ),
)); ));
} }
List<Tag> generateInitialTags({
List<Tag>? spaceTags,
List<SubspaceModel>? subspaces,
}) {
final List<Tag> initialTags = [];
if (spaceTags != null) {
initialTags.addAll(spaceTags);
}
if (subspaces != null) {
for (var subspace in subspaces) {
if (subspace.tags != null) {
initialTags.addAll(
subspace.tags!.map(
(tag) => tag.copyWith(location: subspace.subspaceName),
),
);
}
}
}
return initialTags;
}
} }

View File

@ -13,12 +13,13 @@ import 'package:syncrow_web/utils/constants/assets.dart';
class DeviceTypeTileWidget extends StatelessWidget { class DeviceTypeTileWidget extends StatelessWidget {
final ProductModel product; final ProductModel product;
final List<SelectedProduct> productCounts; final List<SelectedProduct> productCounts;
final bool isCreate;
const DeviceTypeTileWidget({ const DeviceTypeTileWidget(
super.key, {super.key,
required this.product, required this.product,
required this.productCounts, required this.productCounts,
}); required this.isCreate});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -48,7 +49,7 @@ class DeviceTypeTileWidget extends StatelessWidget {
DeviceNameWidget(name: product.name), DeviceNameWidget(name: product.name),
const SizedBox(height: 4), const SizedBox(height: 4),
CounterWidget( CounterWidget(
isCreate: false, isCreate: isCreate,
initialCount: selectedProduct.count, initialCount: selectedProduct.count,
onCountChanged: (newCount) { onCountChanged: (newCount) {
context.read<AddDeviceTypeBloc>().add( context.read<AddDeviceTypeBloc>().add(

View File

@ -10,13 +10,14 @@ class ScrollableGridViewWidget extends StatelessWidget {
final List<ProductModel>? products; final List<ProductModel>? products;
final int crossAxisCount; final int crossAxisCount;
final List<SelectedProduct>? initialProductCounts; final List<SelectedProduct>? initialProductCounts;
final bool isCreate;
const ScrollableGridViewWidget({ const ScrollableGridViewWidget(
super.key, {super.key,
required this.products, required this.products,
required this.crossAxisCount, required this.crossAxisCount,
this.initialProductCounts, this.initialProductCounts,
}); required this.isCreate});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -46,6 +47,7 @@ class ScrollableGridViewWidget extends StatelessWidget {
return DeviceTypeTileWidget( return DeviceTypeTileWidget(
product: product, product: product,
isCreate: isCreate,
productCounts: initialProductCount != null productCounts: initialProductCount != null
? [...productCounts, initialProductCount] ? [...productCounts, initialProductCount]
: productCounts, : productCounts,

View File

@ -5,12 +5,15 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_mod
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_state.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_state.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/all_spaces/model/tag.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_body_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_body_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart';
import 'package:syncrow_web/services/product_api.dart'; import 'package:syncrow_web/services/product_api.dart';
import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/services/space_mana_api.dart';
import 'package:syncrow_web/services/space_model_mang_api.dart'; import 'package:syncrow_web/services/space_model_mang_api.dart';
import 'package:syncrow_web/utils/constants/action_enum.dart';
class SpaceManagementBloc class SpaceManagementBloc
extends Bloc<SpaceManagementEvent, SpaceManagementState> { extends Bloc<SpaceManagementEvent, SpaceManagementState> {
@ -341,7 +344,7 @@ class SpaceManagementBloc
products: _cachedProducts ?? [], products: _cachedProducts ?? [],
selectedCommunity: selectedCommunity, selectedCommunity: selectedCommunity,
selectedSpace: selectedSpace, selectedSpace: selectedSpace,
spaceModels: spaceModels ?? [])); spaceModels: spaceModels));
} }
} catch (e) { } catch (e) {
emit(SpaceManagementError('Error updating state: $e')); emit(SpaceManagementError('Error updating state: $e'));
@ -428,6 +431,76 @@ class SpaceManagementBloc
for (var space in orderedSpaces) { for (var space in orderedSpaces) {
try { try {
if (space.uuid != null && space.uuid!.isNotEmpty) { if (space.uuid != null && space.uuid!.isNotEmpty) {
List<TagModelUpdate> tagUpdates = [];
final prevSpace = await _api.getSpace(communityUuid, space.uuid!);
final List<UpdateSubspaceTemplateModel> subspaceUpdates = [];
final List<SubspaceModel>? prevSubspaces = prevSpace?.subspaces;
final List<SubspaceModel>? newSubspaces = space.subspaces;
tagUpdates = processTagUpdates(prevSpace?.tags, space.tags);
if (prevSubspaces != null || newSubspaces != null) {
if (prevSubspaces != null && newSubspaces != null) {
for (var prevSubspace in prevSubspaces) {
final existsInNew = newSubspaces
.any((subspace) => subspace.uuid == prevSubspace.uuid);
if (!existsInNew) {
subspaceUpdates.add(UpdateSubspaceTemplateModel(
action: Action.delete, uuid: prevSubspace.uuid));
}
}
} else if (prevSubspaces != null && newSubspaces == null) {
for (var prevSubspace in prevSubspaces) {
subspaceUpdates.add(UpdateSubspaceTemplateModel(
action: Action.delete, uuid: prevSubspace.uuid));
}
}
if (newSubspaces != null) {
for (var newSubspace in newSubspaces) {
// Tag without UUID
if ((newSubspace.uuid == null || newSubspace.uuid!.isEmpty)) {
final List<TagModelUpdate> tagUpdates = [];
if (newSubspace.tags != null) {
for (var tag in newSubspace.tags!) {
tagUpdates.add(TagModelUpdate(
action: Action.add,
uuid: tag.uuid == '' ? null : tag.uuid,
tag: tag.tag,
productUuid: tag.product?.uuid));
}
}
subspaceUpdates.add(UpdateSubspaceTemplateModel(
action: Action.add,
subspaceName: newSubspace.subspaceName,
tags: tagUpdates));
}
}
}
if (prevSubspaces != null && newSubspaces != null) {
final newSubspaceMap = {
for (var subspace in newSubspaces) subspace.uuid: subspace
};
for (var prevSubspace in prevSubspaces) {
final newSubspace = newSubspaceMap[prevSubspace.uuid];
if (newSubspace != null) {
final List<TagModelUpdate> tagSubspaceUpdates =
processTagUpdates(prevSubspace.tags, newSubspace.tags);
subspaceUpdates.add(UpdateSubspaceTemplateModel(
action: Action.update,
uuid: newSubspace.uuid,
subspaceName: newSubspace.subspaceName,
tags: tagSubspaceUpdates));
}
}
}
}
final response = await _api.updateSpace( final response = await _api.updateSpace(
communityId: communityUuid, communityId: communityUuid,
spaceId: space.uuid!, spaceId: space.uuid!,
@ -436,6 +509,8 @@ class SpaceManagementBloc
isPrivate: space.isPrivate, isPrivate: space.isPrivate,
position: space.position, position: space.position,
icon: space.icon, icon: space.icon,
subspaces: subspaceUpdates,
tags: tagUpdates,
direction: space.incomingConnection?.direction, direction: space.incomingConnection?.direction,
); );
} else { } else {
@ -535,4 +610,79 @@ class SpaceManagementBloc
emit(SpaceManagementError('Error loading communities and spaces: $e')); emit(SpaceManagementError('Error loading communities and spaces: $e'));
} }
} }
List<TagModelUpdate> processTagUpdates(
List<Tag>? prevTags,
List<Tag>? newTags,
) {
final List<TagModelUpdate> tagUpdates = [];
final processedTags = <String?>{};
if (prevTags == null && newTags != null) {
for (var newTag in newTags) {
tagUpdates.add(TagModelUpdate(
action: Action.add,
tag: newTag.tag,
uuid: newTag.uuid,
productUuid: newTag.product?.uuid,
));
}
return tagUpdates;
}
if (newTags != null || prevTags != null) {
// Case 1: Tags deleted
if (prevTags != null && newTags != null) {
for (var prevTag in prevTags) {
final existsInNew =
newTags.any((newTag) => newTag.uuid == prevTag.uuid);
if (!existsInNew) {
tagUpdates
.add(TagModelUpdate(action: Action.delete, uuid: prevTag.uuid));
}
}
} else if (prevTags != null && newTags == null) {
for (var prevTag in prevTags) {
tagUpdates
.add(TagModelUpdate(action: Action.delete, uuid: prevTag.uuid));
}
}
// Case 2: Tags added
if (newTags != null) {
final prevTagUuids = prevTags?.map((t) => t.uuid).toSet() ?? {};
for (var newTag in newTags) {
// Tag without UUID
if ((newTag.uuid == null || !prevTagUuids.contains(newTag.uuid)) &&
!processedTags.contains(newTag.tag)) {
tagUpdates.add(TagModelUpdate(
action: Action.add,
tag: newTag.tag,
uuid: newTag.uuid == '' ? null : newTag.uuid,
productUuid: newTag.product?.uuid));
processedTags.add(newTag.tag);
}
}
}
// Case 3: Tags updated
if (prevTags != null && newTags != null) {
final newTagMap = {for (var tag in newTags) tag.uuid: tag};
for (var prevTag in prevTags) {
final newTag = newTagMap[prevTag.uuid];
if (newTag != null) {
tagUpdates.add(TagModelUpdate(
action: Action.update,
uuid: newTag.uuid,
tag: newTag.tag,
));
} else {}
}
}
}
return tagUpdates;
}
} }

View File

@ -66,7 +66,6 @@ class SpaceModel {
final instance = SpaceModel( final instance = SpaceModel(
internalId: internalId, internalId: internalId,
uuid: json['uuid'] ?? '', uuid: json['uuid'] ?? '',
spaceTuyaUuid: json['spaceTuyaUuid'],
name: json['spaceName'], name: json['spaceName'],
isPrivate: json['isPrivate'] ?? false, isPrivate: json['isPrivate'] ?? false,
invitationCode: json['invitationCode'], invitationCode: json['invitationCode'],

View File

@ -195,6 +195,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
screenSize, screenSize,
position: position:
spaces[index].position + newPosition, spaces[index].position + newPosition,
parentIndex: index, parentIndex: index,
direction: direction, direction: direction,
); );
@ -294,6 +295,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
return CreateSpaceDialog( return CreateSpaceDialog(
products: widget.products, products: widget.products,
spaceModels: widget.spaceModels, spaceModels: widget.spaceModels,
allTags: _getAllTagValues(spaces),
parentSpace: parentIndex != null ? spaces[parentIndex] : null, parentSpace: parentIndex != null ? spaces[parentIndex] : null,
onCreateSpace: (String name, onCreateSpace: (String name,
String icon, String icon,
@ -350,7 +352,10 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
name: widget.selectedSpace!.name, name: widget.selectedSpace!.name,
icon: widget.selectedSpace!.icon, icon: widget.selectedSpace!.icon,
editSpace: widget.selectedSpace, editSpace: widget.selectedSpace,
tags: widget.selectedSpace?.tags,
subspaces: widget.selectedSpace?.subspaces,
isEdit: true, isEdit: true,
allTags: _getAllTagValues(spaces),
onCreateSpace: (String name, onCreateSpace: (String name,
String icon, String icon,
List<SelectedProduct> selectedProducts, List<SelectedProduct> selectedProducts,
@ -742,4 +747,14 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
duplicateRecursive(space, space.position, duplicatedParent); duplicateRecursive(space, space.position, duplicatedParent);
} }
} }
List<String> _getAllTagValues(List<SpaceModel> spaces) {
final List<String> allTags = [];
for (final space in spaces) {
if (space.tags != null) {
allTags.addAll(space.listAllTagValues());
}
}
return allTags;
}
} }

View File

@ -39,6 +39,7 @@ class CreateSpaceDialog extends StatefulWidget {
final List<SpaceTemplateModel>? spaceModels; final List<SpaceTemplateModel>? spaceModels;
final List<SubspaceModel>? subspaces; final List<SubspaceModel>? subspaces;
final List<Tag>? tags; final List<Tag>? tags;
final List<String>? allTags;
const CreateSpaceDialog( const CreateSpaceDialog(
{super.key, {super.key,
@ -49,6 +50,7 @@ class CreateSpaceDialog extends StatefulWidget {
this.icon, this.icon,
this.isEdit = false, this.isEdit = false,
this.editSpace, this.editSpace,
this.allTags,
this.selectedProducts = const [], this.selectedProducts = const [],
this.spaceModels, this.spaceModels,
this.subspaces, this.subspaces,
@ -79,6 +81,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
widget.selectedProducts.isNotEmpty ? widget.selectedProducts : []; widget.selectedProducts.isNotEmpty ? widget.selectedProducts : [];
isOkButtonEnabled = isOkButtonEnabled =
enteredName.isNotEmpty || nameController.text.isNotEmpty; enteredName.isNotEmpty || nameController.text.isNotEmpty;
tags = widget.tags ?? [];
subspaces = widget.subspaces ?? [];
} }
@override @override
@ -171,14 +175,13 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
} }
}); });
}, },
style: const TextStyle(color: Colors.black), style: Theme.of(context).textTheme.bodyMedium,
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Please enter the name', hintText: 'Please enter the name',
hintStyle: const TextStyle( hintStyle: Theme.of(context)
fontSize: 14, .textTheme
color: ColorsManager.lightGrayColor, .bodyMedium!
fontWeight: FontWeight.w400, .copyWith(color: ColorsManager.lightGrayColor),
),
filled: true, filled: true,
fillColor: ColorsManager.boxColor, fillColor: ColorsManager.boxColor,
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
@ -237,7 +240,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
), ),
) )
: Container( : Container(
width: screenWidth * 0.35, width: screenWidth * 0.25,
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 16.0), vertical: 10.0, horizontal: 16.0),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -251,8 +254,11 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
Chip( Chip(
label: Text( label: Text(
selectedSpaceModel?.modelName ?? '', selectedSpaceModel?.modelName ?? '',
style: const TextStyle( style: Theme.of(context)
color: ColorsManager.spaceColor), .textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.spaceColor),
), ),
backgroundColor: ColorsManager.whiteColors, backgroundColor: ColorsManager.whiteColors,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@ -285,25 +291,25 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
), ),
), ),
const SizedBox(height: 25), const SizedBox(height: 25),
const Row( Row(
children: [ children: [
Expanded( const Expanded(
child: Divider( child: Divider(
color: ColorsManager.neutralGray, color: ColorsManager.neutralGray,
thickness: 1.0, thickness: 1.0,
), ),
), ),
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 6.0), padding: const EdgeInsets.symmetric(horizontal: 6.0),
child: Text( child: Text(
'OR', 'OR',
style: TextStyle( style: Theme.of(context)
color: Colors.black, .textTheme
fontWeight: FontWeight.bold, .bodyMedium
), ?.copyWith(fontWeight: FontWeight.bold),
), ),
), ),
Expanded( const Expanded(
child: Divider( child: Divider(
color: ColorsManager.neutralGray, color: ColorsManager.neutralGray,
thickness: 1.0, thickness: 1.0,
@ -312,7 +318,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
], ],
), ),
const SizedBox(height: 25), const SizedBox(height: 25),
subspaces == null subspaces == null || subspaces!.isEmpty
? TextButton( ? TextButton(
style: TextButton.styleFrom( style: TextButton.styleFrom(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -344,21 +350,29 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
runSpacing: 8.0, runSpacing: 8.0,
children: [ children: [
if (subspaces != null) if (subspaces != null)
...subspaces!.map((subspace) => ...subspaces!.map((subspace) {
SubspaceNameDisplayWidget( return Column(
validateName: (updatedName) { crossAxisAlignment:
return !subspaces!.any((s) => CrossAxisAlignment.start,
s != subspace && children: [
s.subspaceName == updatedName); SubspaceNameDisplayWidget(
}, text: subspace.subspaceName,
text: subspace.subspaceName, validateName: (updatedName) {
onNameChanged: (updatedName) { return subspaces!.any((s) =>
setState(() { s != subspace &&
subspace.subspaceName = s.subspaceName ==
updatedName; updatedName);
}); },
}, onNameChanged: (updatedName) {
)), setState(() {
subspace.subspaceName =
updatedName;
});
},
),
],
);
}),
EditChip( EditChip(
onTap: () async { onTap: () async {
_showSubSpaceDialog(context, enteredName, _showSubSpaceDialog(context, enteredName,
@ -408,9 +422,12 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
), ),
label: Text( label: Text(
'x${entry.value}', // Show count 'x${entry.value}', // Show count
style: const TextStyle( style: Theme.of(context)
color: ColorsManager.spaceColor, .textTheme
), .bodySmall
?.copyWith(
color: ColorsManager
.spaceColor),
), ),
backgroundColor: backgroundColor:
ColorsManager.whiteColors, ColorsManager.whiteColors,
@ -425,14 +442,29 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
), ),
EditChip(onTap: () async { EditChip(onTap: () async {
_showTagCreateDialog( final result = await showDialog(
context, context: context,
enteredName, builder: (context) => AssignTagDialog(
widget.isEdit, products: widget.products,
widget.products, subspaces: widget.subspaces,
subspaces, addedProducts: TagHelper
.createInitialSelectedProductsForTags(
tags ?? [], subspaces),
title: 'Edit Device',
initialTags:
TagHelper.generateInitialForTags(
spaceTags: tags,
subspaces: subspaces),
spaceName: widget.name ?? '',
onSave:
(updatedTags, updatedSubspaces) {
setState(() {
tags = updatedTags;
subspaces = updatedSubspaces;
});
},
),
); );
// Edit action
}) })
], ],
), ),
@ -547,6 +579,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
setState(() { setState(() {
selectedSpaceModel = selectedModel; selectedSpaceModel = selectedModel;
subspaces = null; subspaces = null;
tags = null;
}); });
} }
}, },
@ -597,8 +630,26 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
spaceName: name, spaceName: name,
products: products, products: products,
subspaces: subspaces, subspaces: subspaces,
allTags: [], allTags: widget.allTags,
onSave: (selectedSpaceTags, selectedSubspaces) {}, onSave: (selectedSpaceTags, selectedSubspaces) {
setState(() {
tags = selectedSpaceTags;
selectedSpaceModel = null;
if (selectedSubspaces != null) {
if (subspaces != null) {
for (final subspace in subspaces!) {
for (final selectedSubspace in selectedSubspaces) {
if (subspace.subspaceName ==
selectedSubspace.subspaceName) {
subspace.tags = selectedSubspace.tags;
}
}
}
}
}
});
},
); );
}, },
) )
@ -610,7 +661,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
products: products, products: products,
subspaces: subspaces, subspaces: subspaces,
spaceTags: tags, spaceTags: tags,
allTags: [], isCreate: true,
allTags: widget.allTags,
initialSelectedProducts: initialSelectedProducts:
TagHelper.createInitialSelectedProductsForTags( TagHelper.createInitialSelectedProductsForTags(
tags, subspaces), tags, subspaces),

View File

@ -20,8 +20,7 @@ class SpaceWidget extends StatelessWidget {
top: position.dy, top: position.dy,
child: GestureDetector( child: GestureDetector(
onTap: onTap, onTap: onTap,
child: child: Container(
Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: ColorsManager.whiteColors, color: ColorsManager.whiteColors,
@ -39,11 +38,10 @@ class SpaceWidget extends StatelessWidget {
children: [ children: [
const Icon(Icons.location_on, color: ColorsManager.spaceColor), const Icon(Icons.location_on, color: ColorsManager.spaceColor),
const SizedBox(width: 8), const SizedBox(width: 8),
Text(name, style: const TextStyle(fontSize: 16)), Text(name, style: Theme.of(context).textTheme.bodyMedium),
], ],
), ),
), ),
), ),
); );
} }

View File

@ -12,6 +12,7 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_bloc.dart';
import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_event.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_event.dart';
import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_state.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_state.dart';
import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class AssignTagDialog extends StatelessWidget { class AssignTagDialog extends StatelessWidget {
@ -40,8 +41,11 @@ class AssignTagDialog extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<String> locations = final List<String> locations = (subspaces ?? [])
(subspaces ?? []).map((subspace) => subspace.subspaceName).toList(); .map((subspace) => subspace.subspaceName)
.toList()
..add('Main Space');
return BlocProvider( return BlocProvider(
create: (_) => AssignTagBloc() create: (_) => AssignTagBloc()
..add(InitializeTags( ..add(InitializeTags(
@ -93,21 +97,22 @@ class AssignTagDialog extends StatelessWidget {
], ],
rows: state.tags.isEmpty rows: state.tags.isEmpty
? [ ? [
const DataRow(cells: [ DataRow(cells: [
DataCell( DataCell(
Center( Center(
child: Text( child: Text('No Data Available',
'No Data Available', style: Theme.of(context)
style: TextStyle( .textTheme
fontSize: 14, .bodyMedium
color: ColorsManager.lightGrayColor, ?.copyWith(
), color: ColorsManager
), .lightGrayColor,
)),
), ),
), ),
DataCell(SizedBox()), const DataCell(SizedBox()),
DataCell(SizedBox()), const DataCell(SizedBox()),
DataCell(SizedBox()), const DataCell(SizedBox()),
]) ])
] ]
: List.generate(state.tags.length, (index) { : List.generate(state.tags.length, (index) {
@ -209,10 +214,11 @@ class AssignTagDialog extends StatelessWidget {
), ),
), ),
if (state.errorMessage != null) if (state.errorMessage != null)
Text( Text(state.errorMessage!,
state.errorMessage!, style: Theme.of(context)
style: const TextStyle(color: ColorsManager.warningRed), .textTheme
), .bodySmall
?.copyWith(color: ColorsManager.warningRed)),
], ],
), ),
), ),
@ -235,16 +241,18 @@ class AssignTagDialog extends StatelessWidget {
Navigator.of(context).pop(); Navigator.of(context).pop();
await showDialog<bool>( await showDialog(
barrierDismissible: false,
context: context, context: context,
builder: (dialogContext) => AddDeviceTypeWidget( builder: (context) => AddDeviceTypeWidget(
products: products, products: products,
subspaces: processedSubspaces, subspaces: processedSubspaces,
initialSelectedProducts: addedProducts, initialSelectedProducts: TagHelper
allTags: allTags, .createInitialSelectedProductsForTags(
processedTags, processedSubspaces),
spaceName: spaceName, spaceName: spaceName,
spaceTags: processedTags, spaceTags: processedTags,
isCreate: false,
onSave: onSave,
), ),
); );
}, },
@ -261,7 +269,6 @@ class AssignTagDialog extends StatelessWidget {
foregroundColor: ColorsManager.whiteColors, foregroundColor: ColorsManager.whiteColors,
onPressed: state.isSaveEnabled onPressed: state.isSaveEnabled
? () async { ? () async {
Navigator.of(context).pop();
final updatedTags = List<Tag>.from(state.tags); final updatedTags = List<Tag>.from(state.tags);
final result = final result =
processTags(updatedTags, subspaces); processTags(updatedTags, subspaces);
@ -270,8 +277,8 @@ class AssignTagDialog extends StatelessWidget {
result['updatedTags'] as List<Tag>; result['updatedTags'] as List<Tag>;
final processedSubspaces = final processedSubspaces =
result['subspaces'] as List<SubspaceModel>; result['subspaces'] as List<SubspaceModel>;
onSave?.call(processedTags, processedSubspaces);
onSave!(processedTags, processedSubspaces); Navigator.of(context).pop();
} }
: null, : null,
child: const Text('Save'), child: const Text('Save'),
@ -307,6 +314,14 @@ class AssignTagDialog extends StatelessWidget {
final modifiedTags = List<Tag>.from(updatedTags); final modifiedTags = List<Tag>.from(updatedTags);
final modifiedSubspaces = List<SubspaceModel>.from(subspaces ?? []); final modifiedSubspaces = List<SubspaceModel>.from(subspaces ?? []);
if (subspaces != null) {
for (var subspace in subspaces) {
subspace.tags?.removeWhere(
(tag) => !modifiedTags
.any((updatedTag) => updatedTag.internalId == tag.internalId),
);
}
}
for (var tag in modifiedTags.toList()) { for (var tag in modifiedTags.toList()) {
if (modifiedSubspaces.isEmpty) continue; if (modifiedSubspaces.isEmpty) continue;

View File

@ -112,22 +112,22 @@ class AssignTagModelsDialog extends StatelessWidget {
], ],
rows: state.tags.isEmpty rows: state.tags.isEmpty
? [ ? [
const DataRow(cells: [ DataRow(cells: [
DataCell( DataCell(
Center( Center(
child: Text( child: Text('No Devices Available',
'No Data Available', style: Theme.of(context)
style: TextStyle( .textTheme
fontSize: 14, .bodyMedium
color: ?.copyWith(
ColorsManager.lightGrayColor, color: ColorsManager
), .lightGrayColor,
), )),
), ),
), ),
DataCell(SizedBox()), const DataCell(SizedBox()),
DataCell(SizedBox()), const DataCell(SizedBox()),
DataCell(SizedBox()), const DataCell(SizedBox()),
]) ])
] ]
: List.generate(state.tags.length, (index) { : List.generate(state.tags.length, (index) {
@ -233,11 +233,11 @@ class AssignTagModelsDialog extends StatelessWidget {
), ),
), ),
if (state.errorMessage != null) if (state.errorMessage != null)
Text( Text(state.errorMessage!,
state.errorMessage!, style: Theme.of(context)
style: const TextStyle( .textTheme
color: ColorsManager.warningRed), .bodySmall
), ?.copyWith(color: ColorsManager.warningRed)),
], ],
), ),
), ),
@ -268,7 +268,7 @@ class AssignTagModelsDialog extends StatelessWidget {
builder: (dialogContext) => builder: (dialogContext) =>
AddDeviceTypeModelWidget( AddDeviceTypeModelWidget(
products: products, products: products,
subspaces: subspaces, subspaces: processedSubspaces,
isCreate: false, isCreate: false,
initialSelectedProducts: TagHelper initialSelectedProducts: TagHelper
.createInitialSelectedProducts( .createInitialSelectedProducts(

View File

@ -77,9 +77,7 @@ class CreateCommunityDialog extends StatelessWidget {
.read<CommunityDialogBloc>() .read<CommunityDialogBloc>()
.add(ValidateCommunityNameEvent(value)); .add(ValidateCommunityNameEvent(value));
}, },
style: const TextStyle( style: Theme.of(context).textTheme.bodyMedium,
color: ColorsManager.blackColor,
),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Please enter the community name', hintText: 'Please enter the community name',
filled: true, filled: true,

View File

@ -82,7 +82,6 @@ class SubSpaceBloc extends Bloc<SubSpaceEvent, SubSpaceState> {
)); ));
}); });
on<UpdateSubSpace>((event, emit) { on<UpdateSubSpace>((event, emit) {
final updatedSubSpaces = state.subSpaces.map((subSpace) { final updatedSubSpaces = state.subSpaces.map((subSpace) {
if (subSpace.uuid == event.updatedSubSpace.uuid) { if (subSpace.uuid == event.updatedSubSpace.uuid) {

View File

@ -102,12 +102,13 @@ class CreateSubSpaceDialog extends StatelessWidget {
duplicateIndices.indexOf(index) != 0; duplicateIndices.indexOf(index) != 0;
return Chip( return Chip(
label: Text( label: Text(subSpace.subspaceName,
subSpace.subspaceName, style: Theme.of(context)
style: const TextStyle( .textTheme
color: ColorsManager.spaceColor, .bodyMedium
), ?.copyWith(
), color:
ColorsManager.spaceColor)),
backgroundColor: ColorsManager.whiteColors, backgroundColor: ColorsManager.whiteColors,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
@ -143,27 +144,29 @@ class CreateSubSpaceDialog extends StatelessWidget {
SizedBox( SizedBox(
width: 200, width: 200,
child: TextField( child: TextField(
controller: textController, controller: textController,
decoration: InputDecoration( decoration: InputDecoration(
border: InputBorder.none, border: InputBorder.none,
hintText: state.subSpaces.isEmpty hintText: state.subSpaces.isEmpty
? 'Please enter the name' ? 'Please enter the name'
: null, : null,
hintStyle: const TextStyle( hintStyle: Theme.of(context)
color: ColorsManager.lightGrayColor), .textTheme
), .bodySmall
onSubmitted: (value) { ?.copyWith(
if (value.trim().isNotEmpty) { color: ColorsManager
context.read<SubSpaceBloc>().add( .lightGrayColor)),
AddSubSpace(SubspaceModel( onSubmitted: (value) {
subspaceName: value.trim(), if (value.trim().isNotEmpty) {
disabled: false))); context.read<SubSpaceBloc>().add(
textController.clear(); AddSubSpace(SubspaceModel(
} subspaceName: value.trim(),
}, disabled: false)));
style: const TextStyle( textController.clear();
color: ColorsManager.blackColor), }
), },
style:
Theme.of(context).textTheme.bodyMedium),
), ),
], ],
), ),
@ -171,13 +174,13 @@ class CreateSubSpaceDialog extends StatelessWidget {
if (state.errorMessage.isNotEmpty) if (state.errorMessage.isNotEmpty)
Padding( Padding(
padding: const EdgeInsets.only(top: 8.0), padding: const EdgeInsets.only(top: 8.0),
child: Text( child: Text(state.errorMessage,
state.errorMessage, style: Theme.of(context)
style: const TextStyle( .textTheme
color: ColorsManager.warningRed, .bodySmall
fontSize: 12, ?.copyWith(
), color: ColorsManager.warningRed,
), )),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Row( Row(
@ -193,17 +196,21 @@ class CreateSubSpaceDialog extends StatelessWidget {
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
child: DefaultButton( child: DefaultButton(
onPressed: () async { onPressed: (state.errorMessage.isNotEmpty)
final subSpaces = context ? null
.read<SubSpaceBloc>() : () async {
.state final subSpaces = context
.subSpaces; .read<SubSpaceBloc>()
onSave!(subSpaces); .state
Navigator.of(context).pop(); .subSpaces;
}, onSave!(subSpaces);
Navigator.of(context).pop();
},
backgroundColor: ColorsManager.secondaryColor, backgroundColor: ColorsManager.secondaryColor,
borderRadius: 10, borderRadius: 10,
foregroundColor: ColorsManager.whiteColors, foregroundColor: state.errorMessage.isNotEmpty
? ColorsManager.whiteColorsWithOpacity
: ColorsManager.whiteColors,
child: const Text('OK'), child: const Text('OK'),
), ),
), ),

View File

@ -94,12 +94,13 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
duplicateIndices.indexOf(index) != 0; duplicateIndices.indexOf(index) != 0;
return Chip( return Chip(
label: Text( label: Text(subSpace.subspaceName,
subSpace.subspaceName, style: Theme.of(context)
style: const TextStyle( .textTheme
color: ColorsManager.spaceColor, .bodySmall
), ?.copyWith(
), color: ColorsManager.spaceColor,
)),
backgroundColor: ColorsManager.whiteColors, backgroundColor: ColorsManager.whiteColors,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
@ -135,28 +136,33 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
SizedBox( SizedBox(
width: 200, width: 200,
child: TextField( child: TextField(
controller: textController, controller: textController,
decoration: InputDecoration( decoration: InputDecoration(
border: InputBorder.none, border: InputBorder.none,
hintText: state.subSpaces.isEmpty hintText: state.subSpaces.isEmpty
? 'Please enter the name' ? 'Please enter the name'
: null, : null,
hintStyle: const TextStyle( hintStyle: Theme.of(context)
color: ColorsManager.lightGrayColor), .textTheme
), .bodySmall!
onSubmitted: (value) { .copyWith(
if (value.trim().isNotEmpty) { color: ColorsManager
context.read<SubSpaceModelBloc>().add( .lightGrayColor)),
AddSubSpaceModel( onSubmitted: (value) {
SubspaceTemplateModel( if (value.trim().isNotEmpty) {
subspaceName: value.trim(), context.read<SubSpaceModelBloc>().add(
disabled: false))); AddSubSpaceModel(
textController.clear(); SubspaceTemplateModel(
} subspaceName: value.trim(),
}, disabled: false)));
style: const TextStyle( textController.clear();
color: ColorsManager.blackColor), }
), },
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(
color: ColorsManager.blackColor)),
), ),
], ],
), ),
@ -164,13 +170,13 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
if (state.errorMessage.isNotEmpty) if (state.errorMessage.isNotEmpty)
Padding( Padding(
padding: const EdgeInsets.only(bottom: 16.0), padding: const EdgeInsets.only(bottom: 16.0),
child: Text( child: Text(state.errorMessage,
state.errorMessage, style: Theme.of(context)
style: const TextStyle( .textTheme
color: ColorsManager.red, .bodySmall
fontSize: 12, ?.copyWith(
), color: ColorsManager.red,
), )),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Row( Row(

View File

@ -97,7 +97,10 @@ class SpaceModelPage extends StatelessWidget {
return Center( return Center(
child: Text( child: Text(
'Error: ${state.message}', 'Error: ${state.message}',
style: const TextStyle(color: ColorsManager.warningRed), style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(color: ColorsManager.warningRed),
), ),
); );
} }
@ -109,14 +112,14 @@ class SpaceModelPage extends StatelessWidget {
double _calculateChildAspectRatio(BuildContext context) { double _calculateChildAspectRatio(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width; double screenWidth = MediaQuery.of(context).size.width;
if (screenWidth > 1600) { if (screenWidth > 1600) {
return 2; return 1.5; // Decrease to make cards taller
} }
if (screenWidth > 1200) { if (screenWidth > 1200) {
return 3; return 2.0;
} else if (screenWidth > 800) { } else if (screenWidth > 800) {
return 3.5; return 2.5;
} else { } else {
return 4.0; return 3.0;
} }
} }

View File

@ -167,7 +167,8 @@ class CreateSpaceModelDialog extends StatelessWidget {
onPressed: ((state.errorMessage != null && onPressed: ((state.errorMessage != null &&
state.errorMessage != '') || state.errorMessage != '') ||
!isNameValid) !isNameValid)
? () { ? null
: () {
final updatedSpaceTemplate = final updatedSpaceTemplate =
updatedSpaceModel.copyWith( updatedSpaceModel.copyWith(
modelName: modelName:
@ -240,8 +241,7 @@ class CreateSpaceModelDialog extends StatelessWidget {
} }
} }
} }
} },
: null,
backgroundColor: ColorsManager.secondaryColor, backgroundColor: ColorsManager.secondaryColor,
borderRadius: 10, borderRadius: 10,
foregroundColor: ((state.errorMessage != null && foregroundColor: ((state.errorMessage != null &&

View File

@ -29,7 +29,7 @@ class DynamicRoomWidget extends StatelessWidget {
final TextPainter textPainter = TextPainter( final TextPainter textPainter = TextPainter(
text: TextSpan( text: TextSpan(
text: subspace.subspaceName, text: subspace.subspaceName,
style: const TextStyle(fontSize: 16), style: Theme.of(context).textTheme.bodyMedium
), ),
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
)..layout(); )..layout();

View File

@ -31,82 +31,90 @@ class SpaceModelCardWidget extends StatelessWidget {
} }
} }
return Container( return LayoutBuilder(
padding: const EdgeInsets.all(16.0), builder: (context, constraints) {
decoration: BoxDecoration( bool showOnlyName = constraints.maxWidth < 250;
color: Colors.white, return Container(
borderRadius: BorderRadius.circular(10), padding: const EdgeInsets.all(16.0),
boxShadow: [ decoration: BoxDecoration(
BoxShadow( color: Colors.white,
color: Colors.grey.withOpacity(0.5), borderRadius: BorderRadius.circular(10),
spreadRadius: 2, boxShadow: [
blurRadius: 5, BoxShadow(
offset: const Offset(0, 3), color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
), ),
], child: Column(
), crossAxisAlignment: CrossAxisAlignment.start,
child: Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, Text(
children: [ model.modelName,
Text( style: Theme.of(context).textTheme.headlineMedium?.copyWith(
model.modelName, color: Colors.black,
style: Theme.of(context).textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.bold,
color: Colors.black, ),
fontWeight: FontWeight.bold, maxLines: 1,
), overflow: TextOverflow.ellipsis,
maxLines: 1, ),
overflow: TextOverflow.ellipsis, if (!showOnlyName) ...[
), const SizedBox(height: 10),
const SizedBox(height: 10),
Expanded(
child: Row(
children: [
// Left Container
Expanded( Expanded(
flex: 1, // Distribute space proportionally child: Row(
child: Container( children: [
padding: const EdgeInsets.all(8.0), // Left Container
child: LayoutBuilder( Expanded(
builder: (context, constraints) { flex: 1, // Distribute space proportionally
return Align( child: Container(
alignment: Alignment.topLeft, padding: const EdgeInsets.all(8.0),
child: DynamicRoomWidget( child: LayoutBuilder(
subspaceModels: model.subspaceModels, builder: (context, constraints) {
maxWidth: constraints.maxWidth, return Align(
maxHeight: constraints.maxHeight, alignment: Alignment.topLeft,
child: DynamicRoomWidget(
subspaceModels: model.subspaceModels,
maxWidth: constraints.maxWidth,
maxHeight: constraints.maxHeight,
),
);
},
), ),
); ),
}, ),
), if (productTagCount.isNotEmpty &&
model.subspaceModels != null)
Container(
width: 1.0,
color: ColorsManager.softGray,
margin: const EdgeInsets.symmetric(vertical: 6.0),
),
Expanded(
flex: 1, // Distribute space proportionally
child: Container(
padding: const EdgeInsets.all(8.0),
child: LayoutBuilder(
builder: (context, constraints) {
return Align(
alignment: Alignment.topLeft,
child: DynamicProductWidget(
productTagCount: productTagCount,
maxWidth: constraints.maxWidth,
maxHeight: constraints.maxHeight));
},
),
),
),
],
), ),
), ),
if (productTagCount.isNotEmpty && model.subspaceModels != null) ]
Container( ],
width: 1.0,
color: ColorsManager.softGray,
margin: const EdgeInsets.symmetric(vertical: 6.0),
),
Expanded(
flex: 1, // Distribute space proportionally
child: Container(
padding: const EdgeInsets.all(8.0),
child: LayoutBuilder(
builder: (context, constraints) {
return Align(
alignment: Alignment.topLeft,
child: DynamicProductWidget(
productTagCount: productTagCount,
maxWidth: constraints.maxWidth,
maxHeight: constraints.maxHeight));
},
),
),
),
],
),
), ),
], );
), },
); );
} }
} }

View File

@ -105,6 +105,7 @@ class _SubspaceModelCreateState extends State<SubspaceModelCreate> {
isEdit: true, isEdit: true,
dialogTitle: dialogTitle, dialogTitle: dialogTitle,
existingSubSpaces: _subspaces, existingSubSpaces: _subspaces,
onUpdate: (subspaceModels) { onUpdate: (subspaceModels) {
setState(() { setState(() {
_subspaces = subspaceModels; _subspaces = subspaceModels;

View File

@ -4,7 +4,9 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/create_subs
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_response_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_response_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/create_space_template_body_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/create_space_template_body_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_body_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_body_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart'; import 'package:syncrow_web/utils/constants/api_const.dart';
import 'package:syncrow_web/utils/constants/temp_const.dart'; import 'package:syncrow_web/utils/constants/temp_const.dart';
@ -154,7 +156,7 @@ class CommunitySpaceManagementApi {
.replaceAll('{spaceId}', spaceId) .replaceAll('{spaceId}', spaceId)
.replaceAll('{projectId}', TempConst.projectId), .replaceAll('{projectId}', TempConst.projectId),
expectedResponseModel: (json) { expectedResponseModel: (json) {
return SpaceModel.fromJson(json); return SpaceModel.fromJson(json['data']);
}, },
); );
return response; return response;
@ -210,7 +212,7 @@ class CommunitySpaceManagementApi {
} }
} }
Future<SpaceModel?> updateSpace({ Future<bool> updateSpace({
required String communityId, required String communityId,
required spaceId, required spaceId,
required String name, required String name,
@ -219,6 +221,8 @@ class CommunitySpaceManagementApi {
String? direction, String? direction,
bool isPrivate = false, bool isPrivate = false,
required Offset position, required Offset position,
List<TagModelUpdate>? tags,
List<UpdateSubspaceTemplateModel>? subspaces,
}) async { }) async {
try { try {
final body = { final body = {
@ -228,6 +232,8 @@ class CommunitySpaceManagementApi {
'y': position.dy, 'y': position.dy,
'direction': direction, 'direction': direction,
'icon': icon, 'icon': icon,
'subspace': subspaces,
'tags': tags,
}; };
if (parentId != null) { if (parentId != null) {
body['parentUuid'] = parentId; body['parentUuid'] = parentId;
@ -240,13 +246,13 @@ class CommunitySpaceManagementApi {
.replaceAll('{projectId}', TempConst.projectId), .replaceAll('{projectId}', TempConst.projectId),
body: body, body: body,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return SpaceModel.fromJson(json['data']); return json['success'] ?? false;
}, },
); );
return response; return response;
} catch (e) { } catch (e) {
debugPrint('Error creating space: $e'); debugPrint('Error updating space: $e');
return null; return false;
} }
} }