added initial flow

This commit is contained in:
hannathkadher
2025-01-18 00:32:48 +04:00
parent ec5b7d4395
commit 440263e2f9
7 changed files with 152 additions and 83 deletions

View File

@ -9,10 +9,8 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_pr
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_bloc.dart';
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_event.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_event.dart';
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_state.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_state.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/subspace_template_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class AssignTagModelsDialog extends StatelessWidget { class AssignTagModelsDialog extends StatelessWidget {
@ -24,6 +22,8 @@ class AssignTagModelsDialog extends StatelessWidget {
final List<String>? allTags; final List<String>? allTags;
final String spaceName; final String spaceName;
final String title; final String title;
final void Function(
List<TagModel>? tags, List<SubspaceTemplateModel>? subspaces)? onUpdate;
const AssignTagModelsDialog( const AssignTagModelsDialog(
{Key? key, {Key? key,
@ -34,7 +34,8 @@ class AssignTagModelsDialog extends StatelessWidget {
this.onTagsAssigned, this.onTagsAssigned,
this.allTags, this.allTags,
required this.spaceName, required this.spaceName,
required this.title}) required this.title,
this.onUpdate})
: super(key: key); : super(key: key);
@override @override
@ -226,6 +227,21 @@ class AssignTagModelsDialog extends StatelessWidget {
label: 'Add New Device', label: 'Add New Device',
onPressed: () async { onPressed: () async {
Navigator.of(context).pop(); Navigator.of(context).pop();
final assignedTags = <TagModel>{};
for (var tag in state.tags) {
if (tag.location == null || subspaces == null) {
continue;
}
for (var subspace in subspaces!) {
if (tag.location == subspace.subspaceName) {
subspace.tags ??= [];
subspace.tags!.add(tag);
assignedTags.add(tag);
break;
}
}
}
state.tags.removeWhere(assignedTags.contains);
}, },
), ),
), ),
@ -256,18 +272,7 @@ class AssignTagModelsDialog extends StatelessWidget {
} }
} }
state.tags.removeWhere(assignedTags.contains); state.tags.removeWhere(assignedTags.contains);
await showDialog( onUpdate!(state.tags,subspaces);
barrierDismissible: false,
context: context,
builder: (context) => CreateSpaceModelDialog(
products: products,
allTags: allTags,
spaceModel: SpaceTemplateModel(
modelName: spaceName,
subspaceModels: subspaces,
tags: state.tags),
),
);
} }
: null, : null,
child: const Text('Save'), child: const Text('Save'),

View File

