From 944b981ee03f73b827ae12b43c6458f701a59000 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Fri, 3 Jan 2025 14:28:45 +0400 Subject: [PATCH] added subspace model events --- .../view/spaces_management_page.dart | 10 +- .../space_model/bloc/subspace_model_bloc.dart | 38 ++++ .../models/space_template_model.dart | 38 ++-- .../dialog/create_space_model_dialog.dart | 79 +++++--- .../dialog/create_subspace_model_dialog.dart | 188 ++++++++++++++++++ .../widgets/space_model_card_widget.dart | 8 +- lib/utils/constants/temp_const.dart | 2 +- 7 files changed, 307 insertions(+), 56 deletions(-) create mode 100644 lib/pages/spaces_management/space_model/bloc/subspace_model_bloc.dart create mode 100644 lib/pages/spaces_management/space_model/widgets/dialog/create_subspace_model_dialog.dart diff --git a/lib/pages/spaces_management/all_spaces/view/spaces_management_page.dart b/lib/pages/spaces_management/all_spaces/view/spaces_management_page.dart index 33edceb2..77f878b7 100644 --- a/lib/pages/spaces_management/all_spaces/view/spaces_management_page.dart +++ b/lib/pages/spaces_management/all_spaces/view/spaces_management_page.dart @@ -59,10 +59,12 @@ class SpaceManagementPageState extends State { selectedSpace: state.selectedSpace, products: state.products, ); - }else if(state is SpaceModelLoaded){ - return LoadedSpaceView(communities: state.communities, products: state.products, spaceModels: state.spaceModels); - } - else if (state is SpaceManagementError) { + } else if (state is SpaceModelLoaded) { + return LoadedSpaceView( + communities: state.communities, + products: state.products, + spaceModels: state.spaceModels); + } else if (state is SpaceManagementError) { return Center(child: Text('Error: ${state.errorMessage}')); } return Container(); diff --git a/lib/pages/spaces_management/space_model/bloc/subspace_model_bloc.dart b/lib/pages/spaces_management/space_model/bloc/subspace_model_bloc.dart new file mode 100644 index 00000000..423a5ca5 --- /dev/null +++ b/lib/pages/spaces_management/space_model/bloc/subspace_model_bloc.dart @@ -0,0 +1,38 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; + +// Events +abstract class SubSpaceModelEvent {} + +class AddSubSpaceModel extends SubSpaceModelEvent { + final SubspaceTemplateModel subSpace; + AddSubSpaceModel(this.subSpace); +} + +class RemoveSubSpaceModel extends SubSpaceModelEvent { + final SubspaceTemplateModel subSpace; + RemoveSubSpaceModel(this.subSpace); +} + +// State +class SubSpaceModelState { + final List subSpaces; + SubSpaceModelState(this.subSpaces); +} + +// BLoC +class SubSpaceModelBloc extends Bloc { + SubSpaceModelBloc() : super(SubSpaceModelState([])) { + on((event, emit) { + final updatedSubSpaces = List.from(state.subSpaces) + ..add(event.subSpace); + emit(SubSpaceModelState(updatedSubSpaces)); + }); + + on((event, emit) { + final updatedSubSpaces = List.from(state.subSpaces) + ..remove(event.subSpace); + emit(SubSpaceModelState(updatedSubSpaces)); + }); + } +} diff --git a/lib/pages/spaces_management/space_model/models/space_template_model.dart b/lib/pages/spaces_management/space_model/models/space_template_model.dart index 3d29c29f..2107b87f 100644 --- a/lib/pages/spaces_management/space_model/models/space_template_model.dart +++ b/lib/pages/spaces_management/space_model/models/space_template_model.dart @@ -1,4 +1,5 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart'; +import 'package:uuid/uuid.dart'; class SpaceTemplateModel { final String uuid; @@ -6,28 +7,33 @@ class SpaceTemplateModel { final DateTime updatedAt; final String modelName; final bool disabled; - final List subspaceModels; + final List subspaceModels; final List tags; + String internalId; SpaceTemplateModel({ required this.uuid, + String? internalId, required this.createdAt, required this.updatedAt, required this.modelName, required this.disabled, required this.subspaceModels, required this.tags, - }); + }) : internalId = internalId ?? const Uuid().v4(); factory SpaceTemplateModel.fromJson(Map json) { + final String internalId = json['internalId'] ?? const Uuid().v4(); + return SpaceTemplateModel( uuid: json['uuid'] ?? '', + internalId: internalId, createdAt: DateTime.parse(json['createdAt']), updatedAt: DateTime.parse(json['updatedAt']), modelName: json['modelName'] ?? '', disabled: json['disabled'] ?? false, subspaceModels: (json['subspaceModels'] as List) - .map((item) => SubspaceModel.fromJson(item)) + .map((item) => SubspaceTemplateModel.fromJson(item)) .toList(), tags: (json['tags'] as List) .map((item) => TagModel.fromJson(item)) @@ -48,28 +54,22 @@ class SpaceTemplateModel { } } -class SubspaceModel { - final String uuid; - final DateTime createdAt; - final DateTime updatedAt; +class SubspaceTemplateModel { + final String? uuid; final String subspaceName; final bool disabled; - final List tags; + final List? tags; - SubspaceModel({ - required this.uuid, - required this.createdAt, - required this.updatedAt, + SubspaceTemplateModel({ + this.uuid, required this.subspaceName, required this.disabled, - required this.tags, + this.tags, }); - factory SubspaceModel.fromJson(Map json) { - return SubspaceModel( + factory SubspaceTemplateModel.fromJson(Map json) { + return SubspaceTemplateModel( uuid: json['uuid'] ?? '', - createdAt: DateTime.parse(json['createdAt']), - updatedAt: DateTime.parse(json['updatedAt']), subspaceName: json['subspaceName'] ?? '', disabled: json['disabled'] ?? false, tags: (json['tags'] as List) @@ -81,11 +81,9 @@ class SubspaceModel { Map toJson() { return { 'uuid': uuid, - 'createdAt': createdAt.toIso8601String(), - 'updatedAt': updatedAt.toIso8601String(), 'subspaceName': subspaceName, 'disabled': disabled, - 'tags': tags.map((e) => e.toJson()).toList(), + 'tags': tags?.map((e) => e.toJson()).toList() ?? [], }; } } diff --git a/lib/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart b/lib/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart index c253da02..4f0fff01 100644 --- a/lib/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart +++ b/lib/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.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/space_model/models/space_template_model.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dialog/create_subspace_model_dialog.dart'; import 'package:syncrow_web/utils/color_manager.dart'; class CreateSpaceModelDialog extends StatelessWidget { @@ -48,37 +50,58 @@ class CreateSpaceModelDialog extends StatelessWidget { ), ), const SizedBox(height: 16), - SizedBox( - width: screenWidth * 0.25, - child: Container( - decoration: BoxDecoration( - color: ColorsManager.textFieldGreyColor, - border: Border.all( - color: ColorsManager.neutralGray, - width: 3.0, + GestureDetector( + onTap: () async { + final result = await showDialog( + context: context, + builder: (BuildContext context) { + return CreateSubSpaceModelDialog( + isEdit: true, + dialogTitle: 'Create Sub-space', + existingSubSpaces: [ + SubspaceTemplateModel( + subspaceName: "Living Room", + disabled: false, + uuid: "mkmkl,", + ), + ], + ); + }, + ); + if (result == true) {} + }, + child: SizedBox( + width: screenWidth * 0.25, + child: Container( + decoration: BoxDecoration( + color: ColorsManager.textFieldGreyColor, + border: Border.all( + color: ColorsManager.neutralGray, + width: 3.0, + ), + borderRadius: BorderRadius.circular(20), ), - borderRadius: BorderRadius.circular(20), - ), - child: const Padding( - padding: - EdgeInsets.symmetric(vertical: 10.0, horizontal: 16.0), - child: Row( - children: [ - Icon( - Icons.add, - color: ColorsManager.spaceColor, - ), - SizedBox(width: 10), - Expanded( - child: Text( - 'Create sub space', - style: TextStyle( - color: ColorsManager.blackColor, - fontSize: 16, + child: const Padding( + padding: + EdgeInsets.symmetric(vertical: 10.0, horizontal: 16.0), + child: Row( + children: [ + Icon( + Icons.add, + color: ColorsManager.spaceColor, + ), + SizedBox(width: 10), + Expanded( + child: Text( + 'Create sub space', + style: TextStyle( + color: ColorsManager.blackColor, + fontSize: 16, + ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/spaces_management/space_model/widgets/dialog/create_subspace_model_dialog.dart b/lib/pages/spaces_management/space_model/widgets/dialog/create_subspace_model_dialog.dart new file mode 100644 index 00000000..9738f079 --- /dev/null +++ b/lib/pages/spaces_management/space_model/widgets/dialog/create_subspace_model_dialog.dart @@ -0,0 +1,188 @@ +import 'package:flutter/material.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/default_button.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/bloc/subspace_model_bloc.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; + +class CreateSubSpaceModelDialog extends StatefulWidget { + final bool isEdit; // Flag to determine if it's edit or create + final String dialogTitle; // Title for the dialog + final List? existingSubSpaces; // For edit mode + + const CreateSubSpaceModelDialog({ + super.key, + required this.isEdit, + required this.dialogTitle, + this.existingSubSpaces, + }); + + @override + _CreateSubSpaceModelDialogState createState() => + _CreateSubSpaceModelDialogState(); +} + +class _CreateSubSpaceModelDialogState extends State { + final TextEditingController textController = TextEditingController(); + final FocusNode focusNode = FocusNode(); + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + focusNode.requestFocus(); + }); + + if (widget.isEdit) {} + } + + @override + void dispose() { + textController.dispose(); + focusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + child: BlocProvider( + create: (_) => SubSpaceModelBloc(), + child: BlocBuilder( + builder: (context, state) { + return SizedBox( + width: screenWidth * 0.35, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + widget.dialogTitle, + style: Theme.of(context) + .textTheme + .headlineLarge + ?.copyWith(color: ColorsManager.blackColor), + ), + const SizedBox(height: 16), + Container( + width: 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.0, + runSpacing: 8.0, + children: [ + ...state.subSpaces.map( + (subSpace) => Chip( + label: Text(subSpace.subspaceName, + style: const TextStyle( + color: ColorsManager.spaceColor)), + backgroundColor: ColorsManager.whiteColors, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: const BorderSide( + color: 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, + ), + ), + onDeleted: () => context + .read() + .add(RemoveSubSpaceModel(subSpace)), + ), + ), + SizedBox( + width: 200, + child: TextField( + controller: textController, + focusNode: focusNode, + decoration: InputDecoration( + border: InputBorder.none, + hintText: state.subSpaces.isEmpty + ? 'Please enter the name' + : null, + hintStyle: const TextStyle( + color: ColorsManager.lightGrayColor), + ), + onSubmitted: (value) { + if (value.trim().isNotEmpty) { + context.read().add( + AddSubSpaceModel(SubspaceTemplateModel( + subspaceName: value.trim(), + disabled: false))); + textController.clear(); + focusNode.requestFocus(); + } + }, + style: const TextStyle( + color: ColorsManager.blackColor), + ), + ), + ], + ), + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: CancelButton( + label: 'Cancel', + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + const SizedBox(width: 10), + Expanded( + child: DefaultButton( + onPressed: () { + final subSpaces = context + .read() + .state + .subSpaces; + Navigator.of(context).pop(subSpaces); + }, + backgroundColor: ColorsManager.secondaryColor, + borderRadius: 10, + foregroundColor: ColorsManager.whiteColors, + child: const Text('OK'), + ), + ), + ], + ), + ], + ), + ), + ); + }, + ), + ), + ); + } +} diff --git a/lib/pages/spaces_management/space_model/widgets/space_model_card_widget.dart b/lib/pages/spaces_management/space_model/widgets/space_model_card_widget.dart index 49128a3f..550361c7 100644 --- a/lib/pages/spaces_management/space_model/widgets/space_model_card_widget.dart +++ b/lib/pages/spaces_management/space_model/widgets/space_model_card_widget.dart @@ -19,9 +19,11 @@ class SpaceModelCardWidget extends StatelessWidget { } for (var subspace in model.subspaceModels) { - for (var tag in subspace.tags) { - final prodIcon = tag.product?.icon ?? 'Unknown'; - productTagCount[prodIcon] = (productTagCount[prodIcon] ?? 0) + 1; + if (subspace.tags != null) { + for (var tag in subspace.tags!) { + final prodIcon = tag.product?.icon ?? 'Unknown'; + productTagCount[prodIcon] = (productTagCount[prodIcon] ?? 0) + 1; + } } } diff --git a/lib/utils/constants/temp_const.dart b/lib/utils/constants/temp_const.dart index e5847b98..bcd1a1d6 100644 --- a/lib/utils/constants/temp_const.dart +++ b/lib/utils/constants/temp_const.dart @@ -1,3 +1,3 @@ class TempConst { - static const projectId = '0e62577c-06fa-41b9-8a92-99a21fbaf51c'; + static const projectId = '0685c781-df33-4cbf-bf65-9f4e835eb468'; }