From 96f463229c2ad4890223abecbe0ad275e0e67d9a Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 13:12:57 +0300 Subject: [PATCH 01/18] SP-1723-FE-Integrate-Charts-with-API-s-for-AQI-sensor. --- lib/main.dart | 12 +++--- lib/main_dev.dart | 10 +++-- lib/main_staging.dart | 5 +-- lib/pages/home/bloc/home_bloc.dart | 66 ++++++++---------------------- lib/pages/home/view/home_page.dart | 16 +++++++- lib/services/home_api.dart | 18 +++++--- 6 files changed, 57 insertions(+), 70 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8eb6ce38..31ae414b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,7 +7,6 @@ import 'package:go_router/go_router.dart'; import 'package:syncrow_web/firebase_options_prod.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart'; import 'package:syncrow_web/pages/home/bloc/home_bloc.dart'; -import 'package:syncrow_web/pages/home/bloc/home_event.dart'; import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; @@ -21,8 +20,10 @@ import 'package:syncrow_web/utils/theme/theme.dart'; Future main() async { try { - const environment = - String.fromEnvironment('FLAVOR', defaultValue: 'production'); + const environment = String.fromEnvironment( + 'FLAVOR', + defaultValue: 'production', + ); await dotenv.load(fileName: '.env.$environment'); WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( @@ -40,7 +41,7 @@ class MyApp extends StatelessWidget { initialLocation: RoutesConst.auth, routes: AppRoutes.getRoutes(), redirect: (context, state) async { - String checkToken = await AuthBloc.getTokenAndValidate(); + final checkToken = await AuthBloc.getTokenAndValidate(); final loggedIn = checkToken == 'Success'; final goingToLogin = state.uri.toString() == RoutesConst.auth; @@ -58,8 +59,7 @@ class MyApp extends StatelessWidget { BlocProvider( create: (context) => CreateRoutineBloc(), ), - BlocProvider( - create: (context) => HomeBloc()..add(const FetchUserInfo())), + BlocProvider(create: (context) => HomeBloc()), BlocProvider( create: (context) => VisitorPasswordBloc(), ), diff --git a/lib/main_dev.dart b/lib/main_dev.dart index 578b2c30..8813f6ec 100644 --- a/lib/main_dev.dart +++ b/lib/main_dev.dart @@ -7,7 +7,6 @@ import 'package:go_router/go_router.dart'; import 'package:syncrow_web/firebase_options_dev.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart'; import 'package:syncrow_web/pages/home/bloc/home_bloc.dart'; -import 'package:syncrow_web/pages/home/bloc/home_event.dart'; import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; @@ -21,7 +20,10 @@ import 'package:syncrow_web/utils/theme/theme.dart'; Future main() async { try { - const environment = String.fromEnvironment('FLAVOR', defaultValue: 'development'); + const environment = String.fromEnvironment( + 'FLAVOR', + defaultValue: 'development', + ); await dotenv.load(fileName: '.env.$environment'); WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( @@ -39,7 +41,7 @@ class MyApp extends StatelessWidget { initialLocation: RoutesConst.auth, routes: AppRoutes.getRoutes(), redirect: (context, state) async { - String checkToken = await AuthBloc.getTokenAndValidate(); + final checkToken = await AuthBloc.getTokenAndValidate(); final loggedIn = checkToken == 'Success'; final goingToLogin = state.uri.toString() == RoutesConst.auth; @@ -57,7 +59,7 @@ class MyApp extends StatelessWidget { BlocProvider( create: (context) => CreateRoutineBloc(), ), - BlocProvider(create: (context) => HomeBloc()..add(const FetchUserInfo())), + BlocProvider(create: (context) => HomeBloc()), BlocProvider( create: (context) => VisitorPasswordBloc(), ), diff --git a/lib/main_staging.dart b/lib/main_staging.dart index e7f95c57..d393eb7b 100644 --- a/lib/main_staging.dart +++ b/lib/main_staging.dart @@ -7,7 +7,6 @@ import 'package:go_router/go_router.dart'; import 'package:syncrow_web/firebase_options_prod.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart'; import 'package:syncrow_web/pages/home/bloc/home_bloc.dart'; -import 'package:syncrow_web/pages/home/bloc/home_event.dart'; import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; @@ -39,7 +38,7 @@ class MyApp extends StatelessWidget { initialLocation: RoutesConst.auth, routes: AppRoutes.getRoutes(), redirect: (context, state) async { - String checkToken = await AuthBloc.getTokenAndValidate(); + final checkToken = await AuthBloc.getTokenAndValidate(); final loggedIn = checkToken == 'Success'; final goingToLogin = state.uri.toString() == RoutesConst.auth; @@ -57,7 +56,7 @@ class MyApp extends StatelessWidget { BlocProvider( create: (context) => CreateRoutineBloc(), ), - BlocProvider(create: (context) => HomeBloc()..add(const FetchUserInfo())), + BlocProvider(create: (context) => HomeBloc()), BlocProvider( create: (context) => VisitorPasswordBloc(), ), diff --git a/lib/pages/home/bloc/home_bloc.dart b/lib/pages/home/bloc/home_bloc.dart index ad6ed4d8..c1bcba6a 100644 --- a/lib/pages/home/bloc/home_bloc.dart +++ b/lib/pages/home/bloc/home_bloc.dart @@ -13,30 +13,32 @@ import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart'; import 'package:syncrow_web/services/home_api.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/routes_const.dart'; -import 'package:syncrow_web/utils/navigation_service.dart'; class HomeBloc extends Bloc { UserModel? user; String terms = ''; String policy = ''; - HomeBloc() : super((HomeInitial())) { - // on(_createNode); + HomeBloc() : super(HomeInitial()) { on(_fetchUserInfo); on(_fetchTerms); on(_fetchPolicy); on(_confirmUserAgreement); } - Future _fetchUserInfo(FetchUserInfo event, Emitter emit) async { + Future _fetchUserInfo( + FetchUserInfo event, + Emitter emit, + ) async { try { - var uuid = + final uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey); - user = await HomeApi().fetchUserInfo(uuid); + if (uuid != null) { + user = await HomeApi().fetchUserInfo(uuid); + } - if (user != null && user!.project != null) { + if (user != null && user?.project != null) { await ProjectManager.setProjectUUID(user!.project!.uuid); - } add(FetchTermEvent()); add(FetchPolicyEvent()); @@ -47,7 +49,7 @@ class HomeBloc extends Bloc { } } - Future _fetchTerms(FetchTermEvent event, Emitter emit) async { + Future _fetchTerms(FetchTermEvent event, Emitter emit) async { try { emit(LoadingHome()); terms = await HomeApi().fetchTerms(); @@ -57,22 +59,22 @@ class HomeBloc extends Bloc { } } - Future _fetchPolicy(FetchPolicyEvent event, Emitter emit) async { + Future _fetchPolicy(FetchPolicyEvent event, Emitter emit) async { try { emit(LoadingHome()); policy = await HomeApi().fetchPolicy(); emit(HomeInitial()); } catch (e) { - debugPrint("Error fetching policy: $e"); + debugPrint('Error fetching policy: $e'); return; } } - Future _confirmUserAgreement( + Future _confirmUserAgreement( ConfirmUserAgreementEvent event, Emitter emit) async { try { emit(LoadingHome()); - var uuid = + final uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey); policy = await HomeApi().confirmUserAgreements(uuid); emit(PolicyAgreement()); @@ -81,7 +83,7 @@ class HomeBloc extends Bloc { } } - List homeItems = [ + final List homeItems = [ HomeItemModel( title: 'Access Management', icon: Assets.accessIcon, @@ -126,41 +128,5 @@ class HomeBloc extends Bloc { }, color: const Color(0xFF023DFE), ), - - // HomeItemModel( - // title: 'Move in', - // icon: Assets.moveinIcon, - // active: false, - // onPress: (context) {}, - // color: ColorsManager.primaryColor, - // ), - // HomeItemModel( - // title: 'Construction', - // icon: Assets.constructionIcon, - // active: false, - // onPress: (context) {}, - // color: ColorsManager.primaryColor, - // ), - // HomeItemModel( - // title: 'Energy', - // icon: Assets.energyIcon, - // active: false, - // onPress: (context) {}, - // color: ColorsManager.slidingBlueColor.withOpacity(0.2), - // ), - // HomeItemModel( - // title: 'Integrations', - // icon: Assets.integrationsIcon, - // active: false, - // onPress: (context) {}, - // color: ColorsManager.slidingBlueColor.withOpacity(0.2), - // ), - // HomeItemModel( - // title: 'Asset', - // icon: Assets.assetIcon, - // active: false, - // onPress: (context) {}, - // color: ColorsManager.slidingBlueColor.withOpacity(0.2), - // ), ]; } diff --git a/lib/pages/home/view/home_page.dart b/lib/pages/home/view/home_page.dart index 9159011f..9661cfd9 100644 --- a/lib/pages/home/view/home_page.dart +++ b/lib/pages/home/view/home_page.dart @@ -1,11 +1,25 @@ import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/home/bloc/home_bloc.dart'; +import 'package:syncrow_web/pages/home/bloc/home_event.dart'; import 'package:syncrow_web/pages/home/view/home_page_mobile.dart'; import 'package:syncrow_web/pages/home/view/home_page_web.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; -class HomePage extends StatelessWidget with HelperResponsiveLayout { +class HomePage extends StatefulWidget { const HomePage({super.key}); + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State with HelperResponsiveLayout{ + + @override + void initState() { + context.read().add(const FetchUserInfo()); + super.initState(); + } @override Widget build(BuildContext context) { final isSmallScreen = isSmallScreenSize(context); diff --git a/lib/services/home_api.dart b/lib/services/home_api.dart index c1e67add..40692a40 100644 --- a/lib/services/home_api.dart +++ b/lib/services/home_api.dart @@ -3,14 +3,20 @@ import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/utils/constants/api_const.dart'; class HomeApi { - Future fetchUserInfo(userId) async { - final response = await HTTPService().get( - path: ApiEndpoints.getUser.replaceAll('{userUuid}', userId!), + Future fetchUserInfo(String userId) async { + try { + final response = await HTTPService().get( + path: ApiEndpoints.getUser.replaceAll('{userUuid}', userId), showServerMessage: true, expectedResponseModel: (json) { - return UserModel.fromJson(json); - }); - return response; + final user = UserModel.fromJson(json as Map); + return user; + }, + ); + return response; + } catch (e) { + return null; + } } Future fetchTerms() async { From b0aea94b911fb78fc2e717a02c992ec1ad6928cc Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 15:20:44 +0300 Subject: [PATCH 02/18] Created communities blocs, services, models, and params. --- .../services/remote_communities_service.dart | 20 +++++++++++ .../domain/models/community_model.dart | 27 ++++++++++++++ .../domain/models/space_model.dart | 30 ++++++++++++++++ .../domain/params/load_communities_param.dart | 3 ++ .../domain/services/communities_service.dart | 6 ++++ .../presentation/bloc/communities_bloc.dart | 35 +++++++++++++++++++ .../presentation/bloc/communities_event.dart | 17 +++++++++ .../presentation/bloc/communities_state.dart | 30 ++++++++++++++++ 8 files changed, 168 insertions(+) create mode 100644 lib/pages/space_management_v2/modules/communities/data/services/remote_communities_service.dart create mode 100644 lib/pages/space_management_v2/modules/communities/domain/models/community_model.dart create mode 100644 lib/pages/space_management_v2/modules/communities/domain/models/space_model.dart create mode 100644 lib/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart create mode 100644 lib/pages/space_management_v2/modules/communities/domain/services/communities_service.dart create mode 100644 lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart create mode 100644 lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_event.dart create mode 100644 lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart diff --git a/lib/pages/space_management_v2/modules/communities/data/services/remote_communities_service.dart b/lib/pages/space_management_v2/modules/communities/data/services/remote_communities_service.dart new file mode 100644 index 00000000..b6cfa8fc --- /dev/null +++ b/lib/pages/space_management_v2/modules/communities/data/services/remote_communities_service.dart @@ -0,0 +1,20 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/services/communities_service.dart'; +import 'package:syncrow_web/services/api/http_service.dart'; + +class RemoteCommunitiesService implements CommunitiesService { + const RemoteCommunitiesService(this._httpService); + + final HTTPService _httpService; + + @override + Future> getCommunity(LoadCommunitiesParam param) async { + return _httpService.get( + path: '/api/communities/', + expectedResponseModel: (json) => (json as List) + .map((e) => CommunityModel.fromJson(e as Map)) + .toList(), + ); + } +} diff --git a/lib/pages/space_management_v2/modules/communities/domain/models/community_model.dart b/lib/pages/space_management_v2/modules/communities/domain/models/community_model.dart new file mode 100644 index 00000000..c6efad9e --- /dev/null +++ b/lib/pages/space_management_v2/modules/communities/domain/models/community_model.dart @@ -0,0 +1,27 @@ +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/space_model.dart'; + +class CommunityModel extends Equatable { + final String uuid; + final String name; + final List spaces; + + const CommunityModel({ + required this.uuid, + required this.name, + required this.spaces, + }); + + factory CommunityModel.fromJson(Map json) { + return CommunityModel( + uuid: json['uuid'] as String, + name: json['name'] as String, + spaces: (json['spaces'] as List) + .map((e) => SpaceModel.fromJson(e as Map)) + .toList(), + ); + } + + @override + List get props => [uuid, name, spaces]; +} diff --git a/lib/pages/space_management_v2/modules/communities/domain/models/space_model.dart b/lib/pages/space_management_v2/modules/communities/domain/models/space_model.dart new file mode 100644 index 00000000..0f8aadb2 --- /dev/null +++ b/lib/pages/space_management_v2/modules/communities/domain/models/space_model.dart @@ -0,0 +1,30 @@ +import 'package:equatable/equatable.dart'; + +class SpaceModel extends Equatable { + final String uuid; + final String spaceName; + final String icon; + final List children; + + const SpaceModel({ + required this.uuid, + required this.spaceName, + required this.icon, + required this.children, + }); + + factory SpaceModel.fromJson(Map json) { + return SpaceModel( + uuid: json['uuid'] as String, + spaceName: json['spaceName'] as String, + icon: json['icon'] as String, + children: (json['children'] as List?) + ?.map((e) => SpaceModel.fromJson(e as Map)) + .toList() ?? + [], + ); + } + + @override + List get props => [uuid, spaceName, icon, children]; +} diff --git a/lib/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart b/lib/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart new file mode 100644 index 00000000..9bdc215c --- /dev/null +++ b/lib/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart @@ -0,0 +1,3 @@ +class LoadCommunitiesParam { + const LoadCommunitiesParam(); +} diff --git a/lib/pages/space_management_v2/modules/communities/domain/services/communities_service.dart b/lib/pages/space_management_v2/modules/communities/domain/services/communities_service.dart new file mode 100644 index 00000000..bccad2ad --- /dev/null +++ b/lib/pages/space_management_v2/modules/communities/domain/services/communities_service.dart @@ -0,0 +1,6 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart'; + +abstract class CommunitiesService { + Future> getCommunity(LoadCommunitiesParam param); +} diff --git a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart new file mode 100644 index 00000000..dd556f21 --- /dev/null +++ b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart @@ -0,0 +1,35 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/services/communities_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; + +part 'communities_event.dart'; +part 'communities_state.dart'; + +class CommunitiesBloc extends Bloc { + final CommunitiesService _communitiesService; + + CommunitiesBloc({ + required CommunitiesService communitiesService, + }) : _communitiesService = communitiesService, + super(CommunitiesInitial()) { + on(_onGetCommunity); + } + + Future _onGetCommunity( + LoadCommunities event, + Emitter emit, + ) async { + try { + emit(CommunitiesLoading()); + final communities = await _communitiesService.getCommunity(event.param); + emit(CommunitiesLoaded(communities)); + } on APIException catch (e) { + emit(CommunitiesFailure(e.message)); + } catch (e) { + emit(CommunitiesFailure(e.toString())); + } + } +} diff --git a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_event.dart b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_event.dart new file mode 100644 index 00000000..ef375c5a --- /dev/null +++ b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_event.dart @@ -0,0 +1,17 @@ +part of 'communities_bloc.dart'; + +sealed class CommunitiesEvent extends Equatable { + const CommunitiesEvent(); + + @override + List get props => []; +} + +class LoadCommunities extends CommunitiesEvent { + const LoadCommunities(this.param); + + final LoadCommunitiesParam param; + + @override + List get props => [param]; +} diff --git a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart new file mode 100644 index 00000000..910c87e1 --- /dev/null +++ b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart @@ -0,0 +1,30 @@ +part of 'communities_bloc.dart'; + +sealed class CommunitiesState extends Equatable { + const CommunitiesState(); + + @override + List get props => []; +} + +final class CommunitiesInitial extends CommunitiesState {} + +final class CommunitiesLoading extends CommunitiesState {} + +final class CommunitiesLoaded extends CommunitiesState { + final List communities; + + const CommunitiesLoaded(this.communities); + + @override + List get props => [communities]; +} + +final class CommunitiesFailure extends CommunitiesState { + final String message; + + const CommunitiesFailure(this.message); + + @override + List get props => [message]; +} From aa141ef54dc96ba3fcf4340f43756982a0964122 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 15:24:05 +0300 Subject: [PATCH 03/18] Implemented Space details blocs, services, params, and models. --- .../remote_space_details_service.dart | 27 +++ .../domain/models/space_details_model.dart | 166 ++++++++++++++++++ .../domain/params/load_spaces_param.dart | 3 + .../services/space_details_service.dart | 6 + .../presentation/bloc/space_details_bloc.dart | 34 ++++ .../bloc/space_details_event.dart | 17 ++ .../bloc/space_details_state.dart | 30 ++++ 7 files changed, 283 insertions(+) create mode 100644 lib/pages/space_management_v2/modules/space_details/data/services/remote_space_details_service.dart create mode 100644 lib/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart create mode 100644 lib/pages/space_management_v2/modules/space_details/domain/params/load_spaces_param.dart create mode 100644 lib/pages/space_management_v2/modules/space_details/domain/services/space_details_service.dart create mode 100644 lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_bloc.dart create mode 100644 lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_event.dart create mode 100644 lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_state.dart diff --git a/lib/pages/space_management_v2/modules/space_details/data/services/remote_space_details_service.dart b/lib/pages/space_management_v2/modules/space_details/data/services/remote_space_details_service.dart new file mode 100644 index 00000000..5bcc5851 --- /dev/null +++ b/lib/pages/space_management_v2/modules/space_details/data/services/remote_space_details_service.dart @@ -0,0 +1,27 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/params/load_spaces_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/services/space_details_service.dart'; +import 'package:syncrow_web/services/api/http_service.dart'; + +class RemoteSpaceDetailsService implements SpaceDetailsService { + final HTTPService _httpService; + + RemoteSpaceDetailsService({ + required HTTPService httpService, + }) : _httpService = httpService; + + @override + Future getSpaceDetails(LoadSpacesParam param) async { + try { + final response = await _httpService.get( + path: 'endpoint', + expectedResponseModel: (data) { + return SpaceDetailsModel.fromJson(data as Map); + }, + ); + return response; + } catch (e) { + throw Exception('Failed to fetch space details: $e'); + } + } +} diff --git a/lib/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart b/lib/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart new file mode 100644 index 00000000..0d2ea80d --- /dev/null +++ b/lib/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart @@ -0,0 +1,166 @@ +import 'package:equatable/equatable.dart'; + +class SpaceDetailsModel extends Equatable { + final String uuid; + final String spaceName; + final String icon; + final List productAllocations; + final List subspaces; + + const SpaceDetailsModel({ + required this.uuid, + required this.spaceName, + required this.icon, + required this.productAllocations, + required this.subspaces, + }); + + factory SpaceDetailsModel.fromJson(Map json) { + return SpaceDetailsModel( + uuid: json['uuid'] as String, + spaceName: json['spaceName'] as String, + icon: json['icon'] as String, + productAllocations: (json['productAllocations'] as List) + .map((e) => ProductAllocation.fromJson(e as Map)) + .toList(), + subspaces: (json['subspaces'] as List) + .map((e) => Subspace.fromJson(e as Map)) + .toList(), + ); + } + + Map toJson() { + return { + 'uuid': uuid, + 'spaceName': spaceName, + 'icon': icon, + 'productAllocations': productAllocations.map((e) => e.toJson()).toList(), + 'subspaces': subspaces.map((e) => e.toJson()).toList(), + }; + } + + @override + List get props => [uuid, spaceName, icon, productAllocations, subspaces]; +} + +class ProductAllocation extends Equatable { + final Product product; + final Tag tag; + + const ProductAllocation({ + required this.product, + required this.tag, + }); + + factory ProductAllocation.fromJson(Map json) { + return ProductAllocation( + product: Product.fromJson(json['product'] as Map), + tag: Tag.fromJson(json['tag'] as Map), + ); + } + + Map toJson() { + return { + 'product': product.toJson(), + 'tag': tag.toJson(), + }; + } + + @override + List get props => [product, tag]; +} + +class Product extends Equatable { + final String uuid; + final String name; + + const Product({ + required this.uuid, + required this.name, + }); + + factory Product.fromJson(Map json) { + return Product( + uuid: json['uuid'] as String, + name: json['name'] as String, + ); + } + + Map toJson() { + return { + 'uuid': uuid, + 'name': name, + }; + } + + @override + List get props => [uuid, name]; +} + +class Tag extends Equatable { + final String uuid; + final String name; + final String createdAt; + final String updatedAt; + + const Tag({ + required this.uuid, + required this.name, + required this.createdAt, + required this.updatedAt, + }); + + factory Tag.fromJson(Map json) { + return Tag( + uuid: json['uuid'] as String, + name: json['name'] as String, + createdAt: json['createdAt'] as String, + updatedAt: json['updatedAt'] as String, + ); + } + + Map toJson() { + return { + 'uuid': uuid, + 'name': name, + 'createdAt': createdAt, + 'updatedAt': updatedAt, + }; + } + + @override + List get props => [uuid, name, createdAt, updatedAt]; +} + +class Subspace extends Equatable { + final String uuid; + final String name; + final List productAllocations; + + const Subspace({ + required this.uuid, + required this.name, + required this.productAllocations, + }); + + factory Subspace.fromJson(Map json) { + return Subspace( + uuid: json['uuid'] as String, + name: json['name'] as String, + productAllocations: (json['productAllocations'] as List) + .map((e) => ProductAllocation.fromJson(e as Map)) + .toList(), + ); + } + + Map toJson() { + return { + 'uuid': uuid, + 'name': name, + 'productAllocations': productAllocations.map((e) => e.toJson()).toList(), + }; + } + + @override + List get props => [uuid, name, productAllocations]; +} diff --git a/lib/pages/space_management_v2/modules/space_details/domain/params/load_spaces_param.dart b/lib/pages/space_management_v2/modules/space_details/domain/params/load_spaces_param.dart new file mode 100644 index 00000000..5324ed98 --- /dev/null +++ b/lib/pages/space_management_v2/modules/space_details/domain/params/load_spaces_param.dart @@ -0,0 +1,3 @@ +class LoadSpacesParam { + const LoadSpacesParam(); +} diff --git a/lib/pages/space_management_v2/modules/space_details/domain/services/space_details_service.dart b/lib/pages/space_management_v2/modules/space_details/domain/services/space_details_service.dart new file mode 100644 index 00000000..b032560b --- /dev/null +++ b/lib/pages/space_management_v2/modules/space_details/domain/services/space_details_service.dart @@ -0,0 +1,6 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/params/load_spaces_param.dart'; + +abstract class SpaceDetailsService { + Future getSpaceDetails(LoadSpacesParam param); +} diff --git a/lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_bloc.dart b/lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_bloc.dart new file mode 100644 index 00000000..59c1a06d --- /dev/null +++ b/lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_bloc.dart @@ -0,0 +1,34 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/params/load_spaces_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/services/space_details_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; + +part 'space_details_event.dart'; +part 'space_details_state.dart'; + +class SpaceDetailsBloc extends Bloc { + final SpaceDetailsService _spaceDetailsService; + + SpaceDetailsBloc(this._spaceDetailsService) : super(SpaceDetailsInitial()) { + on(_onLoadSpaceDetails); + } + + Future _onLoadSpaceDetails( + LoadSpaceDetails event, + Emitter emit, + ) async { + emit(SpaceDetailsLoading()); + try { + final spaceDetails = await _spaceDetailsService.getSpaceDetails( + event.param, + ); + emit(SpaceDetailsLoaded(spaceDetails)); + } on APIException catch (e) { + emit(SpaceDetailsFailure(e.message)); + } catch (e) { + emit(SpaceDetailsFailure(e.toString())); + } + } +} diff --git a/lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_event.dart b/lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_event.dart new file mode 100644 index 00000000..fe559e26 --- /dev/null +++ b/lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_event.dart @@ -0,0 +1,17 @@ +part of 'space_details_bloc.dart'; + +sealed class SpaceDetailsEvent extends Equatable { + const SpaceDetailsEvent(); + + @override + List get props => []; +} + +class LoadSpaceDetails extends SpaceDetailsEvent { + const LoadSpaceDetails(this.param); + + final LoadSpacesParam param; + + @override + List get props => [param]; +} diff --git a/lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_state.dart b/lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_state.dart new file mode 100644 index 00000000..c7378f89 --- /dev/null +++ b/lib/pages/space_management_v2/modules/space_details/presentation/bloc/space_details_state.dart @@ -0,0 +1,30 @@ +part of 'space_details_bloc.dart'; + +sealed class SpaceDetailsState extends Equatable { + const SpaceDetailsState(); + + @override + List get props => []; +} + +final class SpaceDetailsInitial extends SpaceDetailsState {} + +final class SpaceDetailsLoading extends SpaceDetailsState {} + +final class SpaceDetailsLoaded extends SpaceDetailsState { + final SpaceDetailsModel spaceDetails; + + const SpaceDetailsLoaded(this.spaceDetails); + + @override + List get props => [spaceDetails]; +} + +final class SpaceDetailsFailure extends SpaceDetailsState { + final String message; + + const SpaceDetailsFailure(this.message); + + @override + List get props => [message]; +} From ac44af54a3da5f8a8978c2be5487c5267e18e251 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 15:27:50 +0300 Subject: [PATCH 04/18] Implemented tags bloc, services, models, and params --- .../data/services/remote_tags_service.dart | 51 ++++++++++++++++++ .../shared/tags/domain/models/tag_model.dart | 53 +++++++++++++++++++ .../tags/domain/params/load_tags_param.dart | 5 ++ .../tags/domain/services/tags_service.dart | 6 +++ .../tags/presentation/bloc/tags_bloc.dart | 34 ++++++++++++ .../tags/presentation/bloc/tags_event.dart | 17 ++++++ .../tags/presentation/bloc/tags_state.dart | 30 +++++++++++ 7 files changed, 196 insertions(+) create mode 100644 lib/pages/space_management_v2/shared/tags/data/services/remote_tags_service.dart create mode 100644 lib/pages/space_management_v2/shared/tags/domain/models/tag_model.dart create mode 100644 lib/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart create mode 100644 lib/pages/space_management_v2/shared/tags/domain/services/tags_service.dart create mode 100644 lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_bloc.dart create mode 100644 lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_event.dart create mode 100644 lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_state.dart diff --git a/lib/pages/space_management_v2/shared/tags/data/services/remote_tags_service.dart b/lib/pages/space_management_v2/shared/tags/data/services/remote_tags_service.dart new file mode 100644 index 00000000..c72cc759 --- /dev/null +++ b/lib/pages/space_management_v2/shared/tags/data/services/remote_tags_service.dart @@ -0,0 +1,51 @@ +import 'package:dio/dio.dart'; +import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/models/tag_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/services/tags_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; +import 'package:syncrow_web/services/api/http_service.dart'; +import 'package:syncrow_web/utils/constants/api_const.dart'; + +final class RemoteTagsService implements TagsService { + const RemoteTagsService(this._httpService); + + final HTTPService _httpService; + + static const _defaultErrorMessage = 'Failed to load tags'; + + @override + Future> loadTags(LoadTagsParam param) async { + if (param.projectUuid == null) { + throw Exception('Project UUID is required'); + } + + try { + final response = await _httpService.get( + path: ApiEndpoints.listTags.replaceAll( + '{projectUuid}', + param.projectUuid!, + ), + expectedResponseModel: (json) { + final result = json as Map; + final data = result['data'] as List; + return data + .map((e) => TagModel.fromJson(e as Map)) + .toList(); + }, + ); + return response; + } on DioException catch (e) { + final message = e.response?.data as Map?; + final error = message?['error'] as Map?; + final errorMessage = error?['error'] as String? ?? ''; + final formattedErrorMessage = [ + _defaultErrorMessage, + errorMessage, + ].join(': '); + throw APIException(formattedErrorMessage); + } catch (e) { + final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': '); + throw APIException(formattedErrorMessage); + } + } +} diff --git a/lib/pages/space_management_v2/shared/tags/domain/models/tag_model.dart b/lib/pages/space_management_v2/shared/tags/domain/models/tag_model.dart new file mode 100644 index 00000000..108aa6b2 --- /dev/null +++ b/lib/pages/space_management_v2/shared/tags/domain/models/tag_model.dart @@ -0,0 +1,53 @@ +import 'package:equatable/equatable.dart'; +import 'package:uuid/uuid.dart'; + +class TagModel extends Equatable { + const TagModel({ + required this.uuid, + required this.tag, + required this.internalId, + required this.location, + }); + + final String? uuid; + final String? tag; + final String? internalId; + final String? location; + + factory TagModel.fromJson(Map json) { + final internalId = json['internalId'] as String? ?? const Uuid().v4(); + final tag = json['tag'] as Map?; + final name = json['name'] as String?; + + return TagModel( + uuid: name != null ? json['uuid'] as String? : tag?['uuid'] as String?, + internalId: internalId, + tag: name ?? tag?['name'] as String?, + location: json['location'] as String?, + ); + } + + TagModel copyWith({ + String? uuid, + String? tag, + String? location, + String? internalId, + }) { + return TagModel( + uuid: uuid ?? this.uuid, + tag: tag ?? this.tag, + location: location ?? this.location, + internalId: internalId ?? this.internalId, + ); + } + + Map toJson() { + return { + if (uuid != null) 'uuid': uuid, + 'name': tag, + }; + } + + @override + List get props => [uuid, tag, internalId, location]; +} diff --git a/lib/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart b/lib/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart new file mode 100644 index 00000000..00bc341e --- /dev/null +++ b/lib/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart @@ -0,0 +1,5 @@ +class LoadTagsParam { + final String? projectUuid; + + const LoadTagsParam({this.projectUuid}); +} diff --git a/lib/pages/space_management_v2/shared/tags/domain/services/tags_service.dart b/lib/pages/space_management_v2/shared/tags/domain/services/tags_service.dart new file mode 100644 index 00000000..49206e11 --- /dev/null +++ b/lib/pages/space_management_v2/shared/tags/domain/services/tags_service.dart @@ -0,0 +1,6 @@ +import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/models/tag_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart'; + +abstract interface class TagsService { + Future> loadTags(LoadTagsParam param); +} diff --git a/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_bloc.dart b/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_bloc.dart new file mode 100644 index 00000000..61bb2838 --- /dev/null +++ b/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_bloc.dart @@ -0,0 +1,34 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/models/tag_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/services/tags_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; + +part 'tags_event.dart'; +part 'tags_state.dart'; + +class TagsBloc extends Bloc { + final TagsService _tagsService; + + TagsBloc(this._tagsService) : super(TagsInitial()) { + on(_onLoadTags); + } + + Future _onLoadTags( + LoadTags event, + Emitter emit, + ) async { + emit(TagsLoading()); + try { + final tags = await _tagsService.loadTags( + event.param, + ); + emit(TagsLoaded(tags)); + } on APIException catch (e) { + emit(TagsFailure(e.message)); + } catch (e) { + emit(TagsFailure(e.toString())); + } + } +} diff --git a/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_event.dart b/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_event.dart new file mode 100644 index 00000000..99134cab --- /dev/null +++ b/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_event.dart @@ -0,0 +1,17 @@ +part of 'tags_bloc.dart'; + +abstract class TagsEvent extends Equatable { + const TagsEvent(); + + @override + List get props => []; +} + +class LoadTags extends TagsEvent { + final LoadTagsParam param; + + const LoadTags(this.param); + + @override + List get props => [param]; +} diff --git a/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_state.dart b/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_state.dart new file mode 100644 index 00000000..d6a13c6d --- /dev/null +++ b/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_state.dart @@ -0,0 +1,30 @@ +part of 'tags_bloc.dart'; + +abstract class TagsState extends Equatable { + const TagsState(); + + @override + List get props => []; +} + +class TagsInitial extends TagsState {} + +class TagsLoading extends TagsState {} + +class TagsLoaded extends TagsState { + final List tags; + + const TagsLoaded(this.tags); + + @override + List get props => [tags]; +} + +class TagsFailure extends TagsState { + final String message; + + const TagsFailure(this.message); + + @override + List get props => [message]; +} From 2108622b5b8b7f77269d32dc75f6850b1d28145c Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 15:35:12 +0300 Subject: [PATCH 05/18] moved tags into `modules` folder. --- .../tags/data/services/remote_tags_service.dart | 6 +++--- .../{shared => modules}/tags/domain/models/tag_model.dart | 0 .../tags/domain/params/load_tags_param.dart | 0 .../modules/tags/domain/services/tags_service.dart | 6 ++++++ .../tags/presentation/bloc/tags_bloc.dart | 6 +++--- .../tags/presentation/bloc/tags_event.dart | 0 .../tags/presentation/bloc/tags_state.dart | 0 .../shared/tags/domain/services/tags_service.dart | 6 ------ 8 files changed, 12 insertions(+), 12 deletions(-) rename lib/pages/space_management_v2/{shared => modules}/tags/data/services/remote_tags_service.dart (84%) rename lib/pages/space_management_v2/{shared => modules}/tags/domain/models/tag_model.dart (100%) rename lib/pages/space_management_v2/{shared => modules}/tags/domain/params/load_tags_param.dart (100%) create mode 100644 lib/pages/space_management_v2/modules/tags/domain/services/tags_service.dart rename lib/pages/space_management_v2/{shared => modules}/tags/presentation/bloc/tags_bloc.dart (70%) rename lib/pages/space_management_v2/{shared => modules}/tags/presentation/bloc/tags_event.dart (100%) rename lib/pages/space_management_v2/{shared => modules}/tags/presentation/bloc/tags_state.dart (100%) delete mode 100644 lib/pages/space_management_v2/shared/tags/domain/services/tags_service.dart diff --git a/lib/pages/space_management_v2/shared/tags/data/services/remote_tags_service.dart b/lib/pages/space_management_v2/modules/tags/data/services/remote_tags_service.dart similarity index 84% rename from lib/pages/space_management_v2/shared/tags/data/services/remote_tags_service.dart rename to lib/pages/space_management_v2/modules/tags/data/services/remote_tags_service.dart index c72cc759..b97077f5 100644 --- a/lib/pages/space_management_v2/shared/tags/data/services/remote_tags_service.dart +++ b/lib/pages/space_management_v2/modules/tags/data/services/remote_tags_service.dart @@ -1,7 +1,7 @@ import 'package:dio/dio.dart'; -import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/models/tag_model.dart'; -import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart'; -import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/services/tags_service.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/params/load_tags_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/services/tags_service.dart'; import 'package:syncrow_web/services/api/api_exception.dart'; import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/utils/constants/api_const.dart'; diff --git a/lib/pages/space_management_v2/shared/tags/domain/models/tag_model.dart b/lib/pages/space_management_v2/modules/tags/domain/models/tag_model.dart similarity index 100% rename from lib/pages/space_management_v2/shared/tags/domain/models/tag_model.dart rename to lib/pages/space_management_v2/modules/tags/domain/models/tag_model.dart diff --git a/lib/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart b/lib/pages/space_management_v2/modules/tags/domain/params/load_tags_param.dart similarity index 100% rename from lib/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart rename to lib/pages/space_management_v2/modules/tags/domain/params/load_tags_param.dart diff --git a/lib/pages/space_management_v2/modules/tags/domain/services/tags_service.dart b/lib/pages/space_management_v2/modules/tags/domain/services/tags_service.dart new file mode 100644 index 00000000..a143743d --- /dev/null +++ b/lib/pages/space_management_v2/modules/tags/domain/services/tags_service.dart @@ -0,0 +1,6 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/params/load_tags_param.dart'; + +abstract interface class TagsService { + Future> loadTags(LoadTagsParam param); +} diff --git a/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_bloc.dart b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart similarity index 70% rename from lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_bloc.dart rename to lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart index 61bb2838..0185818d 100644 --- a/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_bloc.dart +++ b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart @@ -1,8 +1,8 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/models/tag_model.dart'; -import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart'; -import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/services/tags_service.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/params/load_tags_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/services/tags_service.dart'; import 'package:syncrow_web/services/api/api_exception.dart'; part 'tags_event.dart'; diff --git a/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_event.dart b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_event.dart similarity index 100% rename from lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_event.dart rename to lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_event.dart diff --git a/lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_state.dart b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_state.dart similarity index 100% rename from lib/pages/space_management_v2/shared/tags/presentation/bloc/tags_state.dart rename to lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_state.dart diff --git a/lib/pages/space_management_v2/shared/tags/domain/services/tags_service.dart b/lib/pages/space_management_v2/shared/tags/domain/services/tags_service.dart deleted file mode 100644 index 49206e11..00000000 --- a/lib/pages/space_management_v2/shared/tags/domain/services/tags_service.dart +++ /dev/null @@ -1,6 +0,0 @@ -import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/models/tag_model.dart'; -import 'package:syncrow_web/pages/space_management_v2/shared/tags/domain/params/load_tags_param.dart'; - -abstract interface class TagsService { - Future> loadTags(LoadTagsParam param); -} From 3eb38d28f74961ae1dfdcd422860a441ff452559 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 15:39:40 +0300 Subject: [PATCH 06/18] Implemented devices bloc, service, param and model. --- .../data/services/remote_device_service.dart | 47 +++++++++++ .../devices/domain/models/device_model.dart | 82 +++++++++++++++++++ .../domain/params/load_devices_param.dart | 11 +++ .../domain/services/device_service.dart | 6 ++ .../presentation/bloc/device_bloc.dart | 32 ++++++++ .../presentation/bloc/device_event.dart | 17 ++++ .../presentation/bloc/device_state.dart | 30 +++++++ 7 files changed, 225 insertions(+) create mode 100644 lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart create mode 100644 lib/pages/space_management_v2/modules/devices/domain/models/device_model.dart create mode 100644 lib/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart create mode 100644 lib/pages/space_management_v2/modules/devices/domain/services/device_service.dart create mode 100644 lib/pages/space_management_v2/modules/devices/presentation/bloc/device_bloc.dart create mode 100644 lib/pages/space_management_v2/modules/devices/presentation/bloc/device_event.dart create mode 100644 lib/pages/space_management_v2/modules/devices/presentation/bloc/device_state.dart diff --git a/lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart b/lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart new file mode 100644 index 00000000..88760222 --- /dev/null +++ b/lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart @@ -0,0 +1,47 @@ +import 'package:dio/dio.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/models/device_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/services/device_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; +import 'package:syncrow_web/services/api/http_service.dart'; + +class RemoteDeviceService implements DeviceService { + final HTTPService _httpService; + + RemoteDeviceService({ + required HTTPService httpService, + }) : _httpService = httpService; + + static const _defaultErrorMessage = 'Failed to load devices'; + + @override + Future> getDevices(LoadDevicesParam param) async { + try { + final response = await _httpService.get( + path: 'devices', + queryParameters: { + 'spaceUuid': param.spaceUuid, + if (param.type != null) 'type': param.type, + if (param.status != null) 'status': param.status, + }, + expectedResponseModel: (data) { + return (data as List) + .map((e) => DeviceModel.fromJson(e as Map)) + .toList(); + }, + ); + return response; + } on DioException catch (e) { + final message = e.response?.data as Map?; + final error = message?['error'] as Map?; + final errorMessage = error?['error'] as String? ?? ''; + final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join( + ': ', + ); + throw APIException(formattedErrorMessage); + } catch (e) { + final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': '); + throw APIException(formattedErrorMessage); + } + } +} diff --git a/lib/pages/space_management_v2/modules/devices/domain/models/device_model.dart b/lib/pages/space_management_v2/modules/devices/domain/models/device_model.dart new file mode 100644 index 00000000..3ddb4eea --- /dev/null +++ b/lib/pages/space_management_v2/modules/devices/domain/models/device_model.dart @@ -0,0 +1,82 @@ +import 'package:equatable/equatable.dart'; + +class DeviceModel extends Equatable { + final String uuid; + final String name; + final String type; + final String status; + final String lastSeen; + final String spaceUuid; + final List capabilities; + + const DeviceModel({ + required this.uuid, + required this.name, + required this.type, + required this.status, + required this.lastSeen, + required this.spaceUuid, + required this.capabilities, + }); + + factory DeviceModel.fromJson(Map json) { + return DeviceModel( + uuid: json['uuid'] as String, + name: json['name'] as String, + type: json['type'] as String, + status: json['status'] as String, + lastSeen: json['lastSeen'] as String, + spaceUuid: json['spaceUuid'] as String, + capabilities: (json['capabilities'] as List) + .map((e) => DeviceCapability.fromJson(e as Map)) + .toList(), + ); + } + + Map toJson() { + return { + 'uuid': uuid, + 'name': name, + 'type': type, + 'status': status, + 'lastSeen': lastSeen, + 'spaceUuid': spaceUuid, + 'capabilities': capabilities.map((e) => e.toJson()).toList(), + }; + } + + @override + List get props => + [uuid, name, type, status, lastSeen, spaceUuid, capabilities]; +} + +class DeviceCapability extends Equatable { + final String name; + final String type; + final Map config; + + const DeviceCapability({ + required this.name, + required this.type, + required this.config, + }); + + factory DeviceCapability.fromJson(Map json) { + return DeviceCapability( + name: json['name'] as String, + type: json['type'] as String, + config: json['config'] as Map, + ); + } + + Map toJson() { + return { + 'name': name, + 'type': type, + 'config': config, + }; + } + + @override + List get props => [name, type, config]; +} diff --git a/lib/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart b/lib/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart new file mode 100644 index 00000000..2bd1f1aa --- /dev/null +++ b/lib/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart @@ -0,0 +1,11 @@ +class LoadDevicesParam { + final String spaceUuid; + final String? type; + final String? status; + + const LoadDevicesParam({ + required this.spaceUuid, + this.type, + this.status, + }); +} diff --git a/lib/pages/space_management_v2/modules/devices/domain/services/device_service.dart b/lib/pages/space_management_v2/modules/devices/domain/services/device_service.dart new file mode 100644 index 00000000..9721962d --- /dev/null +++ b/lib/pages/space_management_v2/modules/devices/domain/services/device_service.dart @@ -0,0 +1,6 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/models/device_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart'; + +abstract class DeviceService { + Future> getDevices(LoadDevicesParam param); +} diff --git a/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_bloc.dart b/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_bloc.dart new file mode 100644 index 00000000..cdae542e --- /dev/null +++ b/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_bloc.dart @@ -0,0 +1,32 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/models/device_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/services/device_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; + +part 'device_event.dart'; +part 'device_state.dart'; + +class DeviceBloc extends Bloc { + final DeviceService _deviceService; + + DeviceBloc(this._deviceService) : super(DeviceInitial()) { + on(_onLoadDevices); + } + + Future _onLoadDevices( + LoadDevices event, + Emitter emit, + ) async { + emit(DeviceLoading()); + try { + final devices = await _deviceService.getDevices(event.param); + emit(DeviceLoaded(devices)); + } on APIException catch (e) { + emit(DeviceFailure(e.message)); + } catch (e) { + emit(DeviceFailure(e.toString())); + } + } +} diff --git a/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_event.dart b/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_event.dart new file mode 100644 index 00000000..bec89dee --- /dev/null +++ b/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_event.dart @@ -0,0 +1,17 @@ +part of 'device_bloc.dart'; + +sealed class DeviceEvent extends Equatable { + const DeviceEvent(); + + @override + List get props => []; +} + +final class LoadDevices extends DeviceEvent { + const LoadDevices(this.param); + + final LoadDevicesParam param; + + @override + List get props => [param]; +} diff --git a/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_state.dart b/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_state.dart new file mode 100644 index 00000000..a5c028df --- /dev/null +++ b/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_state.dart @@ -0,0 +1,30 @@ +part of 'device_bloc.dart'; + +sealed class DeviceState extends Equatable { + const DeviceState(); + + @override + List get props => []; +} + +final class DeviceInitial extends DeviceState {} + +final class DeviceLoading extends DeviceState {} + +final class DeviceLoaded extends DeviceState { + final List devices; + + const DeviceLoaded(this.devices); + + @override + List get props => [devices]; +} + +final class DeviceFailure extends DeviceState { + final String message; + + const DeviceFailure(this.message); + + @override + List get props => [message]; +} From 519285fa7c8d0905adf4993a5cd6a081c00c529c Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 15:41:18 +0300 Subject: [PATCH 07/18] Implemented proper error handling. --- .../services/remote_communities_service.dart | 26 ++++++++++++++----- .../data/services/remote_device_service.dart | 7 ++--- .../remote_space_details_service.dart | 15 ++++++++++- .../tags/presentation/bloc/tags_bloc.dart | 4 +-- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/lib/pages/space_management_v2/modules/communities/data/services/remote_communities_service.dart b/lib/pages/space_management_v2/modules/communities/data/services/remote_communities_service.dart index b6cfa8fc..36682bb4 100644 --- a/lib/pages/space_management_v2/modules/communities/data/services/remote_communities_service.dart +++ b/lib/pages/space_management_v2/modules/communities/data/services/remote_communities_service.dart @@ -1,6 +1,8 @@ +import 'package:dio/dio.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/services/communities_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; import 'package:syncrow_web/services/api/http_service.dart'; class RemoteCommunitiesService implements CommunitiesService { @@ -8,13 +10,25 @@ class RemoteCommunitiesService implements CommunitiesService { final HTTPService _httpService; + static const _defaultErrorMessage = 'Failed to load communities'; + @override Future> getCommunity(LoadCommunitiesParam param) async { - return _httpService.get( - path: '/api/communities/', - expectedResponseModel: (json) => (json as List) - .map((e) => CommunityModel.fromJson(e as Map)) - .toList(), - ); + try { + return _httpService.get( + path: '/api/communities/', + expectedResponseModel: (json) => (json as List) + .map((e) => CommunityModel.fromJson(e as Map)) + .toList(), + ); + } on DioException catch (e) { + final message = e.response?.data as Map?; + final error = message?['error'] as Map?; + final errorMessage = error?['error'] as String? ?? ''; + throw APIException(errorMessage); + } catch (e) { + final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': '); + throw APIException(formattedErrorMessage); + } } } diff --git a/lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart b/lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart index 88760222..df1a9f76 100644 --- a/lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart +++ b/lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart @@ -35,9 +35,10 @@ class RemoteDeviceService implements DeviceService { final message = e.response?.data as Map?; final error = message?['error'] as Map?; final errorMessage = error?['error'] as String? ?? ''; - final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join( - ': ', - ); + final formattedErrorMessage = [ + _defaultErrorMessage, + errorMessage, + ].join(': '); throw APIException(formattedErrorMessage); } catch (e) { final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': '); diff --git a/lib/pages/space_management_v2/modules/space_details/data/services/remote_space_details_service.dart b/lib/pages/space_management_v2/modules/space_details/data/services/remote_space_details_service.dart index 5bcc5851..2e999361 100644 --- a/lib/pages/space_management_v2/modules/space_details/data/services/remote_space_details_service.dart +++ b/lib/pages/space_management_v2/modules/space_details/data/services/remote_space_details_service.dart @@ -1,6 +1,8 @@ +import 'package:dio/dio.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/params/load_spaces_param.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/services/space_details_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; import 'package:syncrow_web/services/api/http_service.dart'; class RemoteSpaceDetailsService implements SpaceDetailsService { @@ -10,6 +12,8 @@ class RemoteSpaceDetailsService implements SpaceDetailsService { required HTTPService httpService, }) : _httpService = httpService; + static const _defaultErrorMessage = 'Failed to load space details'; + @override Future getSpaceDetails(LoadSpacesParam param) async { try { @@ -20,8 +24,17 @@ class RemoteSpaceDetailsService implements SpaceDetailsService { }, ); return response; + } on DioException catch (e) { + final message = e.response?.data as Map?; + final error = message?['error'] as Map?; + final errorMessage = error?['error'] as String? ?? ''; + final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join( + ': ', + ); + throw APIException(formattedErrorMessage); } catch (e) { - throw Exception('Failed to fetch space details: $e'); + final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': '); + throw APIException(formattedErrorMessage); } } } diff --git a/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart index 0185818d..b4091478 100644 --- a/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart +++ b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart @@ -21,9 +21,7 @@ class TagsBloc extends Bloc { ) async { emit(TagsLoading()); try { - final tags = await _tagsService.loadTags( - event.param, - ); + final tags = await _tagsService.loadTags(event.param); emit(TagsLoaded(tags)); } on APIException catch (e) { emit(TagsFailure(e.message)); From 6b76827f21e90ab7172752c411ab863acbad440f Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 15:48:16 +0300 Subject: [PATCH 08/18] Created update space service, and bloc. --- .../services/remote_update_space_service.dart | 40 +++++++++++++++++++ .../domain/services/update_space_service.dart | 5 +++ .../presentation/bloc/update_space_bloc.dart | 31 ++++++++++++++ .../presentation/bloc/update_space_event.dart | 17 ++++++++ .../presentation/bloc/update_space_state.dart | 30 ++++++++++++++ 5 files changed, 123 insertions(+) create mode 100644 lib/pages/space_management_v2/modules/update_space/data/services/remote_update_space_service.dart create mode 100644 lib/pages/space_management_v2/modules/update_space/domain/services/update_space_service.dart create mode 100644 lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_bloc.dart create mode 100644 lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_event.dart create mode 100644 lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_state.dart diff --git a/lib/pages/space_management_v2/modules/update_space/data/services/remote_update_space_service.dart b/lib/pages/space_management_v2/modules/update_space/data/services/remote_update_space_service.dart new file mode 100644 index 00000000..b15e6095 --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_space/data/services/remote_update_space_service.dart @@ -0,0 +1,40 @@ +import 'package:dio/dio.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/update_space/domain/services/update_space_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; +import 'package:syncrow_web/services/api/http_service.dart'; + +class RemoteUpdateSpaceService implements UpdateSpaceService { + const RemoteUpdateSpaceService(this._httpService); + + final HTTPService _httpService; + + static const _defaultErrorMessage = 'Failed to update space'; + + @override + Future updateSpace(SpaceDetailsModel space) async { + try { + final response = await _httpService.put( + path: 'endpoint', + body: space.toJson(), + expectedResponseModel: (data) => SpaceDetailsModel.fromJson( + data as Map, + ), + ); + + return response; + } on DioException catch (e) { + final message = e.response?.data as Map?; + final error = message?['error'] as Map?; + final errorMessage = error?['error'] as String? ?? ''; + final formattedErrorMessage = [ + _defaultErrorMessage, + errorMessage, + ].join(': '); + throw APIException(formattedErrorMessage); + } catch (e) { + final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': '); + throw APIException(formattedErrorMessage); + } + } +} diff --git a/lib/pages/space_management_v2/modules/update_space/domain/services/update_space_service.dart b/lib/pages/space_management_v2/modules/update_space/domain/services/update_space_service.dart new file mode 100644 index 00000000..29bc9419 --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_space/domain/services/update_space_service.dart @@ -0,0 +1,5 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart'; + +abstract class UpdateSpaceService { + Future updateSpace(SpaceDetailsModel space); +} diff --git a/lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_bloc.dart b/lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_bloc.dart new file mode 100644 index 00000000..3bc4e187 --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_bloc.dart @@ -0,0 +1,31 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/update_space/domain/services/update_space_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; + +part 'update_space_event.dart'; +part 'update_space_state.dart'; + +class UpdateSpaceBloc extends Bloc { + final UpdateSpaceService _updateSpaceService; + + UpdateSpaceBloc(this._updateSpaceService) : super(UpdateSpaceInitial()) { + on(_onUpdateSpace); + } + + Future _onUpdateSpace( + UpdateSpace event, + Emitter emit, + ) async { + emit(UpdateSpaceLoading()); + try { + final updatedSpace = await _updateSpaceService.updateSpace(event.space); + emit(UpdateSpaceSuccess(updatedSpace)); + } on APIException catch (e) { + emit(UpdateSpaceFailure(e.message)); + } catch (e) { + emit(UpdateSpaceFailure(e.toString())); + } + } +} diff --git a/lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_event.dart b/lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_event.dart new file mode 100644 index 00000000..b7d476af --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_event.dart @@ -0,0 +1,17 @@ +part of 'update_space_bloc.dart'; + +sealed class UpdateSpaceEvent extends Equatable { + const UpdateSpaceEvent(); + + @override + List get props => []; +} + +final class UpdateSpace extends UpdateSpaceEvent { + const UpdateSpace(this.space); + + final SpaceDetailsModel space; + + @override + List get props => [space]; +} diff --git a/lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_state.dart b/lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_state.dart new file mode 100644 index 00000000..f0bc5a2b --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_space/presentation/bloc/update_space_state.dart @@ -0,0 +1,30 @@ +part of 'update_space_bloc.dart'; + +sealed class UpdateSpaceState extends Equatable { + const UpdateSpaceState(); + + @override + List get props => []; +} + +final class UpdateSpaceInitial extends UpdateSpaceState {} + +final class UpdateSpaceLoading extends UpdateSpaceState {} + +final class UpdateSpaceSuccess extends UpdateSpaceState { + final SpaceDetailsModel space; + + const UpdateSpaceSuccess(this.space); + + @override + List get props => [space]; +} + +final class UpdateSpaceFailure extends UpdateSpaceState { + final String message; + + const UpdateSpaceFailure(this.message); + + @override + List get props => [message]; +} From 6bcfb77a06c82f9939502f51966c79cd6753843e Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 16:01:01 +0300 Subject: [PATCH 09/18] Created update community bloc, services, and param. --- .../remote_update_community_service.dart | 39 +++++++++++++++++++ .../domain/params/update_community_param.dart | 10 +++++ .../services/update_community_service.dart | 6 +++ .../bloc/update_community_bloc.dart | 36 +++++++++++++++++ .../bloc/update_community_event.dart | 17 ++++++++ .../bloc/update_community_state.dart | 30 ++++++++++++++ 6 files changed, 138 insertions(+) create mode 100644 lib/pages/space_management_v2/modules/update_community/data/services/remote_update_community_service.dart create mode 100644 lib/pages/space_management_v2/modules/update_community/domain/params/update_community_param.dart create mode 100644 lib/pages/space_management_v2/modules/update_community/domain/services/update_community_service.dart create mode 100644 lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_bloc.dart create mode 100644 lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_event.dart create mode 100644 lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_state.dart diff --git a/lib/pages/space_management_v2/modules/update_community/data/services/remote_update_community_service.dart b/lib/pages/space_management_v2/modules/update_community/data/services/remote_update_community_service.dart new file mode 100644 index 00000000..6c550673 --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_community/data/services/remote_update_community_service.dart @@ -0,0 +1,39 @@ +import 'package:dio/dio.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/update_community/domain/params/update_community_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/update_community/domain/services/update_community_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; +import 'package:syncrow_web/services/api/http_service.dart'; + +class RemoteUpdateCommunityService implements UpdateCommunityService { + const RemoteUpdateCommunityService(this._httpService); + + final HTTPService _httpService; + + static const _defaultErrorMessage = 'Failed to update community'; + + @override + Future updateCommunity(UpdateCommunityParam param) async { + try { + final response = await _httpService.put( + path: 'endpoint', + expectedResponseModel: (data) => CommunityModel.fromJson( + data as Map, + ), + ); + return response; + } on DioException catch (e) { + final message = e.response?.data as Map?; + final error = message?['error'] as Map?; + final errorMessage = error?['error'] as String? ?? ''; + final formattedErrorMessage = [ + _defaultErrorMessage, + errorMessage, + ].join(': '); + throw APIException(formattedErrorMessage); + } catch (e) { + final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': '); + throw APIException(formattedErrorMessage); + } + } +} diff --git a/lib/pages/space_management_v2/modules/update_community/domain/params/update_community_param.dart b/lib/pages/space_management_v2/modules/update_community/domain/params/update_community_param.dart new file mode 100644 index 00000000..69dfc4e2 --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_community/domain/params/update_community_param.dart @@ -0,0 +1,10 @@ +import 'package:equatable/equatable.dart'; + +class UpdateCommunityParam extends Equatable { + const UpdateCommunityParam({required this.name}); + + final String name; + + @override + List get props => [name]; +} diff --git a/lib/pages/space_management_v2/modules/update_community/domain/services/update_community_service.dart b/lib/pages/space_management_v2/modules/update_community/domain/services/update_community_service.dart new file mode 100644 index 00000000..9703fdc6 --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_community/domain/services/update_community_service.dart @@ -0,0 +1,6 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/update_community/domain/params/update_community_param.dart'; + +abstract class UpdateCommunityService { + Future updateCommunity(UpdateCommunityParam param); +} diff --git a/lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_bloc.dart b/lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_bloc.dart new file mode 100644 index 00000000..4e913c22 --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_bloc.dart @@ -0,0 +1,36 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/update_community/domain/params/update_community_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/update_community/domain/services/update_community_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; + +part 'update_community_event.dart'; +part 'update_community_state.dart'; + +class UpdateCommunityBloc extends Bloc { + final UpdateCommunityService _updateCommunityService; + + UpdateCommunityBloc( + this._updateCommunityService, + ) : super(UpdateCommunityInitial()) { + on(_onUpdateCommunity); + } + + Future _onUpdateCommunity( + UpdateCommunity event, + Emitter emit, + ) async { + emit(UpdateCommunityLoading()); + try { + final updatedCommunity = await _updateCommunityService.updateCommunity( + event.param, + ); + emit(UpdateCommunitySuccess(updatedCommunity)); + } on APIException catch (e) { + emit(UpdateCommunityFailure(e.message)); + } catch (e) { + emit(UpdateCommunityFailure(e.toString())); + } + } +} diff --git a/lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_event.dart b/lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_event.dart new file mode 100644 index 00000000..234298a0 --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_event.dart @@ -0,0 +1,17 @@ +part of 'update_community_bloc.dart'; + +sealed class UpdateCommunityEvent extends Equatable { + const UpdateCommunityEvent(); + + @override + List get props => []; +} + +final class UpdateCommunity extends UpdateCommunityEvent { + const UpdateCommunity(this.param); + + final UpdateCommunityParam param; + + @override + List get props => [param]; +} diff --git a/lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_state.dart b/lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_state.dart new file mode 100644 index 00000000..9126be0a --- /dev/null +++ b/lib/pages/space_management_v2/modules/update_community/presentation/bloc/update_community_state.dart @@ -0,0 +1,30 @@ +part of 'update_community_bloc.dart'; + +sealed class UpdateCommunityState extends Equatable { + const UpdateCommunityState(); + + @override + List get props => []; +} + +final class UpdateCommunityInitial extends UpdateCommunityState {} + +final class UpdateCommunityLoading extends UpdateCommunityState {} + +final class UpdateCommunitySuccess extends UpdateCommunityState { + final CommunityModel community; + + const UpdateCommunitySuccess(this.community); + + @override + List get props => [community]; +} + +final class UpdateCommunityFailure extends UpdateCommunityState { + final String message; + + const UpdateCommunityFailure(this.message); + + @override + List get props => [message]; +} From 737762bbaf57a731a09dbe6d8268a07dae83d4af Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 16:01:09 +0300 Subject: [PATCH 10/18] Created create community bloc, services, and param. --- .../remote_create_community_service.dart | 39 +++++++++++++++++++ .../domain/param/create_community_param.dart | 10 +++++ .../services/create_community_service.dart | 6 +++ .../bloc/create_community_bloc.dart | 36 +++++++++++++++++ .../bloc/create_community_event.dart | 17 ++++++++ .../bloc/create_community_state.dart | 30 ++++++++++++++ 6 files changed, 138 insertions(+) create mode 100644 lib/pages/space_management_v2/modules/create_community/data/services/remote_create_community_service.dart create mode 100644 lib/pages/space_management_v2/modules/create_community/domain/param/create_community_param.dart create mode 100644 lib/pages/space_management_v2/modules/create_community/domain/services/create_community_service.dart create mode 100644 lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_bloc.dart create mode 100644 lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_event.dart create mode 100644 lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_state.dart diff --git a/lib/pages/space_management_v2/modules/create_community/data/services/remote_create_community_service.dart b/lib/pages/space_management_v2/modules/create_community/data/services/remote_create_community_service.dart new file mode 100644 index 00000000..be83124b --- /dev/null +++ b/lib/pages/space_management_v2/modules/create_community/data/services/remote_create_community_service.dart @@ -0,0 +1,39 @@ +import 'package:dio/dio.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/create_community/domain/param/create_community_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/create_community/domain/services/create_community_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; +import 'package:syncrow_web/services/api/http_service.dart'; + +class RemoteCreateCommunityService implements CreateCommunityService { + const RemoteCreateCommunityService(this._httpService); + + final HTTPService _httpService; + + static const _defaultErrorMessage = 'Failed to create community'; + + @override + Future createCommunity(CreateCommunityParam param) async { + try { + final response = await _httpService.post( + path: 'endpoint', + expectedResponseModel: (data) => CommunityModel.fromJson( + data as Map, + ), + ); + return response; + } on DioException catch (e) { + final message = e.response?.data as Map?; + final error = message?['error'] as Map?; + final errorMessage = error?['error'] as String? ?? ''; + final formattedErrorMessage = [ + _defaultErrorMessage, + errorMessage, + ].join(': '); + throw APIException(formattedErrorMessage); + } catch (e) { + final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': '); + throw APIException(formattedErrorMessage); + } + } +} diff --git a/lib/pages/space_management_v2/modules/create_community/domain/param/create_community_param.dart b/lib/pages/space_management_v2/modules/create_community/domain/param/create_community_param.dart new file mode 100644 index 00000000..3d7c203b --- /dev/null +++ b/lib/pages/space_management_v2/modules/create_community/domain/param/create_community_param.dart @@ -0,0 +1,10 @@ +import 'package:equatable/equatable.dart'; + +class CreateCommunityParam extends Equatable { + const CreateCommunityParam({required this.name}); + + final String name; + + @override + List get props => [name]; +} diff --git a/lib/pages/space_management_v2/modules/create_community/domain/services/create_community_service.dart b/lib/pages/space_management_v2/modules/create_community/domain/services/create_community_service.dart new file mode 100644 index 00000000..ddb1a72d --- /dev/null +++ b/lib/pages/space_management_v2/modules/create_community/domain/services/create_community_service.dart @@ -0,0 +1,6 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/create_community/domain/param/create_community_param.dart'; + +abstract class CreateCommunityService { + Future createCommunity(CreateCommunityParam param); +} diff --git a/lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_bloc.dart b/lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_bloc.dart new file mode 100644 index 00000000..817b1e0e --- /dev/null +++ b/lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_bloc.dart @@ -0,0 +1,36 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/create_community/domain/param/create_community_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/create_community/domain/services/create_community_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; + +part 'create_community_event.dart'; +part 'create_community_state.dart'; + +class CreateCommunityBloc extends Bloc { + final CreateCommunityService _createCommunityService; + + CreateCommunityBloc( + this._createCommunityService, + ) : super(CreateCommunityInitial()) { + on(_onCreateCommunity); + } + + Future _onCreateCommunity( + CreateCommunity event, + Emitter emit, + ) async { + emit(CreateCommunityLoading()); + try { + final createdCommunity = await _createCommunityService.createCommunity( + event.param, + ); + emit(CreateCommunitySuccess(createdCommunity)); + } on APIException catch (e) { + emit(CreateCommunityFailure(e.message)); + } catch (e) { + emit(CreateCommunityFailure(e.toString())); + } + } +} diff --git a/lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_event.dart b/lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_event.dart new file mode 100644 index 00000000..d27c5752 --- /dev/null +++ b/lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_event.dart @@ -0,0 +1,17 @@ +part of 'create_community_bloc.dart'; + +sealed class CreateCommunityEvent extends Equatable { + const CreateCommunityEvent(); + + @override + List get props => []; +} + +final class CreateCommunity extends CreateCommunityEvent { + const CreateCommunity(this.param); + + final CreateCommunityParam param; + + @override + List get props => [param]; +} diff --git a/lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_state.dart b/lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_state.dart new file mode 100644 index 00000000..56345aab --- /dev/null +++ b/lib/pages/space_management_v2/modules/create_community/presentation/bloc/create_community_state.dart @@ -0,0 +1,30 @@ +part of 'create_community_bloc.dart'; + +sealed class CreateCommunityState extends Equatable { + const CreateCommunityState(); + + @override + List get props => []; +} + +final class CreateCommunityInitial extends CreateCommunityState {} + +final class CreateCommunityLoading extends CreateCommunityState {} + +final class CreateCommunitySuccess extends CreateCommunityState { + const CreateCommunitySuccess(this.community); + + final CommunityModel community; + + @override + List get props => [community]; +} + +final class CreateCommunityFailure extends CreateCommunityState { + final String message; + + const CreateCommunityFailure(this.message); + + @override + List get props => [message]; +} From 6af96fadbd0c01b1315a7a7271be1d8381dada1d Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 16:39:34 +0300 Subject: [PATCH 11/18] renamed `devices` module, to `products`. --- .../devices/domain/models/device_model.dart | 82 ------------------- .../domain/services/device_service.dart | 6 -- .../presentation/bloc/device_bloc.dart | 32 -------- .../presentation/bloc/device_event.dart | 17 ---- .../presentation/bloc/device_state.dart | 30 ------- .../services/remote_products_service.dart} | 18 ++-- .../products/domain/models/product_model.dart | 21 +++++ .../domain/params/load_products_param.dart} | 4 +- .../domain/services/products_service.dart | 6 ++ .../presentation/bloc/products_bloc.dart | 32 ++++++++ .../presentation/bloc/products_event.dart | 17 ++++ .../presentation/bloc/products_state.dart | 30 +++++++ 12 files changed, 116 insertions(+), 179 deletions(-) delete mode 100644 lib/pages/space_management_v2/modules/devices/domain/models/device_model.dart delete mode 100644 lib/pages/space_management_v2/modules/devices/domain/services/device_service.dart delete mode 100644 lib/pages/space_management_v2/modules/devices/presentation/bloc/device_bloc.dart delete mode 100644 lib/pages/space_management_v2/modules/devices/presentation/bloc/device_event.dart delete mode 100644 lib/pages/space_management_v2/modules/devices/presentation/bloc/device_state.dart rename lib/pages/space_management_v2/modules/{devices/data/services/remote_device_service.dart => products/data/services/remote_products_service.dart} (66%) create mode 100644 lib/pages/space_management_v2/modules/products/domain/models/product_model.dart rename lib/pages/space_management_v2/modules/{devices/domain/params/load_devices_param.dart => products/domain/params/load_products_param.dart} (72%) create mode 100644 lib/pages/space_management_v2/modules/products/domain/services/products_service.dart create mode 100644 lib/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart create mode 100644 lib/pages/space_management_v2/modules/products/presentation/bloc/products_event.dart create mode 100644 lib/pages/space_management_v2/modules/products/presentation/bloc/products_state.dart diff --git a/lib/pages/space_management_v2/modules/devices/domain/models/device_model.dart b/lib/pages/space_management_v2/modules/devices/domain/models/device_model.dart deleted file mode 100644 index 3ddb4eea..00000000 --- a/lib/pages/space_management_v2/modules/devices/domain/models/device_model.dart +++ /dev/null @@ -1,82 +0,0 @@ -import 'package:equatable/equatable.dart'; - -class DeviceModel extends Equatable { - final String uuid; - final String name; - final String type; - final String status; - final String lastSeen; - final String spaceUuid; - final List capabilities; - - const DeviceModel({ - required this.uuid, - required this.name, - required this.type, - required this.status, - required this.lastSeen, - required this.spaceUuid, - required this.capabilities, - }); - - factory DeviceModel.fromJson(Map json) { - return DeviceModel( - uuid: json['uuid'] as String, - name: json['name'] as String, - type: json['type'] as String, - status: json['status'] as String, - lastSeen: json['lastSeen'] as String, - spaceUuid: json['spaceUuid'] as String, - capabilities: (json['capabilities'] as List) - .map((e) => DeviceCapability.fromJson(e as Map)) - .toList(), - ); - } - - Map toJson() { - return { - 'uuid': uuid, - 'name': name, - 'type': type, - 'status': status, - 'lastSeen': lastSeen, - 'spaceUuid': spaceUuid, - 'capabilities': capabilities.map((e) => e.toJson()).toList(), - }; - } - - @override - List get props => - [uuid, name, type, status, lastSeen, spaceUuid, capabilities]; -} - -class DeviceCapability extends Equatable { - final String name; - final String type; - final Map config; - - const DeviceCapability({ - required this.name, - required this.type, - required this.config, - }); - - factory DeviceCapability.fromJson(Map json) { - return DeviceCapability( - name: json['name'] as String, - type: json['type'] as String, - config: json['config'] as Map, - ); - } - - Map toJson() { - return { - 'name': name, - 'type': type, - 'config': config, - }; - } - - @override - List get props => [name, type, config]; -} diff --git a/lib/pages/space_management_v2/modules/devices/domain/services/device_service.dart b/lib/pages/space_management_v2/modules/devices/domain/services/device_service.dart deleted file mode 100644 index 9721962d..00000000 --- a/lib/pages/space_management_v2/modules/devices/domain/services/device_service.dart +++ /dev/null @@ -1,6 +0,0 @@ -import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/models/device_model.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart'; - -abstract class DeviceService { - Future> getDevices(LoadDevicesParam param); -} diff --git a/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_bloc.dart b/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_bloc.dart deleted file mode 100644 index cdae542e..00000000 --- a/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_bloc.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:bloc/bloc.dart'; -import 'package:equatable/equatable.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/models/device_model.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/services/device_service.dart'; -import 'package:syncrow_web/services/api/api_exception.dart'; - -part 'device_event.dart'; -part 'device_state.dart'; - -class DeviceBloc extends Bloc { - final DeviceService _deviceService; - - DeviceBloc(this._deviceService) : super(DeviceInitial()) { - on(_onLoadDevices); - } - - Future _onLoadDevices( - LoadDevices event, - Emitter emit, - ) async { - emit(DeviceLoading()); - try { - final devices = await _deviceService.getDevices(event.param); - emit(DeviceLoaded(devices)); - } on APIException catch (e) { - emit(DeviceFailure(e.message)); - } catch (e) { - emit(DeviceFailure(e.toString())); - } - } -} diff --git a/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_event.dart b/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_event.dart deleted file mode 100644 index bec89dee..00000000 --- a/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_event.dart +++ /dev/null @@ -1,17 +0,0 @@ -part of 'device_bloc.dart'; - -sealed class DeviceEvent extends Equatable { - const DeviceEvent(); - - @override - List get props => []; -} - -final class LoadDevices extends DeviceEvent { - const LoadDevices(this.param); - - final LoadDevicesParam param; - - @override - List get props => [param]; -} diff --git a/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_state.dart b/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_state.dart deleted file mode 100644 index a5c028df..00000000 --- a/lib/pages/space_management_v2/modules/devices/presentation/bloc/device_state.dart +++ /dev/null @@ -1,30 +0,0 @@ -part of 'device_bloc.dart'; - -sealed class DeviceState extends Equatable { - const DeviceState(); - - @override - List get props => []; -} - -final class DeviceInitial extends DeviceState {} - -final class DeviceLoading extends DeviceState {} - -final class DeviceLoaded extends DeviceState { - final List devices; - - const DeviceLoaded(this.devices); - - @override - List get props => [devices]; -} - -final class DeviceFailure extends DeviceState { - final String message; - - const DeviceFailure(this.message); - - @override - List get props => [message]; -} diff --git a/lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart b/lib/pages/space_management_v2/modules/products/data/services/remote_products_service.dart similarity index 66% rename from lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart rename to lib/pages/space_management_v2/modules/products/data/services/remote_products_service.dart index df1a9f76..47b8f6aa 100644 --- a/lib/pages/space_management_v2/modules/devices/data/services/remote_device_service.dart +++ b/lib/pages/space_management_v2/modules/products/data/services/remote_products_service.dart @@ -1,21 +1,19 @@ import 'package:dio/dio.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/models/device_model.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/services/device_service.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/params/load_products_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/services/products_service.dart'; import 'package:syncrow_web/services/api/api_exception.dart'; import 'package:syncrow_web/services/api/http_service.dart'; -class RemoteDeviceService implements DeviceService { - final HTTPService _httpService; +class RemoteProductsService implements ProductsService { + const RemoteProductsService(this._httpService); - RemoteDeviceService({ - required HTTPService httpService, - }) : _httpService = httpService; + final HTTPService _httpService; static const _defaultErrorMessage = 'Failed to load devices'; @override - Future> getDevices(LoadDevicesParam param) async { + Future> getProducts(LoadProductsParam param) async { try { final response = await _httpService.get( path: 'devices', @@ -26,7 +24,7 @@ class RemoteDeviceService implements DeviceService { }, expectedResponseModel: (data) { return (data as List) - .map((e) => DeviceModel.fromJson(e as Map)) + .map((e) => ProductModel.fromJson(e as Map)) .toList(); }, ); diff --git a/lib/pages/space_management_v2/modules/products/domain/models/product_model.dart b/lib/pages/space_management_v2/modules/products/domain/models/product_model.dart new file mode 100644 index 00000000..03a7995c --- /dev/null +++ b/lib/pages/space_management_v2/modules/products/domain/models/product_model.dart @@ -0,0 +1,21 @@ +import 'package:equatable/equatable.dart'; + +class ProductModel extends Equatable { + final String uuid; + final String name; + + const ProductModel({ + required this.uuid, + required this.name, + }); + + factory ProductModel.fromJson(Map json) { + return ProductModel( + uuid: json['uuid'] as String, + name: json['name'] as String, + ); + } + + @override + List get props => [uuid, name]; +} diff --git a/lib/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart b/lib/pages/space_management_v2/modules/products/domain/params/load_products_param.dart similarity index 72% rename from lib/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart rename to lib/pages/space_management_v2/modules/products/domain/params/load_products_param.dart index 2bd1f1aa..87194ae7 100644 --- a/lib/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart +++ b/lib/pages/space_management_v2/modules/products/domain/params/load_products_param.dart @@ -1,9 +1,9 @@ -class LoadDevicesParam { +class LoadProductsParam { final String spaceUuid; final String? type; final String? status; - const LoadDevicesParam({ + const LoadProductsParam({ required this.spaceUuid, this.type, this.status, diff --git a/lib/pages/space_management_v2/modules/products/domain/services/products_service.dart b/lib/pages/space_management_v2/modules/products/domain/services/products_service.dart new file mode 100644 index 00000000..fe9b2850 --- /dev/null +++ b/lib/pages/space_management_v2/modules/products/domain/services/products_service.dart @@ -0,0 +1,6 @@ +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/params/load_products_param.dart'; + +abstract class ProductsService { + Future> getProducts(LoadProductsParam param); +} diff --git a/lib/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart new file mode 100644 index 00000000..a0f227c1 --- /dev/null +++ b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart @@ -0,0 +1,32 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/params/load_products_param.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/services/products_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; + +part 'products_event.dart'; +part 'products_state.dart'; + +class ProductsBloc extends Bloc { + final ProductsService _deviceService; + + ProductsBloc(this._deviceService) : super(ProductsInitial()) { + on(_onLoadDevices); + } + + Future _onLoadDevices( + LoadProducts event, + Emitter emit, + ) async { + emit(ProductsLoading()); + try { + final devices = await _deviceService.getProducts(event.param); + emit(ProductsLoaded(devices)); + } on APIException catch (e) { + emit(ProductsFailure(e.message)); + } catch (e) { + emit(ProductsFailure(e.toString())); + } + } +} diff --git a/lib/pages/space_management_v2/modules/products/presentation/bloc/products_event.dart b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_event.dart new file mode 100644 index 00000000..971b6d27 --- /dev/null +++ b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_event.dart @@ -0,0 +1,17 @@ +part of 'products_bloc.dart'; + +sealed class ProductsEvent extends Equatable { + const ProductsEvent(); + + @override + List get props => []; +} + +final class LoadProducts extends ProductsEvent { + const LoadProducts(this.param); + + final LoadProductsParam param; + + @override + List get props => [param]; +} diff --git a/lib/pages/space_management_v2/modules/products/presentation/bloc/products_state.dart b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_state.dart new file mode 100644 index 00000000..68942282 --- /dev/null +++ b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_state.dart @@ -0,0 +1,30 @@ +part of 'products_bloc.dart'; + +sealed class ProductsState extends Equatable { + const ProductsState(); + + @override + List get props => []; +} + +final class ProductsInitial extends ProductsState {} + +final class ProductsLoading extends ProductsState {} + +final class ProductsLoaded extends ProductsState { + final List devices; + + const ProductsLoaded(this.devices); + + @override + List get props => [devices]; +} + +final class ProductsFailure extends ProductsState { + final String message; + + const ProductsFailure(this.message); + + @override + List get props => [message]; +} From 02605231211b8a5ab9bef0569698e687eba8ff98 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 16:47:47 +0300 Subject: [PATCH 12/18] Made CommunitiesBloc state object one class, instead of multiple, to make searching and pagination easier. --- .../presentation/bloc/communities_bloc.dart | 25 ++++++++++++--- .../presentation/bloc/communities_state.dart | 32 ++++++------------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart index dd556f21..d75f32eb 100644 --- a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart +++ b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart @@ -14,7 +14,7 @@ class CommunitiesBloc extends Bloc { CommunitiesBloc({ required CommunitiesService communitiesService, }) : _communitiesService = communitiesService, - super(CommunitiesInitial()) { + super(const CommunitiesState()) { on(_onGetCommunity); } @@ -23,13 +23,28 @@ class CommunitiesBloc extends Bloc { Emitter emit, ) async { try { - emit(CommunitiesLoading()); + emit(const CommunitiesState(status: CommunitiesStatus.loading)); final communities = await _communitiesService.getCommunity(event.param); - emit(CommunitiesLoaded(communities)); + emit( + CommunitiesState( + status: CommunitiesStatus.success, + communities: communities, + ), + ); } on APIException catch (e) { - emit(CommunitiesFailure(e.message)); + emit( + CommunitiesState( + status: CommunitiesStatus.failure, + errorMessage: e.message, + ), + ); } catch (e) { - emit(CommunitiesFailure(e.toString())); + emit( + CommunitiesState( + status: CommunitiesStatus.failure, + errorMessage: e.toString(), + ), + ); } } } diff --git a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart index 910c87e1..c015cf03 100644 --- a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart +++ b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart @@ -1,30 +1,18 @@ part of 'communities_bloc.dart'; -sealed class CommunitiesState extends Equatable { - const CommunitiesState(); +enum CommunitiesStatus { initial, loading, success, failure } - @override - List get props => []; -} - -final class CommunitiesInitial extends CommunitiesState {} - -final class CommunitiesLoading extends CommunitiesState {} - -final class CommunitiesLoaded extends CommunitiesState { +class CommunitiesState extends Equatable { + final CommunitiesStatus status; final List communities; + final String? errorMessage; - const CommunitiesLoaded(this.communities); + const CommunitiesState({ + this.status = CommunitiesStatus.initial, + this.communities = const [], + this.errorMessage, + }); @override - List get props => [communities]; -} - -final class CommunitiesFailure extends CommunitiesState { - final String message; - - const CommunitiesFailure(this.message); - - @override - List get props => [message]; + List get props => [status, communities, errorMessage]; } From 5cd13840003d2f56f75551971979ddfc333e4adb Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 16:48:08 +0300 Subject: [PATCH 13/18] Refactored CommunitiesBloc to ensure the CommunitiesService is properly defined as a final member, enhancing clarity and maintainability. Adjusted CommunitiesState to maintain consistent property definitions. --- .../communities/presentation/bloc/communities_bloc.dart | 4 ++-- .../communities/presentation/bloc/communities_state.dart | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart index d75f32eb..83b71c1c 100644 --- a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart +++ b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart @@ -9,8 +9,6 @@ part 'communities_event.dart'; part 'communities_state.dart'; class CommunitiesBloc extends Bloc { - final CommunitiesService _communitiesService; - CommunitiesBloc({ required CommunitiesService communitiesService, }) : _communitiesService = communitiesService, @@ -18,6 +16,8 @@ class CommunitiesBloc extends Bloc { on(_onGetCommunity); } + final CommunitiesService _communitiesService; + Future _onGetCommunity( LoadCommunities event, Emitter emit, diff --git a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart index c015cf03..e38a7f15 100644 --- a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart +++ b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart @@ -3,16 +3,16 @@ part of 'communities_bloc.dart'; enum CommunitiesStatus { initial, loading, success, failure } class CommunitiesState extends Equatable { - final CommunitiesStatus status; - final List communities; - final String? errorMessage; - const CommunitiesState({ this.status = CommunitiesStatus.initial, this.communities = const [], this.errorMessage, }); + final CommunitiesStatus status; + final List communities; + final String? errorMessage; + @override List get props => [status, communities, errorMessage]; } From 9600f4fb8b5cd3c080b2676165efeae95b712cb7 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 16 Jun 2025 16:49:31 +0300 Subject: [PATCH 14/18] Made `CommunitiesState` final, to better document that it shouldn't be extended. --- .../communities/presentation/bloc/communities_state.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart index e38a7f15..94740f0b 100644 --- a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart +++ b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_state.dart @@ -2,7 +2,7 @@ part of 'communities_bloc.dart'; enum CommunitiesStatus { initial, loading, success, failure } -class CommunitiesState extends Equatable { +final class CommunitiesState extends Equatable { const CommunitiesState({ this.status = CommunitiesStatus.initial, this.communities = const [], From 01328057134d96f84ef376916cca7c1729237586 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Tue, 17 Jun 2025 11:26:48 +0300 Subject: [PATCH 15/18] Fix PR notes. --- .../presentation/bloc/communities_bloc.dart | 4 +- .../services/remote_products_service.dart | 6 +- .../{product_model.dart => product.dart} | 15 +++-- .../domain/services/products_service.dart | 4 +- .../presentation/bloc/products_bloc.dart | 6 +- .../presentation/bloc/products_state.dart | 6 +- .../domain/models/space_details_model.dart | 66 ++----------------- .../data/services/remote_tags_service.dart | 8 +-- .../modules/tags/domain/models/tag.dart | 36 ++++++++++ .../modules/tags/domain/models/tag_model.dart | 53 --------------- .../tags/domain/services/tags_service.dart | 4 +- .../tags/presentation/bloc/tags_bloc.dart | 2 +- .../tags/presentation/bloc/tags_state.dart | 2 +- 13 files changed, 71 insertions(+), 141 deletions(-) rename lib/pages/space_management_v2/modules/products/domain/models/{product_model.dart => product.dart} (55%) create mode 100644 lib/pages/space_management_v2/modules/tags/domain/models/tag.dart delete mode 100644 lib/pages/space_management_v2/modules/tags/domain/models/tag_model.dart diff --git a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart index 83b71c1c..0d85b22f 100644 --- a/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart +++ b/lib/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart @@ -13,12 +13,12 @@ class CommunitiesBloc extends Bloc { required CommunitiesService communitiesService, }) : _communitiesService = communitiesService, super(const CommunitiesState()) { - on(_onGetCommunity); + on(_onLoadCommunities); } final CommunitiesService _communitiesService; - Future _onGetCommunity( + Future _onLoadCommunities( LoadCommunities event, Emitter emit, ) async { diff --git a/lib/pages/space_management_v2/modules/products/data/services/remote_products_service.dart b/lib/pages/space_management_v2/modules/products/data/services/remote_products_service.dart index 47b8f6aa..6e501b44 100644 --- a/lib/pages/space_management_v2/modules/products/data/services/remote_products_service.dart +++ b/lib/pages/space_management_v2/modules/products/data/services/remote_products_service.dart @@ -1,5 +1,5 @@ import 'package:dio/dio.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/params/load_products_param.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/services/products_service.dart'; import 'package:syncrow_web/services/api/api_exception.dart'; @@ -13,7 +13,7 @@ class RemoteProductsService implements ProductsService { static const _defaultErrorMessage = 'Failed to load devices'; @override - Future> getProducts(LoadProductsParam param) async { + Future> getProducts(LoadProductsParam param) async { try { final response = await _httpService.get( path: 'devices', @@ -24,7 +24,7 @@ class RemoteProductsService implements ProductsService { }, expectedResponseModel: (data) { return (data as List) - .map((e) => ProductModel.fromJson(e as Map)) + .map((e) => Product.fromJson(e as Map)) .toList(); }, ); diff --git a/lib/pages/space_management_v2/modules/products/domain/models/product_model.dart b/lib/pages/space_management_v2/modules/products/domain/models/product.dart similarity index 55% rename from lib/pages/space_management_v2/modules/products/domain/models/product_model.dart rename to lib/pages/space_management_v2/modules/products/domain/models/product.dart index 03a7995c..cd837121 100644 --- a/lib/pages/space_management_v2/modules/products/domain/models/product_model.dart +++ b/lib/pages/space_management_v2/modules/products/domain/models/product.dart @@ -1,21 +1,28 @@ import 'package:equatable/equatable.dart'; -class ProductModel extends Equatable { +class Product extends Equatable { final String uuid; final String name; - const ProductModel({ + const Product({ required this.uuid, required this.name, }); - factory ProductModel.fromJson(Map json) { - return ProductModel( + factory Product.fromJson(Map json) { + return Product( uuid: json['uuid'] as String, name: json['name'] as String, ); } + Map toJson() { + return { + 'uuid': uuid, + 'name': name, + }; + } + @override List get props => [uuid, name]; } diff --git a/lib/pages/space_management_v2/modules/products/domain/services/products_service.dart b/lib/pages/space_management_v2/modules/products/domain/services/products_service.dart index fe9b2850..18554382 100644 --- a/lib/pages/space_management_v2/modules/products/domain/services/products_service.dart +++ b/lib/pages/space_management_v2/modules/products/domain/services/products_service.dart @@ -1,6 +1,6 @@ -import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/params/load_products_param.dart'; abstract class ProductsService { - Future> getProducts(LoadProductsParam param); + Future> getProducts(LoadProductsParam param); } diff --git a/lib/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart index a0f227c1..1ce6ae89 100644 --- a/lib/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart +++ b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart @@ -1,6 +1,6 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/params/load_products_param.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/services/products_service.dart'; import 'package:syncrow_web/services/api/api_exception.dart'; @@ -12,10 +12,10 @@ class ProductsBloc extends Bloc { final ProductsService _deviceService; ProductsBloc(this._deviceService) : super(ProductsInitial()) { - on(_onLoadDevices); + on(_onLoadProducts); } - Future _onLoadDevices( + Future _onLoadProducts( LoadProducts event, Emitter emit, ) async { diff --git a/lib/pages/space_management_v2/modules/products/presentation/bloc/products_state.dart b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_state.dart index 68942282..d5622cd3 100644 --- a/lib/pages/space_management_v2/modules/products/presentation/bloc/products_state.dart +++ b/lib/pages/space_management_v2/modules/products/presentation/bloc/products_state.dart @@ -12,12 +12,12 @@ final class ProductsInitial extends ProductsState {} final class ProductsLoading extends ProductsState {} final class ProductsLoaded extends ProductsState { - final List devices; + final List products; - const ProductsLoaded(this.devices); + const ProductsLoaded(this.products); @override - List get props => [devices]; + List get props => [products]; } final class ProductsFailure extends ProductsState { diff --git a/lib/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart b/lib/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart index 0d2ea80d..891e7eb2 100644 --- a/lib/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart +++ b/lib/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart @@ -1,4 +1,6 @@ import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag.dart'; class SpaceDetailsModel extends Equatable { final String uuid; @@ -46,10 +48,12 @@ class SpaceDetailsModel extends Equatable { class ProductAllocation extends Equatable { final Product product; final Tag tag; + final String? location; const ProductAllocation({ required this.product, required this.tag, + this.location, }); factory ProductAllocation.fromJson(Map json) { @@ -70,68 +74,6 @@ class ProductAllocation extends Equatable { List get props => [product, tag]; } -class Product extends Equatable { - final String uuid; - final String name; - - const Product({ - required this.uuid, - required this.name, - }); - - factory Product.fromJson(Map json) { - return Product( - uuid: json['uuid'] as String, - name: json['name'] as String, - ); - } - - Map toJson() { - return { - 'uuid': uuid, - 'name': name, - }; - } - - @override - List get props => [uuid, name]; -} - -class Tag extends Equatable { - final String uuid; - final String name; - final String createdAt; - final String updatedAt; - - const Tag({ - required this.uuid, - required this.name, - required this.createdAt, - required this.updatedAt, - }); - - factory Tag.fromJson(Map json) { - return Tag( - uuid: json['uuid'] as String, - name: json['name'] as String, - createdAt: json['createdAt'] as String, - updatedAt: json['updatedAt'] as String, - ); - } - - Map toJson() { - return { - 'uuid': uuid, - 'name': name, - 'createdAt': createdAt, - 'updatedAt': updatedAt, - }; - } - - @override - List get props => [uuid, name, createdAt, updatedAt]; -} - class Subspace extends Equatable { final String uuid; final String name; diff --git a/lib/pages/space_management_v2/modules/tags/data/services/remote_tags_service.dart b/lib/pages/space_management_v2/modules/tags/data/services/remote_tags_service.dart index b97077f5..b5545bd3 100644 --- a/lib/pages/space_management_v2/modules/tags/data/services/remote_tags_service.dart +++ b/lib/pages/space_management_v2/modules/tags/data/services/remote_tags_service.dart @@ -1,5 +1,5 @@ import 'package:dio/dio.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/params/load_tags_param.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/services/tags_service.dart'; import 'package:syncrow_web/services/api/api_exception.dart'; @@ -14,7 +14,7 @@ final class RemoteTagsService implements TagsService { static const _defaultErrorMessage = 'Failed to load tags'; @override - Future> loadTags(LoadTagsParam param) async { + Future> loadTags(LoadTagsParam param) async { if (param.projectUuid == null) { throw Exception('Project UUID is required'); } @@ -28,9 +28,7 @@ final class RemoteTagsService implements TagsService { expectedResponseModel: (json) { final result = json as Map; final data = result['data'] as List; - return data - .map((e) => TagModel.fromJson(e as Map)) - .toList(); + return data.map((e) => Tag.fromJson(e as Map)).toList(); }, ); return response; diff --git a/lib/pages/space_management_v2/modules/tags/domain/models/tag.dart b/lib/pages/space_management_v2/modules/tags/domain/models/tag.dart new file mode 100644 index 00000000..1044d888 --- /dev/null +++ b/lib/pages/space_management_v2/modules/tags/domain/models/tag.dart @@ -0,0 +1,36 @@ +import 'package:equatable/equatable.dart'; + +class Tag extends Equatable { + final String uuid; + final String name; + final String createdAt; + final String updatedAt; + + const Tag({ + required this.uuid, + required this.name, + required this.createdAt, + required this.updatedAt, + }); + + factory Tag.fromJson(Map json) { + return Tag( + uuid: json['uuid'] as String, + name: json['name'] as String, + createdAt: json['createdAt'] as String, + updatedAt: json['updatedAt'] as String, + ); + } + + Map toJson() { + return { + 'uuid': uuid, + 'name': name, + 'createdAt': createdAt, + 'updatedAt': updatedAt, + }; + } + + @override + List get props => [uuid, name, createdAt, updatedAt]; +} diff --git a/lib/pages/space_management_v2/modules/tags/domain/models/tag_model.dart b/lib/pages/space_management_v2/modules/tags/domain/models/tag_model.dart deleted file mode 100644 index 108aa6b2..00000000 --- a/lib/pages/space_management_v2/modules/tags/domain/models/tag_model.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:equatable/equatable.dart'; -import 'package:uuid/uuid.dart'; - -class TagModel extends Equatable { - const TagModel({ - required this.uuid, - required this.tag, - required this.internalId, - required this.location, - }); - - final String? uuid; - final String? tag; - final String? internalId; - final String? location; - - factory TagModel.fromJson(Map json) { - final internalId = json['internalId'] as String? ?? const Uuid().v4(); - final tag = json['tag'] as Map?; - final name = json['name'] as String?; - - return TagModel( - uuid: name != null ? json['uuid'] as String? : tag?['uuid'] as String?, - internalId: internalId, - tag: name ?? tag?['name'] as String?, - location: json['location'] as String?, - ); - } - - TagModel copyWith({ - String? uuid, - String? tag, - String? location, - String? internalId, - }) { - return TagModel( - uuid: uuid ?? this.uuid, - tag: tag ?? this.tag, - location: location ?? this.location, - internalId: internalId ?? this.internalId, - ); - } - - Map toJson() { - return { - if (uuid != null) 'uuid': uuid, - 'name': tag, - }; - } - - @override - List get props => [uuid, tag, internalId, location]; -} diff --git a/lib/pages/space_management_v2/modules/tags/domain/services/tags_service.dart b/lib/pages/space_management_v2/modules/tags/domain/services/tags_service.dart index a143743d..ae097020 100644 --- a/lib/pages/space_management_v2/modules/tags/domain/services/tags_service.dart +++ b/lib/pages/space_management_v2/modules/tags/domain/services/tags_service.dart @@ -1,6 +1,6 @@ -import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/params/load_tags_param.dart'; abstract interface class TagsService { - Future> loadTags(LoadTagsParam param); + Future> loadTags(LoadTagsParam param); } diff --git a/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart index b4091478..e51884cb 100644 --- a/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart +++ b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_bloc.dart @@ -1,6 +1,6 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag_model.dart'; +import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/models/tag.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/params/load_tags_param.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/tags/domain/services/tags_service.dart'; import 'package:syncrow_web/services/api/api_exception.dart'; diff --git a/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_state.dart b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_state.dart index d6a13c6d..7afe55c9 100644 --- a/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_state.dart +++ b/lib/pages/space_management_v2/modules/tags/presentation/bloc/tags_state.dart @@ -12,7 +12,7 @@ class TagsInitial extends TagsState {} class TagsLoading extends TagsState {} class TagsLoaded extends TagsState { - final List tags; + final List tags; const TagsLoaded(this.tags); From 5d3380ef82e7b3eba08863c0f0cfdd4af6827a61 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Tue, 17 Jun 2025 14:30:34 +0300 Subject: [PATCH 16/18] fixed merge conflict. --- lib/pages/home/bloc/home_bloc.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/pages/home/bloc/home_bloc.dart b/lib/pages/home/bloc/home_bloc.dart index 7645b03c..c1bcba6a 100644 --- a/lib/pages/home/bloc/home_bloc.dart +++ b/lib/pages/home/bloc/home_bloc.dart @@ -19,11 +19,7 @@ class HomeBloc extends Bloc { String terms = ''; String policy = ''; -<<<<<<< SP-1737-FE-The-user-appears-as-Null-and-the-project-uuid-is-null-when-we-login-in-after-a-credentials-error HomeBloc() : super(HomeInitial()) { -======= - HomeBloc() : super((HomeInitial())) { ->>>>>>> dev on(_fetchUserInfo); on(_fetchTerms); on(_fetchPolicy); From 09f21239460c7a23d7c4a6b1e87a2f43db58e7fc Mon Sep 17 00:00:00 2001 From: raf-dev1 Date: Tue, 17 Jun 2025 16:21:01 +0300 Subject: [PATCH 17/18] bug fixed it is locally change the state now --- .../bloc/routine_bloc/routine_bloc.dart | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart index ca8aac06..f13e24d4 100644 --- a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart @@ -1422,15 +1422,17 @@ class RoutineBloc extends Bloc { event.automationId, event.automationStatusUpdate, projectId); if (success) { - final updatedAutomations = await SceneApi.getAutomationByUnitId( - event.automationStatusUpdate.spaceUuid, - event.communityId, - projectId); + // await SceneApi.getAutomationByUnitId( + // event.automationStatusUpdate.spaceUuid, + // event.communityId, + // projectId); // Remove from loading set safely + final updatedLoadingIds = {...state.loadingAutomationIds!} ..remove(event.automationId); - + final updatedAutomations = changeItemStateOnToggelingSceen( + state.automations, event.automationId); emit(state.copyWith( automations: updatedAutomations, loadingAutomationIds: updatedLoadingIds, @@ -1452,4 +1454,30 @@ class RoutineBloc extends Bloc { )); } } + + List changeItemStateOnToggelingSceen( + List oldSceen, String automationId) { + final updatedAutomations = oldSceen; + final temp = + updatedAutomations.firstWhere((element) => element.id == automationId); + final tempIndex = updatedAutomations.indexWhere( + (element) => element.id == automationId, + ); + updatedAutomations.removeWhere( + (element) => element.id == automationId, + ); + updatedAutomations.insert( + tempIndex, + ScenesModel( + id: temp.id, + name: temp.name, + status: temp.status == 'enable' ? 'disable' : 'enable', + type: temp.type, + spaceName: temp.spaceName, + spaceId: temp.spaceId, + communityId: temp.communityId, + ), + ); + return updatedAutomations; + } } From 1ba1aba54e56a92d839e6dc80653aff4b0d32e3b Mon Sep 17 00:00:00 2001 From: raf-dev1 Date: Wed, 18 Jun 2025 08:42:18 +0300 Subject: [PATCH 18/18] PR fixes and tested --- .../bloc/routine_bloc/routine_bloc.dart | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart index f13e24d4..af015158 100644 --- a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart @@ -1457,27 +1457,21 @@ class RoutineBloc extends Bloc { List changeItemStateOnToggelingSceen( List oldSceen, String automationId) { - final updatedAutomations = oldSceen; - final temp = - updatedAutomations.firstWhere((element) => element.id == automationId); - final tempIndex = updatedAutomations.indexWhere( - (element) => element.id == automationId, - ); - updatedAutomations.removeWhere( - (element) => element.id == automationId, - ); - updatedAutomations.insert( - tempIndex, - ScenesModel( - id: temp.id, - name: temp.name, - status: temp.status == 'enable' ? 'disable' : 'enable', - type: temp.type, - spaceName: temp.spaceName, - spaceId: temp.spaceId, - communityId: temp.communityId, - ), - ); - return updatedAutomations; + return oldSceen.map((scene) { + if (scene.id == automationId) { + return ScenesModel( + id: scene.id, + sceneTuyaId: scene.sceneTuyaId, + name: scene.name, + status: scene.status == 'enable' ? 'disable' : 'enable', + type: scene.type, + spaceName: scene.spaceName, + spaceId: scene.spaceId, + communityId: scene.communityId, + icon: scene.icon, + ); + } + return scene; + }).toList(); } }