diff --git a/lib/pages/spaces_management/all_spaces/widgets/loaded_space_widget.dart b/lib/pages/spaces_management/all_spaces/widgets/loaded_space_widget.dart index 5039340c..84ed32f7 100644 --- a/lib/pages/spaces_management/all_spaces/widgets/loaded_space_widget.dart +++ b/lib/pages/spaces_management/all_spaces/widgets/loaded_space_widget.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_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/space_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/community_structure_widget.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/gradient_canvas_border_widget.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/sidebar_widget.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/view/space_model_page.dart'; +import 'package:syncrow_web/services/space_model_mang_api.dart'; class LoadedSpaceView extends StatefulWidget { final List communities; @@ -47,10 +50,16 @@ class _LoadedStateViewState extends State { ), hasSpaceModels ? Expanded( - child: SpaceModelPage( - spaceModels: widget.spaceModels ?? [], - products: widget.products, - )) + child: BlocProvider( + create: (context) => SpaceModelBloc( + api: SpaceModelManagementApi(), + initialSpaceModels: widget.spaceModels ?? [], + ), + child: SpaceModelPage( + products: widget.products, + ), + ), + ) : CommunityStructureArea( selectedCommunity: widget.selectedCommunity, selectedSpace: widget.selectedSpace, diff --git a/lib/pages/spaces_management/space_model/bloc/create_space_model_bloc.dart b/lib/pages/spaces_management/space_model/bloc/create_space_model_bloc.dart index 799d1e27..8055e217 100644 --- a/lib/pages/spaces_management/space_model/bloc/create_space_model_bloc.dart +++ b/lib/pages/spaces_management/space_model/bloc/create_space_model_bloc.dart @@ -15,7 +15,7 @@ class CreateSpaceModelBloc CreateSpaceModelBloc(this._api) : super(CreateSpaceModelInitial()) { on((event, emit) async { try { - final spaceTemplate = event.spaceTemplate; + late SpaceTemplateModel spaceTemplate = event.spaceTemplate; final tagBodyModels = spaceTemplate.tags?.map((tag) => tag.toTagBodyModel()).toList() ?? @@ -37,7 +37,16 @@ class CreateSpaceModelBloc tags: tagBodyModels, subspaceModels: subspaceTemplateBodyModels); - await _api.createSpaceModel(spaceModelBody); + final newSpaceTemplate = await _api.createSpaceModel(spaceModelBody); + spaceTemplate.uuid = newSpaceTemplate?.uuid ?? ''; + + if (newSpaceTemplate != null) { + emit(CreateSpaceModelLoaded(spaceTemplate)); + + if (event.onCreate != null) { + event.onCreate!(spaceTemplate); + } + } } catch (e) { emit(CreateSpaceModelError('Error creating space model')); } @@ -77,22 +86,17 @@ class CreateSpaceModelBloc on((event, emit) { final currentState = state; - print('Current State: $currentState'); if (currentState is CreateSpaceModelLoaded) { if (event.name.trim().isEmpty) { - print("set error message"); emit(CreateSpaceModelLoaded( currentState.space, errorMessage: "Model name cannot be empty", )); - print('State emitted: CreateSpaceModelLoaded with updated model:'); } else { final updatedSpaceModel = currentState.space.copyWith(modelName: event.name); - print( - 'State emitted: CreateSpaceModelLoaded with updated model: $updatedSpaceModel'); - + emit(CreateSpaceModelLoaded(updatedSpaceModel)); } } else { diff --git a/lib/pages/spaces_management/space_model/bloc/create_space_model_event.dart b/lib/pages/spaces_management/space_model/bloc/create_space_model_event.dart index e4288837..9342c771 100644 --- a/lib/pages/spaces_management/space_model/bloc/create_space_model_event.dart +++ b/lib/pages/spaces_management/space_model/bloc/create_space_model_event.dart @@ -19,9 +19,11 @@ class UpdateSpaceTemplate extends CreateSpaceModelEvent { class CreateSpaceTemplate extends CreateSpaceModelEvent { final SpaceTemplateModel spaceTemplate; + final Function(SpaceTemplateModel)? onCreate; const CreateSpaceTemplate({ required this.spaceTemplate, + this.onCreate, }); @override @@ -47,4 +49,4 @@ class ValidateSpaceTemplateName extends CreateSpaceModelEvent { final String name; ValidateSpaceTemplateName({required this.name}); -} \ No newline at end of file +} diff --git a/lib/pages/spaces_management/space_model/bloc/space_model_bloc.dart b/lib/pages/spaces_management/space_model/bloc/space_model_bloc.dart new file mode 100644 index 00000000..e383610d --- /dev/null +++ b/lib/pages/spaces_management/space_model/bloc/space_model_bloc.dart @@ -0,0 +1,36 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_event.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_state.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; +import 'package:syncrow_web/services/space_model_mang_api.dart'; + +class SpaceModelBloc extends Bloc { + final SpaceModelManagementApi api; + + SpaceModelBloc({ + required this.api, + required List initialSpaceModels, + }) : super(SpaceModelLoaded(spaceModels: initialSpaceModels)) { + on(_onCreateSpaceModel); + } + + Future _onCreateSpaceModel( + CreateSpaceModel event, Emitter emit) async { + final currentState = state; + if (currentState is SpaceModelLoaded) { + try { + final newSpaceModel = + await api.getSpaceModel(event.newSpaceModel.uuid ?? ''); + + if (newSpaceModel != null) { + final updatedSpaceModels = + List.from(currentState.spaceModels) + ..add(newSpaceModel); + emit(SpaceModelLoaded(spaceModels: updatedSpaceModels)); + } + } catch (e) { + emit(SpaceModelError(message: e.toString())); + } + } + } +} diff --git a/lib/pages/spaces_management/space_model/bloc/space_model_event.dart b/lib/pages/spaces_management/space_model/bloc/space_model_event.dart new file mode 100644 index 00000000..78331f3c --- /dev/null +++ b/lib/pages/spaces_management/space_model/bloc/space_model_event.dart @@ -0,0 +1,18 @@ +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; + +abstract class SpaceModelEvent extends Equatable { + @override + List get props => []; +} + +class LoadSpaceModels extends SpaceModelEvent {} + +class CreateSpaceModel extends SpaceModelEvent { + final SpaceTemplateModel newSpaceModel; + + CreateSpaceModel({required this.newSpaceModel}); + + @override + List get props => [newSpaceModel]; +} diff --git a/lib/pages/spaces_management/space_model/bloc/space_model_state.dart b/lib/pages/spaces_management/space_model/bloc/space_model_state.dart new file mode 100644 index 00000000..53adf973 --- /dev/null +++ b/lib/pages/spaces_management/space_model/bloc/space_model_state.dart @@ -0,0 +1,29 @@ +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; + +abstract class SpaceModelState extends Equatable { + @override + List get props => []; +} + +class SpaceModelInitial extends SpaceModelState {} + +class SpaceModelLoading extends SpaceModelState {} + +class SpaceModelLoaded extends SpaceModelState { + final List spaceModels; + + SpaceModelLoaded({required this.spaceModels}); + + @override + List get props => [spaceModels]; +} + +class SpaceModelError extends SpaceModelState { + final String message; + + SpaceModelError({required this.message}); + + @override + List get props => [message]; +} 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 dea68dbc..4f762c9a 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 @@ -6,7 +6,7 @@ import 'package:syncrow_web/utils/constants/action_enum.dart'; import 'package:uuid/uuid.dart'; class SpaceTemplateModel extends Equatable { - final String? uuid; + String? uuid; String modelName; List? subspaceModels; final List? tags; @@ -31,16 +31,18 @@ class SpaceTemplateModel extends Equatable { internalId: internalId, modelName: json['modelName'] ?? '', subspaceModels: (json['subspaceModels'] as List?) - ?.map((e) => SubspaceTemplateModel.fromJson(e)) + ?.where((e) => e is Map) // Validate type + .map((e) => + SubspaceTemplateModel.fromJson(e as Map)) .toList() ?? [], tags: (json['tags'] as List?) - ?.map((item) => TagModel.fromJson(item)) + ?.where((item) => item is Map) // Validate type + .map((item) => TagModel.fromJson(item as Map)) .toList() ?? [], ); } - SpaceTemplateModel copyWith({ String? uuid, String? modelName, diff --git a/lib/pages/spaces_management/space_model/view/space_model_page.dart b/lib/pages/spaces_management/space_model/view/space_model_page.dart index 6fecd125..9838282c 100644 --- a/lib/pages/spaces_management/space_model/view/space_model_page.dart +++ b/lib/pages/spaces_management/space_model/view/space_model_page.dart @@ -1,61 +1,90 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_bloc.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_event.dart'; +import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_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/widgets/dialog/create_space_model_dialog.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/widgets/space_model_card_widget.dart'; import 'package:syncrow_web/utils/color_manager.dart'; class SpaceModelPage extends StatelessWidget { - final List spaceModels; final List? products; - const SpaceModelPage({Key? key, required this.spaceModels, this.products}) - : super(key: key); + const SpaceModelPage({Key? key, this.products}) : super(key: key); @override Widget build(BuildContext context) { - final allTagValues = getAllTagValues(); - return Scaffold( - backgroundColor: ColorsManager.whiteColors, - body: Padding( - padding: const EdgeInsets.fromLTRB(20.0, 16.0, 16.0, 16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 3, - crossAxisSpacing: 10.0, - mainAxisSpacing: 10.0, - childAspectRatio: calculateChildAspectRatio(context), - ), - itemCount: spaceModels.length + 1, - itemBuilder: (context, index) { - if (index == spaceModels.length) { - return GestureDetector( - onTap: () { - showDialog( - context: context, - builder: (BuildContext context) { - return CreateSpaceModelDialog( - products: products, - allTags: allTagValues, - ); - }, - ); + return BlocBuilder( + builder: (context, state) { + if (state is SpaceModelLoading) { + return const Center(child: CircularProgressIndicator()); + } else if (state is SpaceModelLoaded) { + final spaceModels = state.spaceModels; + final allTagValues = _getAllTagValues(spaceModels); + + return Scaffold( + backgroundColor: ColorsManager.whiteColors, + body: Padding( + padding: const EdgeInsets.fromLTRB(20.0, 16.0, 16.0, 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + crossAxisSpacing: 10.0, + mainAxisSpacing: 10.0, + childAspectRatio: _calculateChildAspectRatio(context), + ), + itemCount: spaceModels.length + 1, + itemBuilder: (context, index) { + if (index == spaceModels.length) { + // Add Button + return GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext dialogContext) { + return CreateSpaceModelDialog( + products: products, + allTags: allTagValues, + onLoad: (newModel) { + + context.read().add( + CreateSpaceModel( + newSpaceModel: newModel), + ); + }, + ); + }, + ); + }, + child: _buildAddContainer(), + ); + } + // Render existing space model + final model = spaceModels[index]; + return SpaceModelCardWidget(model: model); }, - child: _buildAddContainer(), - ); - } - final model = spaceModels[index]; - return SpaceModelCardWidget(model: model); - }, + ), + ), + ], ), ), - ], - ), - ), + ); + } else if (state is SpaceModelError) { + return Center( + child: Text( + 'Error: ${state.message}', + style: const TextStyle(color: Colors.red), + ), + ); + } + return const Center(child: Text('Initializing...')); + }, ); } @@ -101,23 +130,22 @@ class SpaceModelPage extends StatelessWidget { ); } - double calculateChildAspectRatio(BuildContext context) { + double _calculateChildAspectRatio(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; if (screenWidth > 1600) { return 3; } if (screenWidth > 1200) { - return 5; + return 5; } else if (screenWidth > 800) { return 5; } else { - return 6.0; + return 6.0; } } - List getAllTagValues() { + List _getAllTagValues(List spaceModels) { final List allTags = []; - for (final spaceModel in spaceModels) { if (spaceModel.tags != null) { allTags.addAll(spaceModel.listAllTagValues()); 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 a3b9907d..88a23bcf 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 @@ -17,10 +17,15 @@ class CreateSpaceModelDialog extends StatelessWidget { final List? products; final List? allTags; final SpaceTemplateModel? spaceModel; + final void Function(SpaceTemplateModel newModel)? onLoad; - const CreateSpaceModelDialog( - {Key? key, this.products, this.allTags, this.spaceModel}) - : super(key: key); + const CreateSpaceModelDialog({ + Key? key, + this.products, + this.allTags, + this.spaceModel, + this.onLoad, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -142,11 +147,15 @@ class CreateSpaceModelDialog extends StatelessWidget { ); context.read().add( CreateSpaceTemplate( - spaceTemplate: - updatedSpaceTemplate), + spaceTemplate: + updatedSpaceTemplate, + onCreate: (newModel) { + onLoad!(newModel); + Navigator.of(context) + .pop(); // Close the dialog + }, + ), ); - - Navigator.of(context).pop(); } : null, backgroundColor: ColorsManager.secondaryColor, diff --git a/lib/services/api/http_service.dart b/lib/services/api/http_service.dart index 2ed3da42..ee4584c9 100644 --- a/lib/services/api/http_service.dart +++ b/lib/services/api/http_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; import 'package:syncrow_web/services/api/http_interceptor.dart'; import 'package:syncrow_web/services/locator.dart'; import 'package:syncrow_web/utils/constants/api_const.dart'; @@ -34,13 +35,29 @@ class HTTPService { bool showServerMessage = true, }) async { try { + // Log the request path and query parameters + debugPrint('GET Request: $path'); + if (queryParameters != null) { + debugPrint('Query Parameters: $queryParameters'); + } + + // Perform the HTTP GET request final response = await client.get( path, queryParameters: queryParameters, ); - return expectedResponseModel(response.data); + + // Log the raw response data + debugPrint('Response Data: ${response.data}'); + + // Process the response using the expected model function + final result = expectedResponseModel(response.data); + + return result; } catch (error) { - rethrow; + // Log the error details + debugPrint('Error in GET Request: $error'); + rethrow; // Re-throw the error to propagate it further } } diff --git a/lib/services/space_model_mang_api.dart b/lib/services/space_model_mang_api.dart index 82ed097f..19752aea 100644 --- a/lib/services/space_model_mang_api.dart +++ b/lib/services/space_model_mang_api.dart @@ -50,7 +50,27 @@ class SpaceModelManagementApi { ); return response; } catch (e) { - debugPrint('Error creating community: $e'); + debugPrint('Error creating space model: $e'); + return null; + } + } + + Future getSpaceModel(String spaceModelUuid) async { + try { + final response = await HTTPService().get( + path: ApiEndpoints.getSpaceModel + .replaceAll('{projectId}', TempConst.projectId) + .replaceAll('{spaceModelUuid}', spaceModelUuid), + showServerMessage: true, + expectedResponseModel: (json) { + debugPrint('Response JSON: $json'); + + return SpaceTemplateModel.fromJson(json['data']); + }, + ); + return response; + } catch (e) { + debugPrint('Error getting space model: $e'); return null; } } diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index ca4527fb..a2ff63dc 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -100,4 +100,5 @@ abstract class ApiEndpoints { //space model static const String listSpaceModels = '/projects/{projectId}/space-models'; static const String createSpaceModel = '/projects/{projectId}/space-models'; + static const String getSpaceModel = '/projects/{projectId}/space-models/{spaceModelUuid}'; }