@ -84,6 +84,24 @@ class CreateSpaceModelBloc
} }
}); });
on<AddTagsToSpaceTemplate>((event, emit) {
final currentState = state;
if (currentState is CreateSpaceModelLoaded) {
final updatedTags = currentState.space.copyWith(
tags: [
...(_space!.tags ?? []),
...event.tags,
],
);
emit(CreateSpaceModelLoaded(updatedTags));
} else {
emit(CreateSpaceModelError("Space template not initialized"));
}
});
on<UpdateSpaceTemplateName>((event, emit) { on<UpdateSpaceTemplateName>((event, emit) {
final currentState = state; final currentState = state;
if (currentState is CreateSpaceModelLoaded) { if (currentState is CreateSpaceModelLoaded) {

View File

@ -1,6 +1,7 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.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/subspace_template_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
abstract class CreateSpaceModelEvent extends Equatable { abstract class CreateSpaceModelEvent extends Equatable {
const CreateSpaceModelEvent(); const CreateSpaceModelEvent();
@ -46,6 +47,13 @@ class AddSubspacesToSpaceTemplate extends CreateSpaceModelEvent {
AddSubspacesToSpaceTemplate(this.subspaces); AddSubspacesToSpaceTemplate(this.subspaces);
} }
class AddTagsToSpaceTemplate extends CreateSpaceModelEvent {
final List<TagModel> tags;
AddTagsToSpaceTemplate(this.tags);
}
class ValidateSpaceTemplateName extends CreateSpaceModelEvent { class ValidateSpaceTemplateName extends CreateSpaceModelEvent {
final String name; final String name;

View File

@ -13,7 +13,7 @@ class SpaceTemplateModel extends Equatable {
String internalId; String internalId;
@override @override
List<Object?> get props => [modelName, subspaceModels]; List<Object?> get props => [modelName, subspaceModels, tags];
SpaceTemplateModel({ SpaceTemplateModel({
this.uuid, this.uuid,

View File

@ -118,13 +118,28 @@ class CreateSpaceModelDialog extends StatelessWidget {
}, },
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
TagChipDisplay(context, TagChipDisplay(
screenWidth: screenWidth, context,
spaceModel: updatedSpaceModel, screenWidth: screenWidth,
products: products, spaceModel: updatedSpaceModel,
subspaces: subspaces, products: products,
allTags: allTags, subspaces: subspaces,
spaceNameController: spaceNameController), allTags: allTags,
spaceNameController: spaceNameController,
onLoad: (tags, subspaces) {
if(subspaces!=null){
context
.read<CreateSpaceModelBloc>()
.add(AddSubspacesToSpaceTemplate(subspaces));
}
if(tags!=null){
context
.read<CreateSpaceModelBloc>()
.add(AddTagsToSpaceTemplate(tags));
}
},
),
const SizedBox(height: 20), const SizedBox(height: 20),
SizedBox( SizedBox(
width: screenWidth * 0.25, width: screenWidth * 0.25,

View File

@ -16,17 +16,19 @@ class TagChipDisplay extends StatelessWidget {
final List<SubspaceTemplateModel>? subspaces; final List<SubspaceTemplateModel>? subspaces;
final List<String>? allTags; final List<String>? allTags;
final TextEditingController spaceNameController; final TextEditingController spaceNameController;
final void Function(
List<TagModel>? tags, List<SubspaceTemplateModel>? subspaces)? onLoad;
const TagChipDisplay( const TagChipDisplay(BuildContext context,
BuildContext context, { {Key? key,
Key? key, required this.screenWidth,
required this.screenWidth, required this.spaceModel,
required this.spaceModel, required this.products,
required this.products, required this.subspaces,
required this.subspaces, required this.allTags,
required this.allTags, required this.spaceNameController,
required this.spaceNameController, this.onLoad})
}) : super(key: key); : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -104,15 +106,12 @@ class TagChipDisplay extends StatelessWidget {
child: Chip( child: Chip(
label: const Text( label: const Text(
'Edit', 'Edit',
style: TextStyle( style: TextStyle(color: ColorsManager.spaceColor),
color: ColorsManager.spaceColor),
), ),
backgroundColor: backgroundColor: ColorsManager.whiteColors,
ColorsManager.whiteColors,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
side: const BorderSide( side: const BorderSide(color: ColorsManager.spaceColor),
color: ColorsManager.spaceColor),
), ),
), ),
), ),
@ -122,7 +121,7 @@ class TagChipDisplay extends StatelessWidget {
) )
: TextButton( : TextButton(
onPressed: () async { onPressed: () async {
final result = await showDialog<bool>( await showDialog<bool>(
barrierDismissible: false, barrierDismissible: false,
context: context, context: context,
builder: (context) => AddDeviceTypeModelWidget( builder: (context) => AddDeviceTypeModelWidget(
@ -131,9 +130,13 @@ class TagChipDisplay extends StatelessWidget {
allTags: allTags, allTags: allTags,
spaceName: spaceNameController.text, spaceName: spaceNameController.text,
isCreate: true, isCreate: true,
onLoad: (tags, subspaces) {
if (onLoad != null) {
onLoad!(tags, subspaces);
}
},
), ),
); );
if (result == true) {}
}, },
style: TextButton.styleFrom( style: TextButton.styleFrom(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -189,5 +192,4 @@ class TagChipDisplay extends StatelessWidget {
)) ))
.toList(); .toList();
} }
} }

View File

@ -1,17 +1,15 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart'; 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/assign_tag_models/views/assign_tag_models_dialog.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag_models/views/assign_tag_models_dialog.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
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/space_model/models/space_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart';
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_bloc.dart';
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_state.dart'; import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_state.dart';
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_type_model_event.dart'; import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_type_model_event.dart';
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/action_button_widget.dart';
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/scrollable_grid_view_widget.dart'; import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/scrollable_grid_view_widget.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
@ -23,6 +21,8 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
final List<String>? allTags; final List<String>? allTags;
final String spaceName; final String spaceName;
final bool isCreate; final bool isCreate;
final void Function(
List<TagModel>? tags, List<SubspaceTemplateModel>? subspaces)? onLoad;
const AddDeviceTypeModelWidget({ const AddDeviceTypeModelWidget({
super.key, super.key,
@ -33,6 +33,7 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
this.spaceTagModels, this.spaceTagModels,
required this.spaceName, required this.spaceName,
required this.isCreate, required this.isCreate,
this.onLoad,
}); });
@override @override
@ -94,46 +95,66 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
CancelButton( CancelButton(
label: 'Cancel', label: 'Cancel',
onPressed: () async { onPressed: () async {
if (isCreate) { if (isCreate) {
Navigator.of(context).pop(); Navigator.of(context).pop();
}
},
),
ActionButton(
label: 'Continue',
backgroundColor: ColorsManager.secondaryColor,
foregroundColor: ColorsManager.whiteColors,
onPressed: () async {
final state = context.read<AddDeviceTypeModelBloc>().state;
if (state is AddDeviceModelLoaded &&
state.selectedProducts.isNotEmpty) {
final initialTags = generateInitialTags(
spaceTagModels: spaceTagModels,
subspaces: subspaces,
);
if (isCreate) {
Navigator.of(context).pop();
}
final dialogTitle = initialTags.isNotEmpty
? 'Edit Device'
: 'Assign Tags';
await showDialog<bool>(
barrierDismissible: false,
context: context,
builder: (context) => AssignTagModelsDialog(
products: products,
subspaces: subspaces,
addedProducts: state.selectedProducts,
allTags: allTags,
spaceName: spaceName,
initialTags: state.initialTag,
title: dialogTitle,
),
);
} }
}, },
), ),
SizedBox(
width: 140,
child:
BlocBuilder<AddDeviceTypeModelBloc, AddDeviceModelState>(
builder: (context, state) {
final isDisabled = state is AddDeviceModelLoaded &&
state.selectedProducts.isEmpty;
return DefaultButton(
backgroundColor: ColorsManager.secondaryColor,
foregroundColor: isDisabled
? ColorsManager.whiteColorsWithOpacity
: ColorsManager.whiteColors,
borderRadius: 10,
onPressed: isDisabled
? null // Disable the button
: () async {
if (state is AddDeviceModelLoaded &&
state.selectedProducts.isNotEmpty) {
final initialTags = generateInitialTags(
spaceTagModels: spaceTagModels,
subspaces: subspaces,
);
if (isCreate) {
Navigator.of(context).pop();
}
final dialogTitle = initialTags.isNotEmpty
? 'Edit Device'
: 'Assign Tags';
await showDialog<bool>(
barrierDismissible: false,
context: context,
builder: (context) => AssignTagModelsDialog(
products: products,
subspaces: subspaces,
addedProducts: state.selectedProducts,
allTags: allTags,
spaceName: spaceName,
initialTags: state.initialTag,
title: dialogTitle,
onUpdate: (tags, subspaces) {
if (onLoad != null) {
onLoad!(tags, subspaces);
}
},
),
);
}
},
child: const Text('Next'),
);
},
),
),
], ],
), ),
], ],