From 55de7fab0f35ea5ad3351df162f5afbd0b53492a Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Sat, 15 Feb 2025 00:34:38 +0400 Subject: [PATCH 1/6] Introduced `ProjectCubit` to handle project-related state. --- lib/main.dart | 23 +++++++++++++------- lib/pages/auth/model/project_model.dart | 27 ++++++++++++++++++++++++ lib/pages/common/bloc/project_cubit.dart | 19 +++++++++++++++++ 3 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 lib/pages/auth/model/project_model.dart create mode 100644 lib/pages/common/bloc/project_cubit.dart diff --git a/lib/main.dart b/lib/main.dart index 0bf0b9d3..fe14241e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,8 +2,10 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.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/routine_bloc/routine_bloc.dart'; @@ -17,18 +19,21 @@ 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(); initialSetup(); } catch (_) {} - runApp(MyApp()); + final storage = FlutterSecureStorage(); + final projectCubit = ProjectCubit(storage); + runApp(MyApp(projectCubit: projectCubit)); } class MyApp extends StatelessWidget { - MyApp({ - super.key, - }); + final ProjectCubit projectCubit; + + MyApp({super.key, required this.projectCubit}); final GoRouter _router = GoRouter( initialLocation: RoutesConst.auth, @@ -49,15 +54,17 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider(create: (context) => HomeBloc()..add(const FetchUserInfo())), + BlocProvider(create: (context) => projectCubit), + BlocProvider( + create: (context) => HomeBloc(projectCubit)..add(const FetchUserInfo())), BlocProvider( create: (context) => VisitorPasswordBloc(), ), BlocProvider( - create: (context) => RoutineBloc(), + create: (context) => RoutineBloc(projectCubit), ), BlocProvider( - create: (context) => SpaceTreeBloc()..add(InitialEvent()), + create: (context) => SpaceTreeBloc(projectCubit)..add(InitialEvent()), ), ], child: MaterialApp.router( diff --git a/lib/pages/auth/model/project_model.dart b/lib/pages/auth/model/project_model.dart new file mode 100644 index 00000000..4f2f4247 --- /dev/null +++ b/lib/pages/auth/model/project_model.dart @@ -0,0 +1,27 @@ +class Project { + final String uuid; + final String name; + final String description; + + const Project({ + required this.uuid, + required this.name, + required this.description, + }); + + factory Project.fromJson(Map json) { + return Project( + uuid: json['uuid'] as String, + name: json['name'] as String, + description: json['description'] as String, + ); + } + + Map toJson() { + return { + 'uuid': uuid, + 'name': name, + 'description': description, + }; + } +} diff --git a/lib/pages/common/bloc/project_cubit.dart b/lib/pages/common/bloc/project_cubit.dart new file mode 100644 index 00000000..ab0c8912 --- /dev/null +++ b/lib/pages/common/bloc/project_cubit.dart @@ -0,0 +1,19 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +class ProjectCubit extends Cubit { + final FlutterSecureStorage storage; + static const String projectKey = "selected_project_uuid"; + + ProjectCubit(this.storage) : super(null); + + Future setProjectUUID(String newUUID) async { + await storage.write(key: projectKey, value: newUUID); + emit(newUUID); + } + + Future clearProjectUUID() async { + await storage.delete(key: projectKey); + emit(null); + } +} From da445e11aa7652614b140c473e08c67de7227353 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Sat, 15 Feb 2025 00:35:34 +0400 Subject: [PATCH 2/6] Modified `_fetchUserInfo` to update the `ProjectCubit` with the retrieved user's project UUID. --- lib/pages/auth/model/user_model.dart | 6 ++++++ lib/pages/home/bloc/home_bloc.dart | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/pages/auth/model/user_model.dart b/lib/pages/auth/model/user_model.dart index 5090b0e0..267d0b3e 100644 --- a/lib/pages/auth/model/user_model.dart +++ b/lib/pages/auth/model/user_model.dart @@ -1,3 +1,4 @@ +import 'package:syncrow_web/pages/auth/model/project_model.dart'; import 'package:syncrow_web/pages/auth/model/token.dart'; class UserModel { @@ -13,6 +14,7 @@ class UserModel { final bool? hasAcceptedWebAgreement; final DateTime? webAgreementAcceptedAt; final UserRole? role; + final Project? project; UserModel({ required this.uuid, @@ -26,6 +28,7 @@ class UserModel { required this.hasAcceptedWebAgreement, required this.webAgreementAcceptedAt, required this.role, + required this.project, }); factory UserModel.fromJson(Map json) { @@ -43,6 +46,8 @@ class UserModel { ? DateTime.parse(json['webAgreementAcceptedAt']) : null, role: json['role'] != null ? UserRole.fromJson(json['role']) : null, + project: + json['project'] != null ? Project.fromJson(json['project']) : null, ); } @@ -64,6 +69,7 @@ class UserModel { phoneNumber: null, isEmailVerified: null, isAgreementAccepted: null, + project: null ); } diff --git a/lib/pages/home/bloc/home_bloc.dart b/lib/pages/home/bloc/home_bloc.dart index fda76728..6cd3e064 100644 --- a/lib/pages/home/bloc/home_bloc.dart +++ b/lib/pages/home/bloc/home_bloc.dart @@ -4,6 +4,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; // import 'package:graphview/GraphView.dart'; import 'package:syncrow_web/pages/auth/model/user_model.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/home/bloc/home_event.dart'; import 'package:syncrow_web/pages/home/bloc/home_state.dart'; import 'package:syncrow_web/pages/home/home_model/home_item_model.dart'; @@ -21,8 +22,9 @@ class HomeBloc extends Bloc { UserModel? user; String terms = ''; String policy = ''; + final ProjectCubit projectCubit; - HomeBloc() : super((HomeInitial())) { + HomeBloc(this.projectCubit) : super((HomeInitial())) { // on(_createNode); on(_fetchUserInfo); on(_fetchTerms); @@ -51,6 +53,10 @@ class HomeBloc extends Bloc { var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey); user = await HomeApi().fetchUserInfo(uuid); + + if (user != null && user!.project != null) { + projectCubit.setProjectUUID(user!.project!.uuid); + } add(FetchTermEvent()); add(FetchPolicyEvent()); From e1609309cf6a66dc36b29625d93059e97a64c8c9 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Sat, 15 Feb 2025 00:36:20 +0400 Subject: [PATCH 3/6] Added `ProjectCubit` as a dependency in `blocs` for managing project-level state. --- lib/pages/auth/bloc/auth_bloc.dart | 11 +- .../device_managment_bloc.dart | 82 +++++--- .../view/device_managment_page.dart | 3 +- .../view/agreement_and_privacy_dialog.dart | 5 +- .../add_user_dialog/bloc/users_bloc.dart | 56 ++++-- .../add_user_dialog/view/add_user_dialog.dart | 3 +- .../add_user_dialog/view/build_tree_view.dart | 3 +- .../view/edit_user_dialog.dart | 3 +- .../users_table/bloc/user_table_bloc.dart | 17 +- .../view/roles_and_permission_page.dart | 3 +- .../bloc/routine_bloc/routine_bloc.dart | 181 ++++++++++++------ .../space_tree/bloc/space_tree_bloc.dart | 81 +++++--- .../bloc/space_management_bloc.dart | 99 ++++++---- .../view/spaces_management_page.dart | 9 +- .../widgets/loaded_space_widget.dart | 2 + .../bloc/create_space_model_bloc.dart | 21 +- .../space_model/bloc/space_model_bloc.dart | 16 +- .../dialog/create_space_model_dialog.dart | 6 +- lib/services/devices_mang_api.dart | 4 +- lib/services/routines_api.dart | 35 ++-- lib/services/space_mana_api.dart | 70 +++---- lib/services/space_model_mang_api.dart | 24 +-- lib/services/user_permission.dart | 32 ++-- lib/utils/constants/api_const.dart | 4 +- lib/utils/user_drop_down_menu.dart | 7 +- 25 files changed, 509 insertions(+), 268 deletions(-) diff --git a/lib/pages/auth/bloc/auth_bloc.dart b/lib/pages/auth/bloc/auth_bloc.dart index 74980c2d..13490069 100644 --- a/lib/pages/auth/bloc/auth_bloc.dart +++ b/lib/pages/auth/bloc/auth_bloc.dart @@ -9,6 +9,7 @@ import 'package:syncrow_web/pages/auth/model/login_with_email_model.dart'; import 'package:syncrow_web/pages/auth/model/region_model.dart'; import 'package:syncrow_web/pages/auth/model/token.dart'; import 'package:syncrow_web/pages/auth/model/user_model.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/services/auth_api.dart'; import 'package:syncrow_web/utils/constants/strings_manager.dart'; import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart'; @@ -180,7 +181,6 @@ class AuthBloc extends Bloc { return; } - if (token.accessTokenIsNotEmpty) { FlutterSecureStorage storage = const FlutterSecureStorage(); await storage.write( @@ -442,8 +442,13 @@ class AuthBloc extends Bloc { emit(LoginInitial()); } - static logout() { - const storage = FlutterSecureStorage(); + static Future logout( + BuildContext context, ProjectCubit projectCubit) async { + final storage = FlutterSecureStorage(); + + await storage.delete(key: ProjectCubit.projectKey); + + projectCubit.clearProjectUUID(); storage.deleteAll(); } } diff --git a/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart index 56b08ced..672c4d67 100644 --- a/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart +++ b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart @@ -1,14 +1,17 @@ import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; import 'package:syncrow_web/services/devices_mang_api.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; part 'device_managment_event.dart'; part 'device_managment_state.dart'; -class DeviceManagementBloc extends Bloc { +class DeviceManagementBloc + extends Bloc { int _selectedIndex = 0; List _devices = []; int _onlineCount = 0; @@ -19,8 +22,9 @@ class DeviceManagementBloc extends Bloc(_onFetchDevices); on(_onFilterDevices); on(_onSelectedFilterChanged); @@ -31,19 +35,25 @@ class DeviceManagementBloc extends Bloc(_onUpdateSelection); } - Future _onFetchDevices(FetchDevices event, Emitter emit) async { + Future _onFetchDevices( + FetchDevices event, Emitter emit) async { emit(DeviceManagementLoading()); try { List devices = []; _devices.clear(); var spaceBloc = event.context.read(); + final projectUuid = projectCubit.state; + if (spaceBloc.state.selectedCommunities.isEmpty) { - devices = await DevicesManagementApi().fetchDevices('', ''); + devices = await DevicesManagementApi() + .fetchDevices('', '', projectUuid ?? TempConst.projectId); } else { for (var community in spaceBloc.state.selectedCommunities) { - List spacesList = spaceBloc.state.selectedCommunityAndSpaces[community] ?? []; + List spacesList = + spaceBloc.state.selectedCommunityAndSpaces[community] ?? []; for (var space in spacesList) { - devices.addAll(await DevicesManagementApi().fetchDevices(community, space)); + devices.addAll(await DevicesManagementApi().fetchDevices( + community, space, projectUuid ?? TempConst.projectId)); } } } @@ -66,7 +76,8 @@ class DeviceManagementBloc extends Bloc emit) async { + void _onFilterDevices( + FilterDevices event, Emitter emit) async { if (_devices.isNotEmpty) { _filteredDevices = List.from(_devices.where((device) { switch (event.filter) { @@ -97,7 +108,8 @@ class DeviceManagementBloc extends Bloc _onResetFilters(ResetFilters event, Emitter emit) async { + Future _onResetFilters( + ResetFilters event, Emitter emit) async { currentProductName = ''; _selectedDevices.clear(); _filteredDevices = List.from(_devices); @@ -113,7 +125,8 @@ class DeviceManagementBloc extends Bloc emit) { + void _onResetSelectedDevices( + ResetSelectedDevices event, Emitter emit) { _selectedDevices.clear(); if (state is DeviceManagementLoaded) { @@ -139,12 +152,14 @@ class DeviceManagementBloc extends Bloc emit) { + void _onSelectedFilterChanged( + SelectedFilterChanged event, Emitter emit) { _selectedIndex = event.selectedIndex; add(FilterDevices(_getFilterFromIndex(_selectedIndex))); } - void _onSelectDevice(SelectDevice event, Emitter emit) { + void _onSelectDevice( + SelectDevice event, Emitter emit) { final selectedUuid = event.selectedDevice.uuid; if (_selectedDevices.any((device) => device.uuid == selectedUuid)) { @@ -155,7 +170,8 @@ class DeviceManagementBloc extends Bloc clonedSelectedDevices = List.from(_selectedDevices); - bool isControlButtonEnabled = _checkIfControlButtonEnabled(clonedSelectedDevices); + bool isControlButtonEnabled = + _checkIfControlButtonEnabled(clonedSelectedDevices); if (state is DeviceManagementLoaded) { emit(DeviceManagementLoaded( @@ -164,7 +180,8 @@ class DeviceManagementBloc extends Bloc emit) { + void _onUpdateSelection( + UpdateSelection event, Emitter emit) { List selectedDevices = []; List devicesToSelectFrom = []; @@ -223,7 +242,8 @@ class DeviceManagementBloc extends Bloc selectedDevices) { if (selectedDevices.length > 1) { - final productTypes = selectedDevices.map((device) => device.productType).toSet(); + final productTypes = + selectedDevices.map((device) => device.productType).toSet(); return productTypes.length == 1; } else if (selectedDevices.length == 1) { return true; @@ -234,8 +254,10 @@ class DeviceManagementBloc extends Bloc device.online == true).length; _offlineCount = _devices.where((device) => device.online == false).length; - _lowBatteryCount = - _devices.where((device) => device.batteryLevel != null && device.batteryLevel! < 20).length; + _lowBatteryCount = _devices + .where((device) => + device.batteryLevel != null && device.batteryLevel! < 20) + .length; } String _getFilterFromIndex(int index) { @@ -251,7 +273,8 @@ class DeviceManagementBloc extends Bloc emit) { + void _onSearchDevices( + SearchDevices event, Emitter emit) { if ((event.community == null || event.community!.isEmpty) && (event.unitName == null || event.unitName!.isEmpty) && (event.productName == null || event.productName!.isEmpty)) { @@ -280,22 +303,33 @@ class DeviceManagementBloc extends Bloc DeviceManagementBloc()..add(FetchDevices(context)), + create: (context) => DeviceManagementBloc(context.read())..add(FetchDevices(context)), ), ], child: WebScaffold( diff --git a/lib/pages/home/view/agreement_and_privacy_dialog.dart b/lib/pages/home/view/agreement_and_privacy_dialog.dart index 67c33984..bbdb7b34 100644 --- a/lib/pages/home/view/agreement_and_privacy_dialog.dart +++ b/lib/pages/home/view/agreement_and_privacy_dialog.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:go_router/go_router.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/routes_const.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -162,7 +164,8 @@ class _AgreementAndPrivacyDialogState extends State { children: [ InkWell( onTap: () { - AuthBloc.logout(); + final projectCubit = BlocProvider.of(context); + AuthBloc.logout(context, projectCubit); context.go(RoutesConst.auth); }, child: const Text("Cancel"), diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart index 96e49040..73bc23f3 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart @@ -1,5 +1,6 @@ import 'package:bloc/bloc.dart'; import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/common/custom_dialog.dart'; import 'package:syncrow_web/pages/roles_and_permission/model/edit_user_model.dart'; import 'package:syncrow_web/pages/roles_and_permission/model/role_type_model.dart'; @@ -12,9 +13,12 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/services/user_permission.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; class UsersBloc extends Bloc { - UsersBloc() : super(UsersInitial()) { + final ProjectCubit projectCubit; + + UsersBloc(this.projectCubit) : super(UsersInitial()) { on(isCompleteBasicsFun); on(_onLoadCommunityAndSpaces); on(searchTreeNode); @@ -74,7 +78,10 @@ class UsersBloc extends Bloc { Future> _fetchSpacesForCommunity( String communityUuid) async { - return await CommunitySpaceManagementApi().getSpaceHierarchy(communityUuid); + final projectUuid = projectCubit.state; + + return await CommunitySpaceManagementApi() + .getSpaceHierarchy(communityUuid, projectUuid ?? TempConst.projectId); } List updatedCommunities = []; @@ -84,8 +91,9 @@ class UsersBloc extends Bloc { LoadCommunityAndSpacesEvent event, Emitter emit) async { try { emit(UsersLoadingState()); - List communities = - await CommunitySpaceManagementApi().fetchCommunities(); + final projectUuid = projectCubit.state; + List communities = await CommunitySpaceManagementApi() + .fetchCommunities(projectUuid ?? TempConst.projectId); communityIds = communities.map((community) => community.uuid).toList(); updatedCommunities = await Future.wait( communities.map((community) async { @@ -328,20 +336,22 @@ class UsersBloc extends Bloc { void _sendInvitUser(SendInviteUsers event, Emitter emit) async { try { + final projectUuid = projectCubit.state; + emit(UsersLoadingState()); List selectedIds = getSelectedIds(updatedCommunities) .where((id) => !communityIds.contains(id)) .toList(); bool res = await UserPermissionApi().sendInviteUser( - email: emailController.text, - firstName: firstNameController.text, - jobTitle: jobTitleController.text, - lastName: lastNameController.text, - phoneNumber: phoneController.text, - roleUuid: roleSelected, - spaceUuids: selectedIds, - ); + email: emailController.text, + firstName: firstNameController.text, + jobTitle: jobTitleController.text, + lastName: lastNameController.text, + phoneNumber: phoneController.text, + roleUuid: roleSelected, + spaceUuids: selectedIds, + projectUuid: projectUuid ?? TempConst.projectId); if (res) { showCustomDialog( @@ -376,16 +386,17 @@ class UsersBloc extends Bloc { List selectedIds = getSelectedIds(updatedCommunities) .where((id) => !communityIds.contains(id)) .toList(); + final projectUuid = projectCubit.state; bool res = await UserPermissionApi().editInviteUser( - userId: event.userId, - firstName: firstNameController.text, - jobTitle: jobTitleController.text, - lastName: lastNameController.text, - phoneNumber: phoneController.text, - roleUuid: roleSelected, - spaceUuids: selectedIds, - ); + userId: event.userId, + firstName: firstNameController.text, + jobTitle: jobTitleController.text, + lastName: lastNameController.text, + phoneNumber: phoneController.text, + roleUuid: roleSelected, + spaceUuids: selectedIds, + projectUuid: projectUuid ?? TempConst.projectId); if (res == true) { showCustomDialog( barrierDismissible: false, @@ -490,8 +501,11 @@ class UsersBloc extends Bloc { emit(UsersLoadingState()); try { + final projectUuid = projectCubit.state; + if (event.uuid?.isNotEmpty ?? false) { - final res = await UserPermissionApi().fetchUserById(event.uuid); + final res = await UserPermissionApi() + .fetchUserById(event.uuid, projectUuid ?? TempConst.projectId); if (res != null) { // Populate the text controllers diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart index 1a487830..4023f9bd 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart'; @@ -23,7 +24,7 @@ class _AddNewUserDialogState extends State { @override Widget build(BuildContext context) { return BlocProvider( - create: (BuildContext context) => UsersBloc() + create: (BuildContext context) => UsersBloc(context.read()) ..add(const LoadCommunityAndSpacesEvent()) ..add(const RoleEvent()), child: BlocConsumer( diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/build_tree_view.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/build_tree_view.dart index b7fc1085..d45e3482 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/build_tree_view.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/build_tree_view.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart'; @@ -21,7 +22,7 @@ class TreeView extends StatelessWidget { final _blocRole = BlocProvider.of(context); debugPrint('TreeView constructed with userId = $userId'); return BlocProvider( - create: (_) => UsersBloc(), + create: (_) => UsersBloc(context.read()), // ..add(const LoadCommunityAndSpacesEvent()), child: BlocConsumer( listener: (context, state) { diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/edit_user_dialog.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/edit_user_dialog.dart index 8b6600e0..fdf52c4d 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/edit_user_dialog.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/edit_user_dialog.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart'; @@ -24,7 +25,7 @@ class _EditUserDialogState extends State { @override Widget build(BuildContext context) { return BlocProvider( - create: (BuildContext context) => UsersBloc() + create: (BuildContext context) => UsersBloc(context.read()) ..add(const LoadCommunityAndSpacesEvent()) ..add(const RoleEvent()) ..add(GetUserByIdEvent(uuid: widget.userId)), diff --git a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart index 713b03f0..2ba3130a 100644 --- a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart +++ b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart @@ -1,13 +1,17 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/roles_and_permission/model/roles_user_model.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/bloc/user_table_event.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/bloc/user_table_state.dart'; import 'package:syncrow_web/services/user_permission.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; class UserTableBloc extends Bloc { - UserTableBloc() : super(TableInitial()) { + final ProjectCubit _projectCubit; + + UserTableBloc(this._projectCubit) : super(TableInitial()) { on(_getUsers); on(_changeUserStatus); on(_toggleSortUsersByNameAsc); @@ -46,10 +50,13 @@ class UserTableBloc extends Bloc { Future _getUsers(GetUsers event, Emitter emit) async { emit(UsersLoadingState()); try { + final projectUuid = _projectCubit.state; + roleTypes.clear(); jobTitle.clear(); createdBy.clear(); - users = await UserPermissionApi().fetchUsers(); + users = await UserPermissionApi() + .fetchUsers(projectUuid ?? TempConst.projectId); users.sort((a, b) { final dateA = _parseDateTime(a.createdDate); final dateB = _parseDateTime(b.createdDate); @@ -96,9 +103,13 @@ class UserTableBloc extends Bloc { Future _changeUserStatus( ChangeUserStatus event, Emitter emit) async { try { + final projectUuid = _projectCubit.state; + emit(UsersLoadingState()); bool res = await UserPermissionApi().changeUserStatusById( - event.userId, event.newStatus == "disabled" ? false : true); + event.userId, + event.newStatus == "disabled" ? false : true, + projectUuid ?? TempConst.projectId); if (res == true) { add(const GetUsers()); } diff --git a/lib/pages/roles_and_permission/view/roles_and_permission_page.dart b/lib/pages/roles_and_permission/view/roles_and_permission_page.dart index 44944ed3..68b586bc 100644 --- a/lib/pages/roles_and_permission/view/roles_and_permission_page.dart +++ b/lib/pages/roles_and_permission/view/roles_and_permission_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart'; import 'package:syncrow_web/pages/roles_and_permission/bloc/roles_permission_bloc.dart'; import 'package:syncrow_web/pages/roles_and_permission/bloc/roles_permission_state.dart'; @@ -76,7 +77,7 @@ class RolesAndPermissionPage extends StatelessWidget { ], ), scaffoldBody: BlocProvider( - create: (context) => UserTableBloc()..add(const GetUsers()), + create: (context) => UserTableBloc(context.read())..add(const GetUsers()), child: UsersPage(), ) // _blocRole.tapSelect == false diff --git a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart index b05229c4..3a2ef4b0 100644 --- a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart'; @@ -13,6 +14,7 @@ import 'package:syncrow_web/pages/routines/models/routine_model.dart'; import 'package:syncrow_web/services/devices_mang_api.dart'; import 'package:syncrow_web/services/routines_api.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; import 'package:syncrow_web/utils/snack_bar.dart'; import 'package:uuid/uuid.dart'; @@ -23,7 +25,9 @@ String spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; String communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; class RoutineBloc extends Bloc { - RoutineBloc() : super(const RoutineState()) { + final ProjectCubit projectCubit; + + RoutineBloc(this.projectCubit) : super(const RoutineState()) { on(_onAddToIfContainer); on(_onAddToThenContainer); on(_onLoadScenes); @@ -54,7 +58,8 @@ class RoutineBloc extends Bloc { TriggerSwitchTabsEvent event, Emitter emit, ) { - emit(state.copyWith(routineTab: event.isRoutineTab, createRoutineView: false)); + emit(state.copyWith( + routineTab: event.isRoutineTab, createRoutineView: false)); add(ResetRoutineState()); if (event.isRoutineTab) { add(LoadScenes(spaceId, communityId)); @@ -80,8 +85,8 @@ class RoutineBloc extends Bloc { final updatedIfItems = List>.from(state.ifItems); // Find the index of the item in teh current itemsList - int index = - updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); + int index = updatedIfItems.indexWhere( + (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); // Replace the map if the index is valid if (index != -1) { updatedIfItems[index] = event.item; @@ -90,18 +95,21 @@ class RoutineBloc extends Bloc { } if (event.isTabToRun) { - emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: true, isAutomation: false)); + emit(state.copyWith( + ifItems: updatedIfItems, isTabToRun: true, isAutomation: false)); } else { - emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: false, isAutomation: true)); + emit(state.copyWith( + ifItems: updatedIfItems, isTabToRun: false, isAutomation: true)); } } - void _onAddToThenContainer(AddToThenContainer event, Emitter emit) { + void _onAddToThenContainer( + AddToThenContainer event, Emitter emit) { final currentItems = List>.from(state.thenItems); // Find the index of the item in teh current itemsList - int index = - currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); + int index = currentItems.indexWhere( + (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); // Replace the map if the index is valid if (index != -1) { currentItems[index] = event.item; @@ -112,22 +120,26 @@ class RoutineBloc extends Bloc { emit(state.copyWith(thenItems: currentItems)); } - void _onAddFunctionsToRoutine(AddFunctionToRoutine event, Emitter emit) { + void _onAddFunctionsToRoutine( + AddFunctionToRoutine event, Emitter emit) { try { if (event.functions.isEmpty) return; - List selectedFunction = List.from(event.functions); + List selectedFunction = + List.from(event.functions); Map> currentSelectedFunctions = Map>.from(state.selectedFunctions); if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) { List currentFunctions = - List.from(currentSelectedFunctions[event.uniqueCustomId] ?? []); + List.from( + currentSelectedFunctions[event.uniqueCustomId] ?? []); List functionCode = []; for (int i = 0; i < selectedFunction.length; i++) { for (int j = 0; j < currentFunctions.length; j++) { - if (selectedFunction[i].functionCode == currentFunctions[j].functionCode) { + if (selectedFunction[i].functionCode == + currentFunctions[j].functionCode) { currentFunctions[j] = selectedFunction[i]; if (!functionCode.contains(currentFunctions[j].functionCode)) { functionCode.add(currentFunctions[j].functionCode); @@ -137,13 +149,15 @@ class RoutineBloc extends Bloc { } for (int i = 0; i < functionCode.length; i++) { - selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]); + selectedFunction + .removeWhere((code) => code.functionCode == functionCode[i]); } - currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions) - ..addAll(selectedFunction); + currentSelectedFunctions[event.uniqueCustomId] = + List.from(currentFunctions)..addAll(selectedFunction); } else { - currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions); + currentSelectedFunctions[event.uniqueCustomId] = + List.from(event.functions); } emit(state.copyWith(selectedFunctions: currentSelectedFunctions)); @@ -152,17 +166,20 @@ class RoutineBloc extends Bloc { } } - Future _onLoadScenes(LoadScenes event, Emitter emit) async { + Future _onLoadScenes( + LoadScenes event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); try { + final projectUuid = projectCubit.state; + spaceId = event.spaceId; communityId = event.communityId; List scenes = []; if (communityId.isNotEmpty && spaceId.isNotEmpty) { - scenes = await SceneApi.getScenes(event.spaceId, event.communityId); + scenes = await SceneApi.getScenes(event.spaceId, event.communityId, projectUuid ?? TempConst.projectId); } emit(state.copyWith( scenes: scenes, @@ -178,7 +195,8 @@ class RoutineBloc extends Bloc { } } - Future _onLoadAutomation(LoadAutomation event, Emitter emit) async { + Future _onLoadAutomation( + LoadAutomation event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); try { @@ -201,14 +219,16 @@ class RoutineBloc extends Bloc { } } - FutureOr _onSearchRoutines(SearchRoutines event, Emitter emit) async { + FutureOr _onSearchRoutines( + SearchRoutines event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); await Future.delayed(const Duration(seconds: 1)); emit(state.copyWith(isLoading: false, errorMessage: null)); emit(state.copyWith(searchText: event.query)); } - FutureOr _onAddSelectedIcon(AddSelectedIcon event, Emitter emit) { + FutureOr _onAddSelectedIcon( + AddSelectedIcon event, Emitter emit) { emit(state.copyWith(selectedIcon: event.icon)); } @@ -222,7 +242,8 @@ class RoutineBloc extends Bloc { return actions.last['deviceId'] == 'delay'; } - Future _onCreateScene(CreateSceneEvent event, Emitter emit) async { + Future _onCreateScene( + CreateSceneEvent event, Emitter emit) async { try { // Check if first action is delay // if (_isFirstActionDelay(state.thenItems)) { @@ -235,7 +256,8 @@ class RoutineBloc extends Bloc { if (_isLastActionDelay(state.thenItems)) { emit(state.copyWith( - errorMessage: 'A delay condition cannot be the only or the last action', + errorMessage: + 'A delay condition cannot be the only or the last action', isLoading: false, )); return; @@ -308,7 +330,8 @@ class RoutineBloc extends Bloc { } } - Future _onCreateAutomation(CreateAutomationEvent event, Emitter emit) async { + Future _onCreateAutomation( + CreateAutomationEvent event, Emitter emit) async { try { if (state.routineName == null || state.routineName!.isEmpty) { emit(state.copyWith( @@ -329,7 +352,8 @@ class RoutineBloc extends Bloc { if (_isLastActionDelay(state.thenItems)) { emit(state.copyWith( - errorMessage: 'A delay condition cannot be the only or the last action', + errorMessage: + 'A delay condition cannot be the only or the last action', isLoading: false, )); CustomSnackBar.redSnackBar('Cannot have delay as the last action'); @@ -439,17 +463,21 @@ class RoutineBloc extends Bloc { } } - FutureOr _onRemoveDragCard(RemoveDragCard event, Emitter emit) { + FutureOr _onRemoveDragCard( + RemoveDragCard event, Emitter emit) { if (event.isFromThen) { final thenItems = List>.from(state.thenItems); - final selectedFunctions = Map>.from(state.selectedFunctions); + final selectedFunctions = + Map>.from(state.selectedFunctions); thenItems.removeAt(event.index); selectedFunctions.remove(event.key); - emit(state.copyWith(thenItems: thenItems, selectedFunctions: selectedFunctions)); + emit(state.copyWith( + thenItems: thenItems, selectedFunctions: selectedFunctions)); } else { final ifItems = List>.from(state.ifItems); - final selectedFunctions = Map>.from(state.selectedFunctions); + final selectedFunctions = + Map>.from(state.selectedFunctions); ifItems.removeAt(event.index); selectedFunctions.remove(event.key); @@ -460,7 +488,8 @@ class RoutineBloc extends Bloc { isAutomation: false, isTabToRun: false)); } else { - emit(state.copyWith(ifItems: ifItems, selectedFunctions: selectedFunctions)); + emit(state.copyWith( + ifItems: ifItems, selectedFunctions: selectedFunctions)); } } } @@ -472,18 +501,23 @@ class RoutineBloc extends Bloc { )); } - FutureOr _onEffectiveTimeEvent(EffectiveTimePeriodEvent event, Emitter emit) { + FutureOr _onEffectiveTimeEvent( + EffectiveTimePeriodEvent event, Emitter emit) { emit(state.copyWith(effectiveTime: event.effectiveTime)); } - FutureOr _onSetRoutineName(SetRoutineName event, Emitter emit) { + FutureOr _onSetRoutineName( + SetRoutineName event, Emitter emit) { emit(state.copyWith( routineName: event.name, )); } - (List>, List>, Map>) - _createCardData( + ( + List>, + List>, + Map> + ) _createCardData( List actions, List? conditions, Map> currentFunctions, @@ -516,7 +550,8 @@ class RoutineBloc extends Bloc { 'deviceId': condition.entityId, 'title': matchingDevice.name ?? condition.entityId, 'productType': condition.entityType, - 'imagePath': matchingDevice.getDefaultIcon(condition.entityType), + 'imagePath': + matchingDevice.getDefaultIcon(condition.entityType), }; final functions = matchingDevice.functions; @@ -552,8 +587,11 @@ class RoutineBloc extends Bloc { final cardData = { 'entityId': action.entityId, 'uniqueCustomId': const Uuid().v4(), - 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, - 'title': action.actionExecutor == 'delay' ? 'Delay' : (matchingDevice.name ?? 'Device'), + 'deviceId': + action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'title': action.actionExecutor == 'delay' + ? 'Delay' + : (matchingDevice.name ?? 'Device'), 'productType': action.productType, 'imagePath': matchingDevice.getDefaultIcon(action.productType), }; @@ -596,7 +634,8 @@ class RoutineBloc extends Bloc { return (thenItems, ifItems, currentFunctions); } - Future _onGetSceneDetails(GetSceneDetails event, Emitter emit) async { + Future _onGetSceneDetails( + GetSceneDetails event, Emitter emit) async { try { emit(state.copyWith( isLoading: true, @@ -644,10 +683,12 @@ class RoutineBloc extends Bloc { if (!deviceCards.containsKey(deviceId)) { deviceCards[deviceId] = { 'entityId': action.entityId, - 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, - 'uniqueCustomId': action.type == 'automation' || action.actionExecutor == 'delay' - ? const Uuid().v4() - : action.entityId, + 'deviceId': + action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'uniqueCustomId': + action.type == 'automation' || action.actionExecutor == 'delay' + ? const Uuid().v4() + : action.entityId, 'title': action.actionExecutor == 'delay' ? 'Delay' : action.type == 'automation' @@ -682,7 +723,8 @@ class RoutineBloc extends Bloc { ), ); // emit(state.copyWith(automationActionExecutor: action.actionExecutor)); - } else if (action.executorProperty != null && action.actionExecutor != 'delay') { + } else if (action.executorProperty != null && + action.actionExecutor != 'delay') { if (!updatedFunctions.containsKey(uniqueCustomId)) { updatedFunctions[uniqueCustomId] = []; } @@ -754,7 +796,8 @@ class RoutineBloc extends Bloc { } } - FutureOr _onResetRoutineState(ResetRoutineState event, Emitter emit) { + FutureOr _onResetRoutineState( + ResetRoutineState event, Emitter emit) { emit(state.copyWith( ifItems: [], thenItems: [], @@ -784,7 +827,8 @@ class RoutineBloc extends Bloc { if (state.isTabToRun) { SceneApi.deleteScene(unitUuid: spaceId, sceneId: state.sceneId ?? ''); } else { - SceneApi.deleteAutomation(unitUuid: spaceId, automationId: state.automationId ?? ''); + SceneApi.deleteAutomation( + unitUuid: spaceId, automationId: state.automationId ?? ''); } add(LoadScenes(spaceId, communityId)); @@ -813,10 +857,13 @@ class RoutineBloc extends Bloc { // } // } - FutureOr _fetchDevices(FetchDevicesInRoutine event, Emitter emit) async { + FutureOr _fetchDevices( + FetchDevicesInRoutine event, Emitter emit) async { emit(state.copyWith(isLoading: true)); try { - final devices = await DevicesManagementApi().fetchDevices('', ''); + final projectUuid = projectCubit.state; + final devices = await DevicesManagementApi() + .fetchDevices('', '', projectUuid ?? TempConst.projectId); emit(state.copyWith(isLoading: false, devices: devices)); } catch (e) { @@ -824,7 +871,8 @@ class RoutineBloc extends Bloc { } } - FutureOr _onUpdateScene(UpdateScene event, Emitter emit) async { + FutureOr _onUpdateScene( + UpdateScene event, Emitter emit) async { try { // Check if first action is delay // if (_isFirstActionDelay(state.thenItems)) { @@ -838,7 +886,8 @@ class RoutineBloc extends Bloc { if (_isLastActionDelay(state.thenItems)) { emit(state.copyWith( - errorMessage: 'A delay condition cannot be the only or the last action', + errorMessage: + 'A delay condition cannot be the only or the last action', isLoading: false, )); return; @@ -891,7 +940,8 @@ class RoutineBloc extends Bloc { actions: actions, ); - final result = await SceneApi.updateScene(createSceneModel, state.sceneId ?? ''); + final result = + await SceneApi.updateScene(createSceneModel, state.sceneId ?? ''); if (result['success']) { add(ResetRoutineState()); add(LoadScenes(spaceId, communityId)); @@ -910,7 +960,8 @@ class RoutineBloc extends Bloc { } } - FutureOr _onUpdateAutomation(UpdateAutomation event, Emitter emit) async { + FutureOr _onUpdateAutomation( + UpdateAutomation event, Emitter emit) async { try { if (state.routineName == null || state.routineName!.isEmpty) { emit(state.copyWith( @@ -1018,8 +1069,8 @@ class RoutineBloc extends Bloc { actions: actions, ); - final result = - await SceneApi.updateAutomation(createAutomationModel, state.automationId ?? ''); + final result = await SceneApi.updateAutomation( + createAutomationModel, state.automationId ?? ''); if (result['success']) { add(ResetRoutineState()); @@ -1052,7 +1103,8 @@ class RoutineBloc extends Bloc { thenItems: [], )); - final automationDetails = await SceneApi.getAutomationDetails(event.automationId); + final automationDetails = + await SceneApi.getAutomationDetails(event.automationId); final Map> deviceIfCards = {}; final Map> deviceThenCards = {}; @@ -1120,13 +1172,15 @@ class RoutineBloc extends Bloc { ), ); - final deviceId = - action.actionExecutor == 'delay' ? '${action.entityId}_delay' : action.entityId; + final deviceId = action.actionExecutor == 'delay' + ? '${action.entityId}_delay' + : action.entityId; if (!deviceThenCards.containsKey(deviceId)) { deviceThenCards[deviceId] = { 'entityId': action.entityId, - 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'deviceId': + action.actionExecutor == 'delay' ? 'delay' : action.entityId, 'uniqueCustomId': const Uuid().v4(), 'title': action.actionExecutor == 'delay' ? 'Delay' @@ -1157,7 +1211,8 @@ class RoutineBloc extends Bloc { updatedFunctions[uniqueCustomId] = []; } - if (action.executorProperty != null && action.actionExecutor != 'delay') { + if (action.executorProperty != null && + action.actionExecutor != 'delay') { final functions = matchingDevice.functions; final functionCode = action.executorProperty!.functionCode; for (var function in functions) { @@ -1199,10 +1254,14 @@ class RoutineBloc extends Bloc { } } - final ifItems = deviceIfCards.values.where((card) => card['type'] == 'condition').toList(); + final ifItems = deviceIfCards.values + .where((card) => card['type'] == 'condition') + .toList(); final thenItems = deviceThenCards.values .where((card) => - card['type'] == 'action' || card['type'] == 'automation' || card['type'] == 'scene') + card['type'] == 'action' || + card['type'] == 'automation' || + card['type'] == 'scene') .toList(); emit(state.copyWith( diff --git a/lib/pages/space_tree/bloc/space_tree_bloc.dart b/lib/pages/space_tree/bloc/space_tree_bloc.dart index 6ac0c0d9..2cb39fc8 100644 --- a/lib/pages/space_tree/bloc/space_tree_bloc.dart +++ b/lib/pages/space_tree/bloc/space_tree_bloc.dart @@ -1,15 +1,18 @@ import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; import 'package:syncrow_web/services/space_mana_api.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; class SpaceTreeBloc extends Bloc { String selectedCommunityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; String selectedSpaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; + final ProjectCubit projectCubit; - SpaceTreeBloc() : super(const SpaceTreeState()) { + SpaceTreeBloc(this.projectCubit) : super(const SpaceTreeState()) { on(_fetchSpaces); on(_onCommunityExpanded); on(_onSpaceExpanded); @@ -21,12 +24,16 @@ class SpaceTreeBloc extends Bloc { _fetchSpaces(InitialEvent event, Emitter emit) async { emit(SpaceTreeLoadingState()); try { - List communities = await CommunitySpaceManagementApi().fetchCommunities(); + final projectUuid = projectCubit.state; + + List communities = await CommunitySpaceManagementApi() + .fetchCommunities(projectUuid ?? TempConst.projectId); List updatedCommunities = await Future.wait( communities.map((community) async { - List spaces = - await CommunitySpaceManagementApi().getSpaceHierarchy(community.uuid); + List spaces = await CommunitySpaceManagementApi() + .getSpaceHierarchy( + community.uuid, projectUuid ?? TempConst.projectId); return CommunityModel( uuid: community.uuid, @@ -41,15 +48,19 @@ class SpaceTreeBloc extends Bloc { ); emit(state.copyWith( - communitiesList: updatedCommunities, expandedCommunity: [], expandedSpaces: [])); + communitiesList: updatedCommunities, + expandedCommunity: [], + expandedSpaces: [])); } catch (e) { emit(SpaceTreeErrorState('Error loading communities and spaces: $e')); } } - _onCommunityExpanded(OnCommunityExpanded event, Emitter emit) async { + _onCommunityExpanded( + OnCommunityExpanded event, Emitter emit) async { try { - List updatedExpandedCommunityList = List.from(state.expandedCommunities); + List updatedExpandedCommunityList = + List.from(state.expandedCommunities); if (updatedExpandedCommunityList.contains(event.communityId)) { updatedExpandedCommunityList.remove(event.communityId); @@ -81,13 +92,17 @@ class SpaceTreeBloc extends Bloc { } } - _onCommunitySelected(OnCommunitySelected event, Emitter emit) async { + _onCommunitySelected( + OnCommunitySelected event, Emitter emit) async { try { List updatedSelectedCommunities = List.from(state.selectedCommunities.toSet().toList()); - List updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList()); - List updatedSoldChecks = List.from(state.soldCheck.toSet().toList()); - Map> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces); + List updatedSelectedSpaces = + List.from(state.selectedSpaces.toSet().toList()); + List updatedSoldChecks = + List.from(state.soldCheck.toSet().toList()); + Map> communityAndSpaces = + Map.from(state.selectedCommunityAndSpaces); List childrenIds = _getAllChildIds(event.children); @@ -118,9 +133,12 @@ class SpaceTreeBloc extends Bloc { try { List updatedSelectedCommunities = List.from(state.selectedCommunities.toSet().toList()); - List updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList()); - List updatedSoldChecks = List.from(state.soldCheck.toSet().toList()); - Map> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces); + List updatedSelectedSpaces = + List.from(state.selectedSpaces.toSet().toList()); + List updatedSoldChecks = + List.from(state.soldCheck.toSet().toList()); + Map> communityAndSpaces = + Map.from(state.selectedCommunityAndSpaces); List childrenIds = _getAllChildIds(event.children); bool isChildSelected = false; @@ -140,9 +158,11 @@ class SpaceTreeBloc extends Bloc { updatedSelectedSpaces.addAll(childrenIds); } - List spaces = _getThePathToChild(event.communityId, event.spaceId); + List spaces = + _getThePathToChild(event.communityId, event.spaceId); for (String space in spaces) { - if (!updatedSelectedSpaces.contains(space) && !updatedSoldChecks.contains(space)) { + if (!updatedSelectedSpaces.contains(space) && + !updatedSoldChecks.contains(space)) { updatedSoldChecks.add(space); } } @@ -161,7 +181,8 @@ class SpaceTreeBloc extends Bloc { } updatedSoldChecks.remove(event.spaceId); - List parents = _getThePathToChild(event.communityId, event.spaceId); + List parents = + _getThePathToChild(event.communityId, event.spaceId); if (!_parentSelected(parents, updatedSelectedSpaces)) { updatedSoldChecks.removeWhere(parents.contains); } @@ -200,16 +221,18 @@ class SpaceTreeBloc extends Bloc { // Filter communities and expand only those that match the query filteredCommunity = communities.where((community) { - final containsQueryInCommunity = - community.name.toLowerCase().contains(event.searchQuery.toLowerCase()); - final containsQueryInSpaces = - community.spaces.any((space) => _containsQuery(space, event.searchQuery.toLowerCase())); + final containsQueryInCommunity = community.name + .toLowerCase() + .contains(event.searchQuery.toLowerCase()); + final containsQueryInSpaces = community.spaces.any( + (space) => _containsQuery(space, event.searchQuery.toLowerCase())); return containsQueryInCommunity || containsQueryInSpaces; }).toList(); emit(state.copyWith( - filteredCommunity: filteredCommunity, isSearching: event.searchQuery.isNotEmpty)); + filteredCommunity: filteredCommunity, + isSearching: event.searchQuery.isNotEmpty)); } catch (e) { emit(const SpaceTreeErrorState('Something went wrong')); } @@ -218,8 +241,8 @@ class SpaceTreeBloc extends Bloc { // Helper function to determine if any space or its children match the search query bool _containsQuery(SpaceModel space, String query) { final matchesSpace = space.name.toLowerCase().contains(query); - final matchesChildren = - space.children.any((child) => _containsQuery(child, query)); // Recursive check for children + final matchesChildren = space.children.any((child) => + _containsQuery(child, query)); // Recursive check for children return matchesSpace || matchesChildren; } @@ -233,14 +256,15 @@ class SpaceTreeBloc extends Bloc { return ids; } - bool _anySpacesSelectedInCommunity( - String communityId, List selectedSpaces, List partialCheckedList) { + bool _anySpacesSelectedInCommunity(String communityId, + List selectedSpaces, List partialCheckedList) { bool result = false; for (var community in state.communityList) { if (community.uuid == communityId) { List ids = _getAllChildIds(community.spaces); for (var id in ids) { - result = selectedSpaces.contains(id) || partialCheckedList.contains(id); + result = + selectedSpaces.contains(id) || partialCheckedList.contains(id); if (result) { return result; } @@ -267,7 +291,8 @@ class SpaceTreeBloc extends Bloc { return ids; } - List _getAllParentsIds(SpaceModel child, String spaceId, List listIds) { + List _getAllParentsIds( + SpaceModel child, String spaceId, List listIds) { List ids = listIds; ids.add(child.uuid ?? ''); diff --git a/lib/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart b/lib/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart index ee6018e6..fdbdef88 100644 --- a/lib/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart +++ b/lib/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart @@ -1,4 +1,5 @@ import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/create_subspace_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart'; @@ -14,16 +15,19 @@ import 'package:syncrow_web/services/product_api.dart'; import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/services/space_model_mang_api.dart'; import 'package:syncrow_web/utils/constants/action_enum.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; class SpaceManagementBloc extends Bloc { final CommunitySpaceManagementApi _api; final ProductApi _productApi; final SpaceModelManagementApi _spaceModelApi; + final ProjectCubit projectCubit; List? _cachedProducts; - SpaceManagementBloc(this._api, this._productApi, this._spaceModelApi) + SpaceManagementBloc( + this._api, this._productApi, this._spaceModelApi, this.projectCubit) : super(SpaceManagementInitial()) { on(_onLoadCommunityAndSpaces); on(_onUpdateSpacePosition); @@ -45,9 +49,11 @@ class SpaceManagementBloc ) async { final previousState = state; try { + final projectUuid = projectCubit.state; + emit(SpaceManagementLoading()); - final success = - await _api.updateCommunity(event.communityUuid, event.name); + final success = await _api.updateCommunity( + event.communityUuid, event.name, projectUuid ?? TempConst.projectId); if (success) { if (previousState is SpaceManagementLoaded) { final updatedCommunities = @@ -79,6 +85,8 @@ class SpaceManagementBloc Future> fetchSpaceModels( SpaceManagementState previousState) async { try { + final projectUuid = projectCubit.state; + List allSpaces = []; List prevSpaceModels = []; @@ -95,7 +103,8 @@ class SpaceManagementBloc int page = 1; while (hasNext) { - final spaces = await _spaceModelApi.listSpaceModels(page: page); + final spaces = await _spaceModelApi.listSpaceModels( + page: page, projectId: projectUuid ?? TempConst.projectId); if (spaces.isNotEmpty) { allSpaces.addAll(spaces); page++; @@ -103,7 +112,8 @@ class SpaceManagementBloc hasNext = false; } } - prevSpaceModels = await _spaceModelApi.listSpaceModels(page: 1); + prevSpaceModels = await _spaceModelApi.listSpaceModels( + page: 1, projectId: projectUuid ?? TempConst.projectId); } return allSpaces; @@ -132,7 +142,10 @@ class SpaceManagementBloc Future> _fetchSpacesForCommunity( String communityUuid) async { - return await _api.getSpaceHierarchy(communityUuid); + final projectUuid = projectCubit.state; + + return await _api.getSpaceHierarchy( + communityUuid, projectUuid ?? TempConst.projectId); } Future _onNewCommunity( @@ -163,6 +176,8 @@ class SpaceManagementBloc BlankStateEvent event, Emitter emit) async { try { final previousState = state; + final projectUuid = projectCubit.state; + var prevSpaceModels = await fetchSpaceModels(previousState); if (previousState is SpaceManagementLoaded || @@ -176,7 +191,8 @@ class SpaceManagementBloc return; } - final communities = await _api.fetchCommunities(); + final communities = + await _api.fetchCommunities(projectUuid ?? TempConst.projectId); final updatedCommunities = await Future.wait(communities.map((community) async { final spaces = await _fetchSpacesForCommunity(community.uuid); @@ -209,8 +225,11 @@ class SpaceManagementBloc var prevState = state; emit(SpaceManagementLoading()); try { + final projectUuid = projectCubit.state; + _onloadProducts(); - List communities = await _api.fetchCommunities(); + List communities = + await _api.fetchCommunities(projectUuid ?? TempConst.projectId); List updatedCommunities = await Future.wait( communities.map((community) async { @@ -244,8 +263,10 @@ class SpaceManagementBloc ) async { try { emit(SpaceManagementLoading()); + final projectUuid = projectCubit.state; - final success = await _api.deleteCommunity(event.communityUuid); + final success = await _api.deleteCommunity( + event.communityUuid, projectUuid ?? TempConst.projectId); if (success) { add(LoadCommunityAndSpacesEvent()); } else { @@ -270,8 +291,9 @@ class SpaceManagementBloc emit(SpaceManagementLoading()); try { - CommunityModel? newCommunity = - await _api.createCommunity(event.name, event.description); + final projectUuid = projectCubit.state; + CommunityModel? newCommunity = await _api.createCommunity( + event.name, event.description, projectUuid ?? TempConst.projectId); var prevSpaceModels = await fetchSpaceModels(previousState); if (newCommunity != null) { @@ -414,6 +436,7 @@ class SpaceManagementBloc Future> saveSpacesHierarchically( List spaces, String communityUuid) async { final orderedSpaces = flattenHierarchy(spaces); + final projectUuid = projectCubit.state; final parentsToDelete = orderedSpaces.where((space) => space.status == SpaceStatus.deleted && @@ -422,7 +445,8 @@ class SpaceManagementBloc for (var parent in parentsToDelete) { try { if (parent.uuid != null) { - await _api.deleteSpace(communityUuid, parent.uuid!); + await _api.deleteSpace( + communityUuid, parent.uuid!, projectUuid ?? TempConst.projectId); } } catch (e) { rethrow; @@ -435,7 +459,8 @@ class SpaceManagementBloc if (space.uuid != null && space.uuid!.isNotEmpty) { List tagUpdates = []; - final prevSpace = await _api.getSpace(communityUuid, space.uuid!); + final prevSpace = await _api.getSpace( + communityUuid, space.uuid!, projectUuid ?? TempConst.projectId); final List subspaceUpdates = []; final List? prevSubspaces = prevSpace?.subspaces; final List? newSubspaces = space.subspaces; @@ -504,17 +529,17 @@ class SpaceManagementBloc } final response = await _api.updateSpace( - communityId: communityUuid, - spaceId: space.uuid!, - name: space.name, - parentId: space.parent?.uuid, - isPrivate: space.isPrivate, - position: space.position, - icon: space.icon, - subspaces: subspaceUpdates, - tags: tagUpdates, - direction: space.incomingConnection?.direction, - ); + communityId: communityUuid, + spaceId: space.uuid!, + name: space.name, + parentId: space.parent?.uuid, + isPrivate: space.isPrivate, + position: space.position, + icon: space.icon, + subspaces: subspaceUpdates, + tags: tagUpdates, + direction: space.incomingConnection?.direction, + projectId: projectUuid ?? TempConst.projectId); } else { // Call create if the space does not have a UUID final List tagBodyModels = space.tags != null @@ -533,17 +558,17 @@ class SpaceManagementBloc []; final response = await _api.createSpace( - communityId: communityUuid, - name: space.name, - parentId: space.parent?.uuid, - isPrivate: space.isPrivate, - position: space.position, - icon: space.icon, - direction: space.incomingConnection?.direction, - spaceModelUuid: space.spaceModel?.uuid, - tags: tagBodyModels, - subspaces: createSubspaceBodyModels, - ); + communityId: communityUuid, + name: space.name, + parentId: space.parent?.uuid, + isPrivate: space.isPrivate, + position: space.position, + icon: space.icon, + direction: space.incomingConnection?.direction, + spaceModelUuid: space.spaceModel?.uuid, + tags: tagBodyModels, + subspaces: createSubspaceBodyModels, + projectId: projectUuid ?? TempConst.projectId); space.uuid = response?.uuid; } } catch (e) { @@ -583,8 +608,10 @@ class SpaceManagementBloc emit(SpaceManagementLoading()); try { var prevState = state; + final projectUuid = projectCubit.state; - List communities = await _api.fetchCommunities(); + List communities = + await _api.fetchCommunities(projectUuid ?? TempConst.projectId); List updatedCommunities = await Future.wait( communities.map((community) async { diff --git a/lib/pages/spaces_management/all_spaces/view/spaces_management_page.dart b/lib/pages/spaces_management/all_spaces/view/spaces_management_page.dart index 3abab9cc..4d03d11f 100644 --- a/lib/pages/spaces_management/all_spaces/view/spaces_management_page.dart +++ b/lib/pages/spaces_management/all_spaces/view/spaces_management_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart'; import 'package:syncrow_web/pages/spaces_management/structure_selector/bloc/center_body_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart'; @@ -28,8 +29,12 @@ class SpaceManagementPageState extends State { return MultiBlocProvider( providers: [ BlocProvider( - create: (_) => SpaceManagementBloc(_api, _productApi, _spaceModelApi) - ..add(LoadCommunityAndSpacesEvent()), + create: (_) => SpaceManagementBloc( + _api, + _productApi, + _spaceModelApi, + context.read(), + )..add(LoadCommunityAndSpacesEvent()), ), BlocProvider( create: (_) => CenterBodyBloc(), diff --git a/lib/pages/spaces_management/all_spaces/widgets/loaded_space_widget.dart b/lib/pages/spaces_management/all_spaces/widgets/loaded_space_widget.dart index d66970e6..626052cb 100644 --- a/lib/pages/spaces_management/all_spaces/widgets/loaded_space_widget.dart +++ b/lib/pages/spaces_management/all_spaces/widgets/loaded_space_widget.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; @@ -87,6 +88,7 @@ class _LoadedSpaceViewState extends State { child: BlocProvider( create: (context) => SpaceModelBloc( api: SpaceModelManagementApi(), + projectCubit: context.read(), initialSpaceModels: _spaceModels, ), child: SpaceModelPage( diff --git a/lib/pages/spaces_management/space_model/bloc/create_space_model_bloc.dart b/lib/pages/spaces_management/space_model/bloc/create_space_model_bloc.dart index 36efaaa5..bb609084 100644 --- a/lib/pages/spaces_management/space_model/bloc/create_space_model_bloc.dart +++ b/lib/pages/spaces_management/space_model/bloc/create_space_model_bloc.dart @@ -1,4 +1,5 @@ import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_space_model_event.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_space_model_state.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/create_space_template_body_model.dart'; @@ -8,16 +9,20 @@ import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart'; import 'package:syncrow_web/services/space_model_mang_api.dart'; import 'package:syncrow_web/utils/constants/action_enum.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; class CreateSpaceModelBloc extends Bloc { SpaceTemplateModel? _space; final SpaceModelManagementApi _api; + final ProjectCubit _projectCubit; - CreateSpaceModelBloc(this._api) : super(CreateSpaceModelInitial()) { + CreateSpaceModelBloc(this._api, this._projectCubit) + : super(CreateSpaceModelInitial()) { on((event, emit) async { try { + final projectUuid = _projectCubit.state; late SpaceTemplateModel spaceTemplate = event.spaceTemplate; final tagBodyModels = @@ -40,7 +45,8 @@ class CreateSpaceModelBloc tags: tagBodyModels, subspaceModels: subspaceTemplateBodyModels); - final newSpaceTemplate = await _api.createSpaceModel(spaceModelBody); + final newSpaceTemplate = await _api.createSpaceModel( + spaceModelBody, projectUuid ?? TempConst.projectId); spaceTemplate.uuid = newSpaceTemplate?.uuid ?? ''; if (newSpaceTemplate != null) { @@ -201,9 +207,12 @@ class CreateSpaceModelBloc on((event, emit) async { try { + final projectUuid = _projectCubit.state; + if (event.spaceTemplate.uuid != null) { - final prevSpaceModel = - await _api.getSpaceModel(event.spaceTemplate.uuid ?? ''); + final prevSpaceModel = await _api.getSpaceModel( + event.spaceTemplate.uuid ?? '', + projectUuid ?? TempConst.projectId); final newSpaceModel = event.updatedSpaceTemplate; String? spaceModelName; @@ -286,8 +295,8 @@ class CreateSpaceModelBloc tags: tagUpdates, subspaceModels: subspaceUpdates); - final res = await _api.updateSpaceModel( - spaceModelBody, prevSpaceModel?.uuid ?? ''); + final res = await _api.updateSpaceModel(spaceModelBody, + prevSpaceModel?.uuid ?? '', projectUuid ?? TempConst.projectId); if (res != null) { emit(CreateSpaceModelLoaded(newSpaceModel)); diff --git a/lib/pages/spaces_management/space_model/bloc/space_model_bloc.dart b/lib/pages/spaces_management/space_model/bloc/space_model_bloc.dart index 090dfa13..4464a829 100644 --- a/lib/pages/spaces_management/space_model/bloc/space_model_bloc.dart +++ b/lib/pages/spaces_management/space_model/bloc/space_model_bloc.dart @@ -1,14 +1,18 @@ import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_event.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_state.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; import 'package:syncrow_web/services/space_model_mang_api.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; class SpaceModelBloc extends Bloc { final SpaceModelManagementApi api; + final ProjectCubit projectCubit; SpaceModelBloc({ required this.api, + required this.projectCubit, required List initialSpaceModels, }) : super(SpaceModelLoaded(spaceModels: initialSpaceModels)) { on(_onCreateSpaceModel); @@ -18,10 +22,12 @@ class SpaceModelBloc extends Bloc { Future _onCreateSpaceModel( CreateSpaceModel event, Emitter emit) async { final currentState = state; + if (currentState is SpaceModelLoaded) { try { - final newSpaceModel = - await api.getSpaceModel(event.newSpaceModel.uuid ?? ''); + final projectUuid = projectCubit.state; + final newSpaceModel = await api.getSpaceModel( + event.newSpaceModel.uuid ?? '', projectUuid ?? TempConst.projectId); if (newSpaceModel != null) { final updatedSpaceModels = @@ -40,8 +46,10 @@ class SpaceModelBloc extends Bloc { final currentState = state; if (currentState is SpaceModelLoaded) { try { - final newSpaceModel = - await api.getSpaceModel(event.spaceModelUuid ?? ''); + final projectUuid = projectCubit.state; + + final newSpaceModel = await api.getSpaceModel( + event.spaceModelUuid ?? '', projectUuid ?? TempConst.projectId); if (newSpaceModel != null) { final updatedSpaceModels = currentState.spaceModels.map((model) { return model.uuid == event.spaceModelUuid ? newSpaceModel : model; diff --git a/lib/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart b/lib/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart index dd41903e..5beb1fc1 100644 --- a/lib/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart +++ b/lib/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/common/buttons/cancel_button.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart'; @@ -50,7 +51,10 @@ class CreateSpaceModelDialog extends StatelessWidget { width: screenWidth * 0.3, child: BlocProvider( create: (_) { - final bloc = CreateSpaceModelBloc(_spaceModelApi); + final bloc = CreateSpaceModelBloc( + _spaceModelApi, + context.read(), + ); if (spaceModel != null) { bloc.add(UpdateSpaceTemplate(spaceModel!, otherSpaceModels)); } else { diff --git a/lib/services/devices_mang_api.dart b/lib/services/devices_mang_api.dart index 1a8b979e..d671038f 100644 --- a/lib/services/devices_mang_api.dart +++ b/lib/services/devices_mang_api.dart @@ -12,14 +12,14 @@ import 'package:syncrow_web/utils/constants/api_const.dart'; import 'package:syncrow_web/utils/constants/temp_const.dart'; class DevicesManagementApi { - Future> fetchDevices(String communityId, String spaceId) async { + Future> fetchDevices(String communityId, String spaceId, String projectId) async { try { final response = await HTTPService().get( path: communityId.isNotEmpty && spaceId.isNotEmpty ? ApiEndpoints.getSpaceDevices .replaceAll('{spaceUuid}', spaceId) .replaceAll('{communityUuid}', communityId) - .replaceAll('{projectId}', TempConst.projectId) + .replaceAll('{projectId}', projectId) : ApiEndpoints.getAllDevices, showServerMessage: true, expectedResponseModel: (json) { diff --git a/lib/services/routines_api.dart b/lib/services/routines_api.dart index aae7c453..9360820c 100644 --- a/lib/services/routines_api.dart +++ b/lib/services/routines_api.dart @@ -12,7 +12,8 @@ class SceneApi { static final HTTPService _httpService = HTTPService(); // //create scene - static Future> createScene(CreateSceneModel createSceneModel) async { + static Future> createScene( + CreateSceneModel createSceneModel) async { try { debugPrint('create scene model: ${createSceneModel.toMap()}'); final response = await _httpService.post( @@ -69,14 +70,15 @@ class SceneApi { //get scenes by community id and space id - static Future> getScenes(String spaceId, String communityId, + static Future> getScenes( + String spaceId, String communityId, String projectId, {showInDevice = false}) async { try { final response = await _httpService.get( path: ApiEndpoints.getUnitScenes .replaceAll('{spaceUuid}', spaceId) .replaceAll('{communityUuid}', communityId) - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), queryParameters: {'showInHomePage': showInDevice}, showServerMessage: false, expectedResponseModel: (json) { @@ -100,7 +102,8 @@ class SceneApi { static Future> getAutomation(String spaceId) async { try { final response = await _httpService.get( - path: ApiEndpoints.getSpaceAutomation.replaceAll('{spaceUuid}', spaceId), + path: + ApiEndpoints.getSpaceAutomation.replaceAll('{spaceUuid}', spaceId), showServerMessage: false, expectedResponseModel: (json) { List scenes = []; @@ -130,10 +133,12 @@ class SceneApi { // } //automation details - static Future getAutomationDetails(String automationId) async { + static Future getAutomationDetails( + String automationId) async { try { final response = await _httpService.get( - path: ApiEndpoints.getAutomationDetails.replaceAll('{automationId}', automationId), + path: ApiEndpoints.getAutomationDetails + .replaceAll('{automationId}', automationId), showServerMessage: false, expectedResponseModel: (json) => RoutineDetailsModel.fromMap(json), ); @@ -148,7 +153,8 @@ class SceneApi { try { final response = await _httpService.put( path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId), - body: createSceneModel.toJson(sceneId.isNotEmpty == true ? sceneId : null), + body: createSceneModel + .toJson(sceneId.isNotEmpty == true ? sceneId : null), expectedResponseModel: (json) { return json; }, @@ -160,11 +166,14 @@ class SceneApi { } //update automation - static updateAutomation(CreateAutomationModel createAutomationModel, String automationId) async { + static updateAutomation( + CreateAutomationModel createAutomationModel, String automationId) async { try { final response = await _httpService.put( - path: ApiEndpoints.updateAutomation.replaceAll('{automationId}', automationId), - body: createAutomationModel.toJson(automationId.isNotEmpty == true ? automationId : null), + path: ApiEndpoints.updateAutomation + .replaceAll('{automationId}', automationId), + body: createAutomationModel + .toJson(automationId.isNotEmpty == true ? automationId : null), expectedResponseModel: (json) { return json; }, @@ -181,7 +190,8 @@ class SceneApi { final response = await _httpService.get( path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId), showServerMessage: false, - expectedResponseModel: (json) => RoutineDetailsModel.fromMap(json['data']), + expectedResponseModel: (json) => + RoutineDetailsModel.fromMap(json['data']), ); return response; } catch (e) { @@ -190,7 +200,8 @@ class SceneApi { } //delete Scene - static Future deleteScene({required String unitUuid, required String sceneId}) async { + static Future deleteScene( + {required String unitUuid, required String sceneId}) async { try { final response = await _httpService.delete( path: ApiEndpoints.deleteScene diff --git a/lib/services/space_mana_api.dart b/lib/services/space_mana_api.dart index c4877c98..2361dd1d 100644 --- a/lib/services/space_mana_api.dart +++ b/lib/services/space_mana_api.dart @@ -13,7 +13,8 @@ import 'package:syncrow_web/utils/constants/temp_const.dart'; class CommunitySpaceManagementApi { // Community Management APIs - Future> fetchCommunities({int page = 1}) async { + Future> fetchCommunities(String projectId, + {int page = 1}) async { try { List allCommunities = []; bool hasNext = true; @@ -21,7 +22,7 @@ class CommunitySpaceManagementApi { while (hasNext) { await HTTPService().get( path: ApiEndpoints.getCommunityList - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), queryParameters: {'page': page}, expectedResponseModel: (json) { try { @@ -65,11 +66,10 @@ class CommunitySpaceManagementApi { } Future createCommunity( - String name, String description) async { + String name, String description, String projectId) async { try { final response = await HTTPService().post( - path: ApiEndpoints.createCommunity - .replaceAll('{projectId}', TempConst.projectId), + path: ApiEndpoints.createCommunity.replaceAll('{projectId}', projectId), body: { 'name': name, 'description': description, @@ -85,12 +85,13 @@ class CommunitySpaceManagementApi { } } - Future updateCommunity(String communityId, String name) async { + Future updateCommunity( + String communityId, String name, String projectId) async { try { final response = await HTTPService().put( path: ApiEndpoints.updateCommunity .replaceAll('{communityId}', communityId) - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), body: { 'name': name, }, @@ -105,12 +106,12 @@ class CommunitySpaceManagementApi { } } - Future deleteCommunity(String communityId) async { + Future deleteCommunity(String communityId, String projectId) async { try { final response = await HTTPService().delete( path: ApiEndpoints.deleteCommunity .replaceAll('{communityId}', communityId) - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), expectedResponseModel: (json) { return json['success'] ?? false; }, @@ -122,12 +123,13 @@ class CommunitySpaceManagementApi { } } - Future fetchSpaces(String communityId) async { + Future fetchSpaces( + String communityId, String projectId) async { try { final response = await HTTPService().get( path: ApiEndpoints.listSpaces .replaceAll('{communityId}', communityId) - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), expectedResponseModel: (json) { return SpacesResponse.fromJson(json); }, @@ -148,13 +150,14 @@ class CommunitySpaceManagementApi { } } - Future getSpace(String communityId, String spaceId) async { + Future getSpace( + String communityId, String spaceId, String projectId) async { try { final response = await HTTPService().get( path: ApiEndpoints.getSpace .replaceAll('{communityId}', communityId) .replaceAll('{spaceId}', spaceId) - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), expectedResponseModel: (json) { return SpaceModel.fromJson(json['data']); }, @@ -176,7 +179,8 @@ class CommunitySpaceManagementApi { String? spaceModelUuid, String? icon, List? tags, - List? subspaces}) async { + List? subspaces, + required String projectId}) async { try { final body = { 'spaceName': name, @@ -199,7 +203,7 @@ class CommunitySpaceManagementApi { final response = await HTTPService().post( path: ApiEndpoints.createSpace .replaceAll('{communityId}', communityId) - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), body: body, expectedResponseModel: (json) { return SpaceModel.fromJson(json['data']); @@ -212,18 +216,18 @@ class CommunitySpaceManagementApi { } } - Future updateSpace({ - required String communityId, - required spaceId, - required String name, - String? parentId, - String? icon, - String? direction, - bool isPrivate = false, - required Offset position, - List? tags, - List? subspaces, - }) async { + Future updateSpace( + {required String communityId, + required spaceId, + required String name, + String? parentId, + String? icon, + String? direction, + bool isPrivate = false, + required Offset position, + List? tags, + List? subspaces, + required String projectId}) async { try { final body = { 'spaceName': name, @@ -243,7 +247,7 @@ class CommunitySpaceManagementApi { path: ApiEndpoints.updateSpace .replaceAll('{communityId}', communityId) .replaceAll('{spaceId}', spaceId) - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), body: body, expectedResponseModel: (json) { return json['success'] ?? false; @@ -256,13 +260,14 @@ class CommunitySpaceManagementApi { } } - Future deleteSpace(String communityId, String spaceId) async { + Future deleteSpace( + String communityId, String spaceId, String projectId) async { try { final response = await HTTPService().delete( path: ApiEndpoints.deleteSpace .replaceAll('{communityId}', communityId) .replaceAll('{spaceId}', spaceId) - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), expectedResponseModel: (json) { return json['success'] ?? false; }, @@ -274,12 +279,13 @@ class CommunitySpaceManagementApi { } } - Future> getSpaceHierarchy(String communityId) async { + Future> getSpaceHierarchy( + String communityId, String projectId) async { try { final response = await HTTPService().get( path: ApiEndpoints.getSpaceHierarchy .replaceAll('{communityId}', communityId) - .replaceAll('{projectId}', TempConst.projectId), + .replaceAll('{projectId}', projectId), expectedResponseModel: (json) { final spaceModels = (json['data'] as List) .map((spaceJson) => SpaceModel.fromJson(spaceJson)) diff --git a/lib/services/space_model_mang_api.dart b/lib/services/space_model_mang_api.dart index eb896432..d9e295e0 100644 --- a/lib/services/space_model_mang_api.dart +++ b/lib/services/space_model_mang_api.dart @@ -5,10 +5,10 @@ import 'package:syncrow_web/utils/constants/api_const.dart'; import 'package:syncrow_web/utils/constants/temp_const.dart'; class SpaceModelManagementApi { - Future> listSpaceModels({int page = 1}) async { + Future> listSpaceModels( + {required String projectId, int page = 1}) async { final response = await HTTPService().get( - path: ApiEndpoints.listSpaceModels - .replaceAll('{projectId}', TempConst.projectId), + path: ApiEndpoints.listSpaceModels.replaceAll('{projectId}', projectId), queryParameters: {'page': page}, expectedResponseModel: (json) { List jsonData = json['data']; @@ -21,10 +21,9 @@ class SpaceModelManagementApi { } Future createSpaceModel( - CreateSpaceTemplateBodyModel spaceModel) async { + CreateSpaceTemplateBodyModel spaceModel, String projectId) async { final response = await HTTPService().post( - path: ApiEndpoints.createSpaceModel - .replaceAll('{projectId}', TempConst.projectId), + path: ApiEndpoints.createSpaceModel.replaceAll('{projectId}', projectId), showServerMessage: true, body: spaceModel.toJson(), expectedResponseModel: (json) { @@ -34,12 +33,12 @@ class SpaceModelManagementApi { return response; } - - Future updateSpaceModel( - CreateSpaceTemplateBodyModel spaceModel, String spaceModelUuid) async { + Future updateSpaceModel(CreateSpaceTemplateBodyModel spaceModel, + String spaceModelUuid, String projectId) async { final response = await HTTPService().put( path: ApiEndpoints.updateSpaceModel - .replaceAll('{projectId}', TempConst.projectId).replaceAll('{spaceModelUuid}', spaceModelUuid), + .replaceAll('{projectId}', projectId) + .replaceAll('{spaceModelUuid}', spaceModelUuid), body: spaceModel.toJson(), expectedResponseModel: (json) { return json['message']; @@ -48,10 +47,11 @@ class SpaceModelManagementApi { return response; } - Future getSpaceModel(String spaceModelUuid) async { + Future getSpaceModel( + String spaceModelUuid, String projectId) async { final response = await HTTPService().get( path: ApiEndpoints.getSpaceModel - .replaceAll('{projectId}', TempConst.projectId) + .replaceAll('{projectId}', projectId) .replaceAll('{spaceModelUuid}', spaceModelUuid), showServerMessage: true, expectedResponseModel: (json) { diff --git a/lib/services/user_permission.dart b/lib/services/user_permission.dart index e4f097f4..a3fb2d96 100644 --- a/lib/services/user_permission.dart +++ b/lib/services/user_permission.dart @@ -11,10 +11,10 @@ import 'package:syncrow_web/utils/constants/api_const.dart'; class UserPermissionApi { static final HTTPService _httpService = HTTPService(); - Future> fetchUsers() async { + Future> fetchUsers(String projectId) async { try { final response = await _httpService.get( - path: ApiEndpoints.getUsers, + path: ApiEndpoints.getUsers.replaceAll('{projectUuid}', projectId), showServerMessage: true, expectedResponseModel: (json) { debugPrint('fetchUsers Response: $json'); @@ -34,8 +34,9 @@ class UserPermissionApi { path: ApiEndpoints.roleTypes, showServerMessage: true, expectedResponseModel: (json) { - final List fetchedRoles = - (json['data'] as List).map((item) => RoleTypeModel.fromJson(item)).toList(); + final List fetchedRoles = (json['data'] as List) + .map((item) => RoleTypeModel.fromJson(item)) + .toList(); return fetchedRoles; }, ); @@ -47,7 +48,9 @@ class UserPermissionApi { path: ApiEndpoints.permission.replaceAll("roleUuid", roleUuid), showServerMessage: true, expectedResponseModel: (json) { - return (json as List).map((data) => PermissionOption.fromJson(data)).toList(); + return (json as List) + .map((data) => PermissionOption.fromJson(data)) + .toList(); }, ); return response ?? []; @@ -61,6 +64,7 @@ class UserPermissionApi { String? phoneNumber, String? roleUuid, List? spaceUuids, + required String projectUuid, }) async { try { final body = { @@ -70,7 +74,7 @@ class UserPermissionApi { "jobTitle": jobTitle != '' ? jobTitle : null, "phoneNumber": phoneNumber != '' ? phoneNumber : null, "roleUuid": roleUuid, - "projectUuid": "0e62577c-06fa-41b9-8a92-99a21fbaf51c", + "projectUuid": projectUuid, "spaceUuids": spaceUuids, }; final response = await _httpService.post( @@ -121,9 +125,11 @@ class UserPermissionApi { } } - Future fetchUserById(userUuid) async { + Future fetchUserById(userUuid, String projectId) async { final response = await _httpService.get( - path: ApiEndpoints.getUserById.replaceAll("{userUuid}", userUuid), + path: ApiEndpoints.getUserById + .replaceAll("{userUuid}", userUuid) + .replaceAll("{projectId}", projectId), showServerMessage: true, expectedResponseModel: (json) { EditUserModel res = EditUserModel.fromJson(json['data']); @@ -141,6 +147,7 @@ class UserPermissionApi { String? phoneNumber, String? roleUuid, List? spaceUuids, + required String projectUuid, }) async { try { final body = { @@ -149,7 +156,7 @@ class UserPermissionApi { "jobTitle": jobTitle != '' ? jobTitle : " ", "phoneNumber": phoneNumber != '' ? phoneNumber : " ", "roleUuid": roleUuid, - "projectUuid": "0e62577c-06fa-41b9-8a92-99a21fbaf51c", + "projectUuid": projectUuid, "spaceUuids": spaceUuids, }; final response = await _httpService.put( @@ -186,15 +193,16 @@ class UserPermissionApi { } } - Future changeUserStatusById(userUuid, status) async { + Future changeUserStatusById(userUuid, status, String projectUuid) async { try { Map bodya = { "disable": status, - "projectUuid": "0e62577c-06fa-41b9-8a92-99a21fbaf51c" + "projectUuid": projectUuid }; final response = await _httpService.put( - path: ApiEndpoints.changeUserStatus.replaceAll("{invitedUserUuid}", userUuid), + path: ApiEndpoints.changeUserStatus + .replaceAll("{invitedUserUuid}", userUuid), body: bodya, expectedResponseModel: (json) { return json['success']; diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index 80c3c830..ee41cfa0 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -95,8 +95,8 @@ abstract class ApiEndpoints { static const String inviteUser = '/invite-user'; static const String checkEmail = '/invite-user/check-email'; - static const String getUsers = '/projects/${projectUuid}/user'; - static const String getUserById = '/projects/${projectUuid}/user/{userUuid}'; + static const String getUsers = '/projects/{projectUuid}/user'; + static const String getUserById = '/projects/{projectUuid}/user/{userUuid}'; static const String editUser = '/invite-user/{inviteUserUuid}'; static const String deleteUser = '/invite-user/{inviteUserUuid}'; static const String changeUserStatus = '/invite-user/{invitedUserUuid}/disable'; diff --git a/lib/utils/user_drop_down_menu.dart b/lib/utils/user_drop_down_menu.dart index 2d740e27..b0028843 100644 --- a/lib/utils/user_drop_down_menu.dart +++ b/lib/utils/user_drop_down_menu.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart'; import 'package:syncrow_web/pages/auth/model/user_model.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; @@ -218,7 +220,10 @@ class _UserDropdownMenuState extends State { ), GestureDetector( onTap: () { - AuthBloc.logout(); + final projectCubit = + BlocProvider.of(context); + + AuthBloc.logout(context, projectCubit); context.go(RoutesConst.auth); }, child: SizedBox( From 581dcf7016bfbda233e4151bb0cf945c1107e00b Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Sun, 16 Feb 2025 23:32:46 +0400 Subject: [PATCH 4/6] changed endpoint for get visitor password and access control --- lib/main.dart | 2 +- .../access_management/bloc/access_bloc.dart | 14 +++- .../view/access_management.dart | 3 +- .../bloc/visitor_password_bloc.dart | 77 +++++++++++++------ .../view/add_device_dialog.dart | 3 +- .../view/visitor_password_dialog.dart | 3 +- lib/services/access_mang_api.dart | 17 ++-- lib/services/devices_mang_api.dart | 2 +- lib/utils/constants/api_const.dart | 6 +- 9 files changed, 84 insertions(+), 43 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index fe14241e..ffd18f31 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -58,7 +58,7 @@ class MyApp extends StatelessWidget { BlocProvider( create: (context) => HomeBloc(projectCubit)..add(const FetchUserInfo())), BlocProvider( - create: (context) => VisitorPasswordBloc(), + create: (context) => VisitorPasswordBloc(projectCubit), ), BlocProvider( create: (context) => RoutineBloc(projectCubit), diff --git a/lib/pages/access_management/bloc/access_bloc.dart b/lib/pages/access_management/bloc/access_bloc.dart index 3e74dbff..ac94036c 100644 --- a/lib/pages/access_management/bloc/access_bloc.dart +++ b/lib/pages/access_management/bloc/access_bloc.dart @@ -3,14 +3,18 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/access_management/bloc/access_event.dart'; import 'package:syncrow_web/pages/access_management/bloc/access_state.dart'; import 'package:syncrow_web/pages/access_management/model/password_model.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/common/hour_picker_dialog.dart'; import 'package:syncrow_web/services/access_mang_api.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/app_enum.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; import 'package:syncrow_web/utils/snack_bar.dart'; class AccessBloc extends Bloc { - AccessBloc() : super((AccessInitial())) { + final ProjectCubit projectCubit; + + AccessBloc(this.projectCubit) : super((AccessInitial())) { on(_onFetchTableData); on(selectTime); on(_filterData); @@ -30,8 +34,10 @@ class AccessBloc extends Bloc { Future _onFetchTableData( FetchTableData event, Emitter emit) async { try { + final projectUuid = projectCubit.state; emit(AccessLoaded()); - data = await AccessMangApi().fetchVisitorPassword(); + data = await AccessMangApi() + .fetchVisitorPassword(projectUuid ?? TempConst.projectId); filteredData = data; updateTabsCount(); emit(TableLoaded(data)); @@ -88,8 +94,8 @@ class AccessBloc extends Bloc { return Theme( data: ThemeData.light().copyWith( colorScheme: ColorScheme.light( - primary: ColorsManager.blackColor, - onPrimary: Colors.white, + primary: ColorsManager.blackColor, + onPrimary: Colors.white, onSurface: ColorsManager.grayColor, ), textButtonTheme: TextButtonThemeData( diff --git a/lib/pages/access_management/view/access_management.dart b/lib/pages/access_management/view/access_management.dart index 9fe3a722..620dd566 100644 --- a/lib/pages/access_management/view/access_management.dart +++ b/lib/pages/access_management/view/access_management.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/access_management/bloc/access_bloc.dart'; import 'package:syncrow_web/pages/access_management/bloc/access_event.dart'; import 'package:syncrow_web/pages/access_management/bloc/access_state.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; import 'package:syncrow_web/pages/common/buttons/search_reset_buttons.dart'; import 'package:syncrow_web/pages/common/custom_table.dart'; @@ -39,7 +40,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout { ), rightBody: const NavigateHomeGridView(), scaffoldBody: BlocProvider( - create: (BuildContext context) => AccessBloc()..add(FetchTableData()), + create: (BuildContext context) => AccessBloc(context.read())..add(FetchTableData()), child: BlocConsumer( listener: (context, state) {}, builder: (context, state) { diff --git a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart index aeb53260..02dc0dd3 100644 --- a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart +++ b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart @@ -3,6 +3,7 @@ import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/common/custom_dialog.dart'; import 'package:syncrow_web/pages/common/hour_picker_dialog.dart'; import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart'; @@ -13,10 +14,14 @@ import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart'; import 'package:syncrow_web/services/access_mang_api.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/constants/temp_const.dart'; import 'package:syncrow_web/utils/snack_bar.dart'; -class VisitorPasswordBloc extends Bloc { - VisitorPasswordBloc() : super(VisitorPasswordInitial()) { +class VisitorPasswordBloc + extends Bloc { + final ProjectCubit projectCubit; + + VisitorPasswordBloc(this.projectCubit) : super(VisitorPasswordInitial()) { on(selectUsageFrequency); on(_onFetchDevice); on(selectAccessType); @@ -38,7 +43,8 @@ class VisitorPasswordBloc extends Bloc selectedDevices = []; List data = []; @@ -64,12 +70,14 @@ class VisitorPasswordBloc extends Bloc emit) { + selectAccessType( + SelectPasswordType event, Emitter emit) { accessTypeSelected = event.type; emit(PasswordTypeSelected(event.type)); } - selectUsageFrequency(SelectUsageFrequency event, Emitter emit) { + selectUsageFrequency( + SelectUsageFrequency event, Emitter emit) { usageFrequencySelected = event.usageType; emit(UsageFrequencySelected(event.usageType)); } @@ -116,10 +124,12 @@ class VisitorPasswordBloc extends Bloc expirationTimeTimeStamp!) { + if (expirationTimeTimeStamp != null && + selectedTimestamp > expirationTimeTimeStamp!) { CustomSnackBar.displaySnackBar( 'Effective Time cannot be later than Expiration Time.', ); @@ -128,7 +138,8 @@ class VisitorPasswordBloc extends Bloc emit) { + bool toggleRepeat( + ToggleRepeatEvent event, Emitter emit) { emit(LoadingInitialState()); repeat = !repeat; emit(IsRepeatState(repeat: repeat)); @@ -175,10 +187,14 @@ class VisitorPasswordBloc extends Bloc _onFetchDevice(FetchDevice event, Emitter emit) async { + Future _onFetchDevice( + FetchDevice event, Emitter emit) async { try { emit(DeviceLoaded()); - data = await AccessMangApi().fetchDevices(); + final projectUuid = projectCubit.state; + + data = await AccessMangApi() + .fetchDevices(projectUuid ?? TempConst.projectId); emit(TableLoaded(data)); } catch (e) { emit(FailedState(e.toString())); @@ -186,8 +202,8 @@ class VisitorPasswordBloc extends Bloc postOnlineOneTimePassword( - OnlineOneTimePasswordEvent event, Emitter emit) async { + Future postOnlineOneTimePassword(OnlineOneTimePasswordEvent event, + Emitter emit) async { try { emit(LoadingInitialState()); generate7DigitNumber(); @@ -211,7 +227,8 @@ class VisitorPasswordBloc extends Bloc postOnlineMultipleTimePassword( - OnlineMultipleTimePasswordEvent event, Emitter emit) async { + OnlineMultipleTimePasswordEvent event, + Emitter emit) async { try { emit(LoadingInitialState()); @@ -221,7 +238,8 @@ class VisitorPasswordBloc extends Bloc postOfflineOneTimePassword( - OfflineOneTimePasswordEvent event, Emitter emit) async { + Future postOfflineOneTimePassword(OfflineOneTimePasswordEvent event, + Emitter emit) async { try { emit(LoadingInitialState()); await generate7DigitNumber(); var res = await AccessMangApi().postOffLineOneTime( - email: event.email, devicesUuid: selectedDevices, passwordName: event.passwordName); + email: event.email, + devicesUuid: selectedDevices, + passwordName: event.passwordName); if (res['statusCode'] == 201) { passwordStatus = PasswordStatus.fromJson(res['data']); emit(SuccessState()); @@ -264,7 +284,8 @@ class VisitorPasswordBloc extends Bloc postOfflineMultipleTimePassword( - OfflineMultipleTimePasswordEvent event, Emitter emit) async { + OfflineMultipleTimePasswordEvent event, + Emitter emit) async { try { emit(LoadingInitialState()); await generate7DigitNumber(); @@ -287,7 +308,8 @@ class VisitorPasswordBloc extends Bloc emit) { + void selectDevice( + SelectDeviceEvent event, Emitter emit) { if (selectedDeviceIds.contains(event.deviceId)) { selectedDeviceIds.remove(event.deviceId); } else { @@ -329,7 +351,8 @@ class VisitorPasswordBloc extends Bloc mapEventToState(VisitorPasswordEvent event) async* { + Stream mapEventToState( + VisitorPasswordEvent event) async* { if (event is FetchDevice) { } else if (event is UpdateFilteredDevicesEvent) { yield TableLoaded(event.filteredData); @@ -378,16 +401,20 @@ class VisitorPasswordBloc extends Bloc expirationTimeTimeStamp!) { - accessPeriodValidate = "Effective Time cannot be later than Expiration Time."; + if (expirationTimeTimeStamp != null && + selectedTimestamp > expirationTimeTimeStamp!) { + accessPeriodValidate = + "Effective Time cannot be later than Expiration Time."; } else { accessPeriodValidate = ''; effectiveTime = selectedDateTime.toString().split('.').first; effectiveTimeTimeStamp = selectedTimestamp; } } else { - if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) { - accessPeriodValidate = 'Expiration Time cannot be earlier than Effective Time.'; + if (effectiveTimeTimeStamp != null && + selectedTimestamp < effectiveTimeTimeStamp!) { + accessPeriodValidate = + 'Expiration Time cannot be earlier than Effective Time.'; } else { accessPeriodValidate = ''; expirationTime = selectedDateTime.toString().split('.').first; diff --git a/lib/pages/visitor_password/view/add_device_dialog.dart b/lib/pages/visitor_password/view/add_device_dialog.dart index ebc41292..f560b390 100644 --- a/lib/pages/visitor_password/view/add_device_dialog.dart +++ b/lib/pages/visitor_password/view/add_device_dialog.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_web/pages/common/access_device_table.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart'; @@ -19,7 +20,7 @@ class AddDeviceDialog extends StatelessWidget { Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return BlocProvider( - create: (context) => VisitorPasswordBloc()..add(FetchDevice()), + create: (context) => VisitorPasswordBloc(context.read())..add(FetchDevice()), child: BlocBuilder( builder: (BuildContext context, VisitorPasswordState state) { final visitorBloc = BlocProvider.of(context); diff --git a/lib/pages/visitor_password/view/visitor_password_dialog.dart b/lib/pages/visitor_password/view/visitor_password_dialog.dart index 1f014352..d610e36e 100644 --- a/lib/pages/visitor_password/view/visitor_password_dialog.dart +++ b/lib/pages/visitor_password/view/visitor_password_dialog.dart @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; import 'package:syncrow_web/pages/common/date_time_widget.dart'; import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart'; @@ -22,7 +23,7 @@ class VisitorPasswordDialog extends StatelessWidget { Size size = MediaQuery.of(context).size; var text = Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black, fontSize: 13); return BlocProvider( - create: (context) => VisitorPasswordBloc(), + create: (context) => VisitorPasswordBloc(context.read()), child: BlocListener( listener: (context, state) { final visitorBloc = BlocProvider.of(context); diff --git a/lib/services/access_mang_api.dart b/lib/services/access_mang_api.dart index 103f6121..6acbc395 100644 --- a/lib/services/access_mang_api.dart +++ b/lib/services/access_mang_api.dart @@ -6,10 +6,10 @@ import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/utils/constants/api_const.dart'; class AccessMangApi { - Future> fetchVisitorPassword() async { + Future> fetchVisitorPassword(String projectId) async { try { final response = await HTTPService().get( - path: ApiEndpoints.visitorPassword, + path: ApiEndpoints.visitorPassword.replaceAll('{projectId}', projectId), showServerMessage: true, expectedResponseModel: (json) { List jsonData = json; @@ -25,10 +25,10 @@ class AccessMangApi { } } - Future fetchDevices() async { + Future fetchDevices(String projectId) async { try { final response = await HTTPService().get( - path: ApiEndpoints.getDevices, + path: ApiEndpoints.getDevices.replaceAll('{projectId}', projectId), showServerMessage: true, expectedResponseModel: (json) { List jsonData = json; @@ -86,7 +86,8 @@ class AccessMangApi { "invalidTime": invalidTime, }; if (scheduleList != null) { - body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList(); + body["scheduleList"] = + scheduleList.map((schedule) => schedule.toJson()).toList(); } final response = await HTTPService().post( path: ApiEndpoints.sendOnlineMultipleTime, @@ -105,7 +106,11 @@ class AccessMangApi { {String? email, String? passwordName, List? devicesUuid}) async { final response = await HTTPService().post( path: ApiEndpoints.sendOffLineOneTime, - body: jsonEncode({"email": email, "passwordName": passwordName, "devicesUuid": devicesUuid}), + body: jsonEncode({ + "email": email, + "passwordName": passwordName, + "devicesUuid": devicesUuid + }), showServerMessage: true, expectedResponseModel: (json) { return json; diff --git a/lib/services/devices_mang_api.dart b/lib/services/devices_mang_api.dart index d671038f..655c6a83 100644 --- a/lib/services/devices_mang_api.dart +++ b/lib/services/devices_mang_api.dart @@ -20,7 +20,7 @@ class DevicesManagementApi { .replaceAll('{spaceUuid}', spaceId) .replaceAll('{communityUuid}', communityId) .replaceAll('{projectId}', projectId) - : ApiEndpoints.getAllDevices, + : ApiEndpoints.getAllDevices.replaceAll('{projectId}', projectId), showServerMessage: true, expectedResponseModel: (json) { List jsonData = diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index ee41cfa0..72a2b778 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -9,8 +9,8 @@ abstract class ApiEndpoints { static const String sendOtp = '/authentication/user/send-otp'; static const String verifyOtp = '/authentication/user/verify-otp'; static const String getRegion = '/region'; - static const String visitorPassword = '/visitor-password'; - static const String getDevices = '/visitor-password/devices'; + static const String visitorPassword = '/projects/{projectId}/visitor-password'; + static const String getDevices = '/projects/{projectId}/visitor-password/devices'; static const String sendOnlineOneTime = '/visitor-password/temporary-password/online/one-time'; static const String sendOnlineMultipleTime = @@ -25,7 +25,7 @@ abstract class ApiEndpoints { ////// Devices Management //////////////// - static const String getAllDevices = '/device'; + static const String getAllDevices = '/projects/{projectId}/device'; static const String getSpaceDevices = '/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/devices'; static const String getDeviceStatus = '/device/{uuid}/functions/status'; From 0aa029a2fc56da3154c128f9c67bee5e50fcfd66 Mon Sep 17 00:00:00 2001 From: Abdullah Alassaf Date: Mon, 17 Feb 2025 03:32:40 +0300 Subject: [PATCH 5/6] Removed static space id and community id in the routine --- lib/common/widgets/search_bar.dart | 26 +- lib/common/widgets/spaces_side_tree.dart | 25 -- lib/main.dart | 9 +- .../view/device_managment_page.dart | 4 +- .../bloc/routine_bloc/routine_bloc.dart | 268 ++++++++---------- .../bloc/routine_bloc/routine_event.dart | 16 +- lib/pages/routines/view/routines_view.dart | 28 +- .../fetch_routine_scenes_automation.dart | 4 - .../routines/widgets/routine_devices.dart | 13 +- .../widgets/scenes_and_automations.dart | 6 +- .../space_tree/bloc/space_tree_bloc.dart | 90 +++--- .../space_tree/bloc/space_tree_state.dart | 13 +- .../space_tree/view/space_tree_view.dart | 1 + 13 files changed, 248 insertions(+), 255 deletions(-) delete mode 100644 lib/common/widgets/spaces_side_tree.dart diff --git a/lib/common/widgets/search_bar.dart b/lib/common/widgets/search_bar.dart index 9d17d1c1..a99ac510 100644 --- a/lib/common/widgets/search_bar.dart +++ b/lib/common/widgets/search_bar.dart @@ -3,18 +3,33 @@ import 'package:flutter_svg/svg.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; -class CustomSearchBar extends StatelessWidget { +class CustomSearchBar extends StatefulWidget { final TextEditingController? controller; final String hintText; + final String? searchQuery; final Function(String)? onSearchChanged; // Callback for search input changes const CustomSearchBar({ super.key, this.controller, + this.searchQuery = '', this.hintText = 'Search', this.onSearchChanged, }); + @override + State createState() => _CustomSearchBarState(); +} + +class _CustomSearchBarState extends State { + @override + void dispose() { + if (widget.controller != null) { + widget.controller!.dispose(); + } + super.dispose(); + } + @override Widget build(BuildContext context) { return Container( @@ -36,16 +51,17 @@ class CustomSearchBar extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), ), - child: TextField( - controller: controller, + child: TextFormField( + controller: widget.controller, + initialValue: widget.searchQuery, style: const TextStyle( color: Colors.black, ), - onChanged: onSearchChanged, // Call the callback on text change + onChanged: widget.onSearchChanged, // Call the callback on text change decoration: InputDecoration( filled: true, fillColor: ColorsManager.textFieldGreyColor, - hintText: hintText, + hintText: widget.hintText, hintStyle: Theme.of(context).textTheme.bodyLarge!.copyWith( color: ColorsManager.lightGrayColor, fontSize: 12, diff --git a/lib/common/widgets/spaces_side_tree.dart b/lib/common/widgets/spaces_side_tree.dart deleted file mode 100644 index b77b0dc5..00000000 --- a/lib/common/widgets/spaces_side_tree.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; - -class SpacesSideTree extends StatefulWidget { - final List communities; - final String? selectedSpaceUuid; - const SpacesSideTree({ - super.key, - required this.communities, - this.selectedSpaceUuid, - }); - - @override - State createState() => _SpacesSideTreeState(); -} - -class _SpacesSideTreeState extends State { - String _searchQuery = ''; - String? _selectedSpaceUuid; - String? _selectedId; - @override - Widget build(BuildContext context) { - return const Placeholder(); - } -} diff --git a/lib/main.dart b/lib/main.dart index ffd18f31..72895e94 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,12 +15,12 @@ import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.da import 'package:syncrow_web/services/locator.dart'; import 'package:syncrow_web/utils/app_routes.dart'; import 'package:syncrow_web/utils/constants/routes_const.dart'; +import 'package:syncrow_web/utils/navigation_service.dart'; 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(); initialSetup(); @@ -55,8 +55,7 @@ class MyApp extends StatelessWidget { return MultiBlocProvider( providers: [ BlocProvider(create: (context) => projectCubit), - BlocProvider( - create: (context) => HomeBloc(projectCubit)..add(const FetchUserInfo())), + BlocProvider(create: (context) => HomeBloc(projectCubit)..add(const FetchUserInfo())), BlocProvider( create: (context) => VisitorPasswordBloc(projectCubit), ), @@ -77,6 +76,8 @@ class MyApp extends StatelessWidget { PointerDeviceKind.unknown, }, ), + key: NavigationService.navigatorKey, + // scaffoldMessengerKey: NavigationService.snackbarKey, theme: myTheme, routerConfig: _router, )); diff --git a/lib/pages/device_managment/all_devices/view/device_managment_page.dart b/lib/pages/device_managment/all_devices/view/device_managment_page.dart index e336e5f1..1ce42b57 100644 --- a/lib/pages/device_managment/all_devices/view/device_managment_page.dart +++ b/lib/pages/device_managment/all_devices/view/device_managment_page.dart @@ -20,7 +20,8 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { return MultiBlocProvider( providers: [ BlocProvider( - create: (context) => DeviceManagementBloc(context.read())..add(FetchDevices(context)), + create: (context) => + DeviceManagementBloc(context.read())..add(FetchDevices(context)), ), ], child: WebScaffold( @@ -42,6 +43,7 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { context .read() .add(const TriggerSwitchTabsEvent(isRoutineTab: false)); + context.read().add(FetchDevices(context)); }, child: Text( 'Devices', diff --git a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart index 3a2ef4b0..7cd66a9e 100644 --- a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart @@ -4,6 +4,7 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart'; @@ -11,18 +12,20 @@ import 'package:syncrow_web/pages/routines/models/delay/delay_fucntions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/routine_details_model.dart'; import 'package:syncrow_web/pages/routines/models/routine_model.dart'; +import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; import 'package:syncrow_web/services/devices_mang_api.dart'; import 'package:syncrow_web/services/routines_api.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/temp_const.dart'; +import 'package:syncrow_web/utils/navigation_service.dart'; import 'package:syncrow_web/utils/snack_bar.dart'; import 'package:uuid/uuid.dart'; part 'routine_event.dart'; part 'routine_state.dart'; -String spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; -String communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; +// String spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; +// String communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; class RoutineBloc extends Bloc { final ProjectCubit projectCubit; @@ -58,12 +61,11 @@ class RoutineBloc extends Bloc { TriggerSwitchTabsEvent event, Emitter emit, ) { - emit(state.copyWith( - routineTab: event.isRoutineTab, createRoutineView: false)); + emit(state.copyWith(routineTab: event.isRoutineTab, createRoutineView: false)); add(ResetRoutineState()); if (event.isRoutineTab) { - add(LoadScenes(spaceId, communityId)); - add(LoadAutomation(spaceId)); + add(const LoadScenes()); + add(const LoadAutomation()); } } @@ -85,8 +87,8 @@ class RoutineBloc extends Bloc { final updatedIfItems = List>.from(state.ifItems); // Find the index of the item in teh current itemsList - int index = updatedIfItems.indexWhere( - (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); + int index = + updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); // Replace the map if the index is valid if (index != -1) { updatedIfItems[index] = event.item; @@ -95,21 +97,18 @@ class RoutineBloc extends Bloc { } if (event.isTabToRun) { - emit(state.copyWith( - ifItems: updatedIfItems, isTabToRun: true, isAutomation: false)); + emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: true, isAutomation: false)); } else { - emit(state.copyWith( - ifItems: updatedIfItems, isTabToRun: false, isAutomation: true)); + emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: false, isAutomation: true)); } } - void _onAddToThenContainer( - AddToThenContainer event, Emitter emit) { + void _onAddToThenContainer(AddToThenContainer event, Emitter emit) { final currentItems = List>.from(state.thenItems); // Find the index of the item in teh current itemsList - int index = currentItems.indexWhere( - (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); + int index = + currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); // Replace the map if the index is valid if (index != -1) { currentItems[index] = event.item; @@ -120,26 +119,22 @@ class RoutineBloc extends Bloc { emit(state.copyWith(thenItems: currentItems)); } - void _onAddFunctionsToRoutine( - AddFunctionToRoutine event, Emitter emit) { + void _onAddFunctionsToRoutine(AddFunctionToRoutine event, Emitter emit) { try { if (event.functions.isEmpty) return; - List selectedFunction = - List.from(event.functions); + List selectedFunction = List.from(event.functions); Map> currentSelectedFunctions = Map>.from(state.selectedFunctions); if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) { List currentFunctions = - List.from( - currentSelectedFunctions[event.uniqueCustomId] ?? []); + List.from(currentSelectedFunctions[event.uniqueCustomId] ?? []); List functionCode = []; for (int i = 0; i < selectedFunction.length; i++) { for (int j = 0; j < currentFunctions.length; j++) { - if (selectedFunction[i].functionCode == - currentFunctions[j].functionCode) { + if (selectedFunction[i].functionCode == currentFunctions[j].functionCode) { currentFunctions[j] = selectedFunction[i]; if (!functionCode.contains(currentFunctions[j].functionCode)) { functionCode.add(currentFunctions[j].functionCode); @@ -149,15 +144,13 @@ class RoutineBloc extends Bloc { } for (int i = 0; i < functionCode.length; i++) { - selectedFunction - .removeWhere((code) => code.functionCode == functionCode[i]); + selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]); } - currentSelectedFunctions[event.uniqueCustomId] = - List.from(currentFunctions)..addAll(selectedFunction); + currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions) + ..addAll(selectedFunction); } else { - currentSelectedFunctions[event.uniqueCustomId] = - List.from(event.functions); + currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions); } emit(state.copyWith(selectedFunctions: currentSelectedFunctions)); @@ -166,21 +159,21 @@ class RoutineBloc extends Bloc { } } - Future _onLoadScenes( - LoadScenes event, Emitter emit) async { + Future _onLoadScenes(LoadScenes event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); - + List scenes = []; try { final projectUuid = projectCubit.state; - - spaceId = event.spaceId; - communityId = event.communityId; - - List scenes = []; - - if (communityId.isNotEmpty && spaceId.isNotEmpty) { - scenes = await SceneApi.getScenes(event.spaceId, event.communityId, projectUuid ?? TempConst.projectId); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + for (var communityId in spaceBloc.state.selectedCommunities) { + List spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; + for (var spaceId in spacesList) { + scenes.addAll( + await SceneApi.getScenes(spaceId, communityId, projectUuid ?? TempConst.projectId)); + } } + emit(state.copyWith( scenes: scenes, isLoading: false, @@ -191,19 +184,22 @@ class RoutineBloc extends Bloc { loadScenesErrorMessage: 'Failed to load scenes', errorMessage: '', loadAutomationErrorMessage: '', - scenes: [])); + scenes: scenes)); } } - Future _onLoadAutomation( - LoadAutomation event, Emitter emit) async { + Future _onLoadAutomation(LoadAutomation event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); + List automations = []; try { - spaceId = event.spaceId; - List automations = []; - if (spaceId.isNotEmpty) { - automations = await SceneApi.getAutomation(event.spaceId); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + for (var communityId in spaceBloc.state.selectedCommunities) { + List spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; + for (var spaceId in spacesList) { + automations.addAll(await SceneApi.getAutomation(spaceId)); + } } emit(state.copyWith( automations: automations, @@ -215,20 +211,18 @@ class RoutineBloc extends Bloc { loadAutomationErrorMessage: 'Failed to load automations', errorMessage: '', loadScenesErrorMessage: '', - automations: [])); + automations: automations)); } } - FutureOr _onSearchRoutines( - SearchRoutines event, Emitter emit) async { + FutureOr _onSearchRoutines(SearchRoutines event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); await Future.delayed(const Duration(seconds: 1)); emit(state.copyWith(isLoading: false, errorMessage: null)); emit(state.copyWith(searchText: event.query)); } - FutureOr _onAddSelectedIcon( - AddSelectedIcon event, Emitter emit) { + FutureOr _onAddSelectedIcon(AddSelectedIcon event, Emitter emit) { emit(state.copyWith(selectedIcon: event.icon)); } @@ -242,8 +236,7 @@ class RoutineBloc extends Bloc { return actions.last['deviceId'] == 'delay'; } - Future _onCreateScene( - CreateSceneEvent event, Emitter emit) async { + Future _onCreateScene(CreateSceneEvent event, Emitter emit) async { try { // Check if first action is delay // if (_isFirstActionDelay(state.thenItems)) { @@ -256,8 +249,7 @@ class RoutineBloc extends Bloc { if (_isLastActionDelay(state.thenItems)) { emit(state.copyWith( - errorMessage: - 'A delay condition cannot be the only or the last action', + errorMessage: 'A delay condition cannot be the only or the last action', isLoading: false, )); return; @@ -302,8 +294,11 @@ class RoutineBloc extends Bloc { }); }).toList(); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + final createSceneModel = CreateSceneModel( - spaceUuid: spaceId, + spaceUuid: spaceBloc.state.selectedSpaces[0], iconId: state.selectedIcon ?? '', showInDevice: true, sceneName: state.routineName ?? '', @@ -314,8 +309,8 @@ class RoutineBloc extends Bloc { final result = await SceneApi.createScene(createSceneModel); if (result['success']) { add(ResetRoutineState()); - add(LoadScenes(spaceId, communityId)); - add(LoadAutomation(spaceId)); + add(const LoadScenes()); + add(const LoadAutomation()); } else { emit(state.copyWith( isLoading: false, @@ -330,8 +325,7 @@ class RoutineBloc extends Bloc { } } - Future _onCreateAutomation( - CreateAutomationEvent event, Emitter emit) async { + Future _onCreateAutomation(CreateAutomationEvent event, Emitter emit) async { try { if (state.routineName == null || state.routineName!.isEmpty) { emit(state.copyWith( @@ -352,8 +346,7 @@ class RoutineBloc extends Bloc { if (_isLastActionDelay(state.thenItems)) { emit(state.copyWith( - errorMessage: - 'A delay condition cannot be the only or the last action', + errorMessage: 'A delay condition cannot be the only or the last action', isLoading: false, )); CustomSnackBar.redSnackBar('Cannot have delay as the last action'); @@ -428,9 +421,11 @@ class RoutineBloc extends Bloc { ); }); }).toList(); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); final createAutomationModel = CreateAutomationModel( - spaceUuid: spaceId, + spaceUuid: spaceBloc.state.selectedSpaces[0], automationName: state.routineName ?? '', decisionExpr: state.selectedAutomationOperator, effectiveTime: EffectiveTime( @@ -445,8 +440,8 @@ class RoutineBloc extends Bloc { final result = await SceneApi.createAutomation(createAutomationModel); if (result['success']) { add(ResetRoutineState()); - add(LoadAutomation(spaceId)); - add(LoadScenes(spaceId, communityId)); + add(const LoadAutomation()); + add(const LoadScenes()); } else { emit(state.copyWith( isLoading: false, @@ -463,21 +458,17 @@ class RoutineBloc extends Bloc { } } - FutureOr _onRemoveDragCard( - RemoveDragCard event, Emitter emit) { + FutureOr _onRemoveDragCard(RemoveDragCard event, Emitter emit) { if (event.isFromThen) { final thenItems = List>.from(state.thenItems); - final selectedFunctions = - Map>.from(state.selectedFunctions); + final selectedFunctions = Map>.from(state.selectedFunctions); thenItems.removeAt(event.index); selectedFunctions.remove(event.key); - emit(state.copyWith( - thenItems: thenItems, selectedFunctions: selectedFunctions)); + emit(state.copyWith(thenItems: thenItems, selectedFunctions: selectedFunctions)); } else { final ifItems = List>.from(state.ifItems); - final selectedFunctions = - Map>.from(state.selectedFunctions); + final selectedFunctions = Map>.from(state.selectedFunctions); ifItems.removeAt(event.index); selectedFunctions.remove(event.key); @@ -488,8 +479,7 @@ class RoutineBloc extends Bloc { isAutomation: false, isTabToRun: false)); } else { - emit(state.copyWith( - ifItems: ifItems, selectedFunctions: selectedFunctions)); + emit(state.copyWith(ifItems: ifItems, selectedFunctions: selectedFunctions)); } } } @@ -501,23 +491,18 @@ class RoutineBloc extends Bloc { )); } - FutureOr _onEffectiveTimeEvent( - EffectiveTimePeriodEvent event, Emitter emit) { + FutureOr _onEffectiveTimeEvent(EffectiveTimePeriodEvent event, Emitter emit) { emit(state.copyWith(effectiveTime: event.effectiveTime)); } - FutureOr _onSetRoutineName( - SetRoutineName event, Emitter emit) { + FutureOr _onSetRoutineName(SetRoutineName event, Emitter emit) { emit(state.copyWith( routineName: event.name, )); } - ( - List>, - List>, - Map> - ) _createCardData( + (List>, List>, Map>) + _createCardData( List actions, List? conditions, Map> currentFunctions, @@ -550,8 +535,7 @@ class RoutineBloc extends Bloc { 'deviceId': condition.entityId, 'title': matchingDevice.name ?? condition.entityId, 'productType': condition.entityType, - 'imagePath': - matchingDevice.getDefaultIcon(condition.entityType), + 'imagePath': matchingDevice.getDefaultIcon(condition.entityType), }; final functions = matchingDevice.functions; @@ -587,11 +571,8 @@ class RoutineBloc extends Bloc { final cardData = { 'entityId': action.entityId, 'uniqueCustomId': const Uuid().v4(), - 'deviceId': - action.actionExecutor == 'delay' ? 'delay' : action.entityId, - 'title': action.actionExecutor == 'delay' - ? 'Delay' - : (matchingDevice.name ?? 'Device'), + 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'title': action.actionExecutor == 'delay' ? 'Delay' : (matchingDevice.name ?? 'Device'), 'productType': action.productType, 'imagePath': matchingDevice.getDefaultIcon(action.productType), }; @@ -634,8 +615,7 @@ class RoutineBloc extends Bloc { return (thenItems, ifItems, currentFunctions); } - Future _onGetSceneDetails( - GetSceneDetails event, Emitter emit) async { + Future _onGetSceneDetails(GetSceneDetails event, Emitter emit) async { try { emit(state.copyWith( isLoading: true, @@ -683,12 +663,10 @@ class RoutineBloc extends Bloc { if (!deviceCards.containsKey(deviceId)) { deviceCards[deviceId] = { 'entityId': action.entityId, - 'deviceId': - action.actionExecutor == 'delay' ? 'delay' : action.entityId, - 'uniqueCustomId': - action.type == 'automation' || action.actionExecutor == 'delay' - ? const Uuid().v4() - : action.entityId, + 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'uniqueCustomId': action.type == 'automation' || action.actionExecutor == 'delay' + ? const Uuid().v4() + : action.entityId, 'title': action.actionExecutor == 'delay' ? 'Delay' : action.type == 'automation' @@ -723,8 +701,7 @@ class RoutineBloc extends Bloc { ), ); // emit(state.copyWith(automationActionExecutor: action.actionExecutor)); - } else if (action.executorProperty != null && - action.actionExecutor != 'delay') { + } else if (action.executorProperty != null && action.actionExecutor != 'delay') { if (!updatedFunctions.containsKey(uniqueCustomId)) { updatedFunctions[uniqueCustomId] = []; } @@ -796,8 +773,7 @@ class RoutineBloc extends Bloc { } } - FutureOr _onResetRoutineState( - ResetRoutineState event, Emitter emit) { + FutureOr _onResetRoutineState(ResetRoutineState event, Emitter emit) { emit(state.copyWith( ifItems: [], thenItems: [], @@ -821,18 +797,21 @@ class RoutineBloc extends Bloc { createRoutineView: false)); } - FutureOr _deleteScene(DeleteScene event, Emitter emit) { + FutureOr _deleteScene(DeleteScene event, Emitter emit) async { try { emit(state.copyWith(isLoading: true)); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); if (state.isTabToRun) { - SceneApi.deleteScene(unitUuid: spaceId, sceneId: state.sceneId ?? ''); + await SceneApi.deleteScene( + unitUuid: spaceBloc.state.selectedSpaces[0], sceneId: state.sceneId ?? ''); } else { - SceneApi.deleteAutomation( - unitUuid: spaceId, automationId: state.automationId ?? ''); + await SceneApi.deleteAutomation( + unitUuid: spaceBloc.state.selectedSpaces[0], automationId: state.automationId ?? ''); } - add(LoadScenes(spaceId, communityId)); - add(LoadAutomation(spaceId)); + add(const LoadScenes()); + add(const LoadAutomation()); add(ResetRoutineState()); emit(state.copyWith(isLoading: false, createRoutineView: false)); } catch (e) { @@ -857,13 +836,21 @@ class RoutineBloc extends Bloc { // } // } - FutureOr _fetchDevices( - FetchDevicesInRoutine event, Emitter emit) async { + FutureOr _fetchDevices(FetchDevicesInRoutine event, Emitter emit) async { emit(state.copyWith(isLoading: true)); try { final projectUuid = projectCubit.state; - final devices = await DevicesManagementApi() - .fetchDevices('', '', projectUuid ?? TempConst.projectId); + List devices = []; + + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + for (var communityId in spaceBloc.state.selectedCommunities) { + List spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; + for (var spaceId in spacesList) { + devices.addAll(await DevicesManagementApi() + .fetchDevices(communityId, spaceId, projectUuid ?? TempConst.projectId)); + } + } emit(state.copyWith(isLoading: false, devices: devices)); } catch (e) { @@ -871,8 +858,7 @@ class RoutineBloc extends Bloc { } } - FutureOr _onUpdateScene( - UpdateScene event, Emitter emit) async { + FutureOr _onUpdateScene(UpdateScene event, Emitter emit) async { try { // Check if first action is delay // if (_isFirstActionDelay(state.thenItems)) { @@ -886,8 +872,7 @@ class RoutineBloc extends Bloc { if (_isLastActionDelay(state.thenItems)) { emit(state.copyWith( - errorMessage: - 'A delay condition cannot be the only or the last action', + errorMessage: 'A delay condition cannot be the only or the last action', isLoading: false, )); return; @@ -940,12 +925,11 @@ class RoutineBloc extends Bloc { actions: actions, ); - final result = - await SceneApi.updateScene(createSceneModel, state.sceneId ?? ''); + final result = await SceneApi.updateScene(createSceneModel, state.sceneId ?? ''); if (result['success']) { add(ResetRoutineState()); - add(LoadScenes(spaceId, communityId)); - add(LoadAutomation(spaceId)); + add(const LoadScenes()); + add(const LoadAutomation()); } else { emit(state.copyWith( isLoading: false, @@ -960,8 +944,7 @@ class RoutineBloc extends Bloc { } } - FutureOr _onUpdateAutomation( - UpdateAutomation event, Emitter emit) async { + FutureOr _onUpdateAutomation(UpdateAutomation event, Emitter emit) async { try { if (state.routineName == null || state.routineName!.isEmpty) { emit(state.copyWith( @@ -1056,8 +1039,11 @@ class RoutineBloc extends Bloc { }); }).toList(); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + final createAutomationModel = CreateAutomationModel( - spaceUuid: spaceId, + spaceUuid: spaceBloc.state.selectedSpaces[0], automationName: state.routineName ?? '', decisionExpr: state.selectedAutomationOperator, effectiveTime: EffectiveTime( @@ -1069,13 +1055,13 @@ class RoutineBloc extends Bloc { actions: actions, ); - final result = await SceneApi.updateAutomation( - createAutomationModel, state.automationId ?? ''); + final result = + await SceneApi.updateAutomation(createAutomationModel, state.automationId ?? ''); if (result['success']) { add(ResetRoutineState()); - add(LoadAutomation(spaceId)); - add(LoadScenes(spaceId, communityId)); + add(LoadAutomation()); + add(LoadScenes()); } else { emit(state.copyWith( isLoading: false, @@ -1103,8 +1089,7 @@ class RoutineBloc extends Bloc { thenItems: [], )); - final automationDetails = - await SceneApi.getAutomationDetails(event.automationId); + final automationDetails = await SceneApi.getAutomationDetails(event.automationId); final Map> deviceIfCards = {}; final Map> deviceThenCards = {}; @@ -1172,15 +1157,13 @@ class RoutineBloc extends Bloc { ), ); - final deviceId = action.actionExecutor == 'delay' - ? '${action.entityId}_delay' - : action.entityId; + final deviceId = + action.actionExecutor == 'delay' ? '${action.entityId}_delay' : action.entityId; if (!deviceThenCards.containsKey(deviceId)) { deviceThenCards[deviceId] = { 'entityId': action.entityId, - 'deviceId': - action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, 'uniqueCustomId': const Uuid().v4(), 'title': action.actionExecutor == 'delay' ? 'Delay' @@ -1211,8 +1194,7 @@ class RoutineBloc extends Bloc { updatedFunctions[uniqueCustomId] = []; } - if (action.executorProperty != null && - action.actionExecutor != 'delay') { + if (action.executorProperty != null && action.actionExecutor != 'delay') { final functions = matchingDevice.functions; final functionCode = action.executorProperty!.functionCode; for (var function in functions) { @@ -1254,14 +1236,10 @@ class RoutineBloc extends Bloc { } } - final ifItems = deviceIfCards.values - .where((card) => card['type'] == 'condition') - .toList(); + final ifItems = deviceIfCards.values.where((card) => card['type'] == 'condition').toList(); final thenItems = deviceThenCards.values .where((card) => - card['type'] == 'action' || - card['type'] == 'automation' || - card['type'] == 'scene') + card['type'] == 'action' || card['type'] == 'automation' || card['type'] == 'scene') .toList(); emit(state.copyWith( diff --git a/lib/pages/routines/bloc/routine_bloc/routine_event.dart b/lib/pages/routines/bloc/routine_bloc/routine_event.dart index e412aae6..c1b2a23f 100644 --- a/lib/pages/routines/bloc/routine_bloc/routine_event.dart +++ b/lib/pages/routines/bloc/routine_bloc/routine_event.dart @@ -27,22 +27,24 @@ class AddToThenContainer extends RoutineEvent { } class LoadScenes extends RoutineEvent { - final String spaceId; - final String communityId; + // final String spaceId; + // final String communityId; + // final BuildContext context; - const LoadScenes(this.spaceId, this.communityId); + const LoadScenes(); @override - List get props => [spaceId, communityId]; + List get props => []; } class LoadAutomation extends RoutineEvent { - final String spaceId; + // final String spaceId; + // final BuildContext context; - const LoadAutomation(this.spaceId); + const LoadAutomation(); @override - List get props => [spaceId]; + List get props => []; } class AddFunctionToRoutine extends RoutineEvent { diff --git a/lib/pages/routines/view/routines_view.dart b/lib/pages/routines/view/routines_view.dart index 43d3b227..0982601e 100644 --- a/lib/pages/routines/view/routines_view.dart +++ b/lib/pages/routines/view/routines_view.dart @@ -20,7 +20,7 @@ class _RoutinesViewState extends State { @override void initState() { super.initState(); - context.read().add(FetchDevicesInRoutine()); + // context.read().add(FetchDevicesInRoutine()); } @override @@ -32,9 +32,12 @@ class _RoutinesViewState extends State { } return Row( children: [ - Expanded( - child: SpaceTreeView( - onSelect: () {}, + Expanded(child: SpaceTreeView( + onSelect: () { + context.read() + ..add(const LoadScenes()) + ..add(const LoadAutomation()); + }, )), Expanded( flex: 4, @@ -59,8 +62,8 @@ class _RoutinesViewState extends State { ), RoutineViewCard( onTap: () { - if (context.read().selectedCommunityId.isNotEmpty && - context.read().selectedSpaceId.isNotEmpty) { + if (context.read().state.selectedCommunities.length == 1 && + context.read().state.selectedSpaces.length == 1) { context.read().add( (ResetRoutineState()), ); @@ -68,7 +71,18 @@ class _RoutinesViewState extends State { const CreateNewRoutineViewEvent(createRoutineView: true), ); } else { - CustomSnackBar.redSnackBar('Please select a space'); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + context.read().state.selectedSpaces.isEmpty + ? 'Please select a space' + : 'Please select only one space to proceed'), + ), + ); + // CustomSnackBar.redSnackBar( + // context.read().state.selectedSpaces.isEmpty + // ? 'Please select a space' + // : 'Please select only one space to proceed'); } }, icon: Icons.add, diff --git a/lib/pages/routines/widgets/main_routine_view/fetch_routine_scenes_automation.dart b/lib/pages/routines/widgets/main_routine_view/fetch_routine_scenes_automation.dart index ed2a9405..718a78b9 100644 --- a/lib/pages/routines/widgets/main_routine_view/fetch_routine_scenes_automation.dart +++ b/lib/pages/routines/widgets/main_routine_view/fetch_routine_scenes_automation.dart @@ -20,10 +20,6 @@ class _FetchRoutineScenesState extends State @override void initState() { super.initState(); - context.read() - ..add(LoadScenes(context.read().selectedSpaceId, - context.read().selectedCommunityId)) - ..add(LoadAutomation(context.read().selectedSpaceId)); } @override diff --git a/lib/pages/routines/widgets/routine_devices.dart b/lib/pages/routines/widgets/routine_devices.dart index 3515cc70..21531ad3 100644 --- a/lib/pages/routines/widgets/routine_devices.dart +++ b/lib/pages/routines/widgets/routine_devices.dart @@ -4,9 +4,20 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart'; -class RoutineDevices extends StatelessWidget { +class RoutineDevices extends StatefulWidget { const RoutineDevices({super.key}); + @override + State createState() => _RoutineDevicesState(); +} + +class _RoutineDevicesState extends State { + @override + void initState() { + super.initState(); + context.read().add(FetchDevicesInRoutine()); + } + @override Widget build(BuildContext context) { return BlocBuilder( diff --git a/lib/pages/routines/widgets/scenes_and_automations.dart b/lib/pages/routines/widgets/scenes_and_automations.dart index 2e268b1c..14cb8d61 100644 --- a/lib/pages/routines/widgets/scenes_and_automations.dart +++ b/lib/pages/routines/widgets/scenes_and_automations.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart'; -import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; class ScenesAndAutomations extends StatefulWidget { @@ -19,9 +18,8 @@ class _ScenesAndAutomationsState extends State { void initState() { super.initState(); context.read() - ..add(LoadScenes(context.read().selectedSpaceId, - context.read().selectedCommunityId)) - ..add(LoadAutomation(context.read().selectedSpaceId)); + ..add(const LoadScenes()) + ..add(const LoadAutomation()); } @override diff --git a/lib/pages/space_tree/bloc/space_tree_bloc.dart b/lib/pages/space_tree/bloc/space_tree_bloc.dart index 2cb39fc8..9a0078e3 100644 --- a/lib/pages/space_tree/bloc/space_tree_bloc.dart +++ b/lib/pages/space_tree/bloc/space_tree_bloc.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart'; @@ -8,9 +9,13 @@ import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/utils/constants/temp_const.dart'; class SpaceTreeBloc extends Bloc { - String selectedCommunityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; - String selectedSpaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; + // String selectedCommunityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; + // String selectedSpaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; final ProjectCubit projectCubit; + final TextEditingController textController = TextEditingController(); + + // String selectedCommunityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; + // String selectedSpaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; SpaceTreeBloc(this.projectCubit) : super(const SpaceTreeState()) { on(_fetchSpaces); @@ -26,14 +31,13 @@ class SpaceTreeBloc extends Bloc { try { final projectUuid = projectCubit.state; - List communities = await CommunitySpaceManagementApi() - .fetchCommunities(projectUuid ?? TempConst.projectId); + List communities = + await CommunitySpaceManagementApi().fetchCommunities(projectUuid ?? TempConst.projectId); List updatedCommunities = await Future.wait( communities.map((community) async { List spaces = await CommunitySpaceManagementApi() - .getSpaceHierarchy( - community.uuid, projectUuid ?? TempConst.projectId); + .getSpaceHierarchy(community.uuid, projectUuid ?? TempConst.projectId); return CommunityModel( uuid: community.uuid, @@ -48,19 +52,15 @@ class SpaceTreeBloc extends Bloc { ); emit(state.copyWith( - communitiesList: updatedCommunities, - expandedCommunity: [], - expandedSpaces: [])); + communitiesList: updatedCommunities, expandedCommunity: [], expandedSpaces: [])); } catch (e) { emit(SpaceTreeErrorState('Error loading communities and spaces: $e')); } } - _onCommunityExpanded( - OnCommunityExpanded event, Emitter emit) async { + _onCommunityExpanded(OnCommunityExpanded event, Emitter emit) async { try { - List updatedExpandedCommunityList = - List.from(state.expandedCommunities); + List updatedExpandedCommunityList = List.from(state.expandedCommunities); if (updatedExpandedCommunityList.contains(event.communityId)) { updatedExpandedCommunityList.remove(event.communityId); @@ -92,17 +92,13 @@ class SpaceTreeBloc extends Bloc { } } - _onCommunitySelected( - OnCommunitySelected event, Emitter emit) async { + _onCommunitySelected(OnCommunitySelected event, Emitter emit) async { try { List updatedSelectedCommunities = List.from(state.selectedCommunities.toSet().toList()); - List updatedSelectedSpaces = - List.from(state.selectedSpaces.toSet().toList()); - List updatedSoldChecks = - List.from(state.soldCheck.toSet().toList()); - Map> communityAndSpaces = - Map.from(state.selectedCommunityAndSpaces); + List updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList()); + List updatedSoldChecks = List.from(state.soldCheck.toSet().toList()); + Map> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces); List childrenIds = _getAllChildIds(event.children); @@ -133,12 +129,9 @@ class SpaceTreeBloc extends Bloc { try { List updatedSelectedCommunities = List.from(state.selectedCommunities.toSet().toList()); - List updatedSelectedSpaces = - List.from(state.selectedSpaces.toSet().toList()); - List updatedSoldChecks = - List.from(state.soldCheck.toSet().toList()); - Map> communityAndSpaces = - Map.from(state.selectedCommunityAndSpaces); + List updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList()); + List updatedSoldChecks = List.from(state.soldCheck.toSet().toList()); + Map> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces); List childrenIds = _getAllChildIds(event.children); bool isChildSelected = false; @@ -158,11 +151,9 @@ class SpaceTreeBloc extends Bloc { updatedSelectedSpaces.addAll(childrenIds); } - List spaces = - _getThePathToChild(event.communityId, event.spaceId); + List spaces = _getThePathToChild(event.communityId, event.spaceId); for (String space in spaces) { - if (!updatedSelectedSpaces.contains(space) && - !updatedSoldChecks.contains(space)) { + if (!updatedSelectedSpaces.contains(space) && !updatedSoldChecks.contains(space)) { updatedSoldChecks.add(space); } } @@ -181,8 +172,7 @@ class SpaceTreeBloc extends Bloc { } updatedSoldChecks.remove(event.spaceId); - List parents = - _getThePathToChild(event.communityId, event.spaceId); + List parents = _getThePathToChild(event.communityId, event.spaceId); if (!_parentSelected(parents, updatedSelectedSpaces)) { updatedSoldChecks.removeWhere(parents.contains); } @@ -195,7 +185,7 @@ class SpaceTreeBloc extends Bloc { communityAndSpaces[event.communityId] = updatedSelectedSpaces; emit(state.copyWith( - selectedCommunities: updatedSelectedCommunities, + selectedCommunities: updatedSelectedCommunities.toSet().toList(), selectedSpaces: updatedSelectedSpaces, soldCheck: updatedSoldChecks, selectedCommunityAndSpaces: communityAndSpaces)); @@ -221,18 +211,18 @@ class SpaceTreeBloc extends Bloc { // Filter communities and expand only those that match the query filteredCommunity = communities.where((community) { - final containsQueryInCommunity = community.name - .toLowerCase() - .contains(event.searchQuery.toLowerCase()); - final containsQueryInSpaces = community.spaces.any( - (space) => _containsQuery(space, event.searchQuery.toLowerCase())); + final containsQueryInCommunity = + community.name.toLowerCase().contains(event.searchQuery.toLowerCase()); + final containsQueryInSpaces = + community.spaces.any((space) => _containsQuery(space, event.searchQuery.toLowerCase())); return containsQueryInCommunity || containsQueryInSpaces; }).toList(); emit(state.copyWith( filteredCommunity: filteredCommunity, - isSearching: event.searchQuery.isNotEmpty)); + isSearching: event.searchQuery.isNotEmpty, + searchQuery: event.searchQuery)); } catch (e) { emit(const SpaceTreeErrorState('Something went wrong')); } @@ -241,8 +231,8 @@ class SpaceTreeBloc extends Bloc { // Helper function to determine if any space or its children match the search query bool _containsQuery(SpaceModel space, String query) { final matchesSpace = space.name.toLowerCase().contains(query); - final matchesChildren = space.children.any((child) => - _containsQuery(child, query)); // Recursive check for children + final matchesChildren = + space.children.any((child) => _containsQuery(child, query)); // Recursive check for children return matchesSpace || matchesChildren; } @@ -256,15 +246,14 @@ class SpaceTreeBloc extends Bloc { return ids; } - bool _anySpacesSelectedInCommunity(String communityId, - List selectedSpaces, List partialCheckedList) { + bool _anySpacesSelectedInCommunity( + String communityId, List selectedSpaces, List partialCheckedList) { bool result = false; for (var community in state.communityList) { if (community.uuid == communityId) { List ids = _getAllChildIds(community.spaces); for (var id in ids) { - result = - selectedSpaces.contains(id) || partialCheckedList.contains(id); + result = selectedSpaces.contains(id) || partialCheckedList.contains(id); if (result) { return result; } @@ -291,8 +280,7 @@ class SpaceTreeBloc extends Bloc { return ids; } - List _getAllParentsIds( - SpaceModel child, String spaceId, List listIds) { + List _getAllParentsIds(SpaceModel child, String spaceId, List listIds) { List ids = listIds; ids.add(child.uuid ?? ''); @@ -313,4 +301,10 @@ class SpaceTreeBloc extends Bloc { ids.removeLast(); return []; } + + @override + Future close() async { + textController.dispose(); + super.close(); + } } diff --git a/lib/pages/space_tree/bloc/space_tree_state.dart b/lib/pages/space_tree/bloc/space_tree_state.dart index 1abd7455..915197dc 100644 --- a/lib/pages/space_tree/bloc/space_tree_state.dart +++ b/lib/pages/space_tree/bloc/space_tree_state.dart @@ -11,6 +11,7 @@ class SpaceTreeState extends Equatable { final List selectedSpaces; final List soldCheck; final bool isSearching; + final String searchQuery; const SpaceTreeState( {this.communityList = const [], @@ -21,7 +22,8 @@ class SpaceTreeState extends Equatable { this.selectedSpaces = const [], this.soldCheck = const [], this.isSearching = false, - this.selectedCommunityAndSpaces = const {}}); + this.selectedCommunityAndSpaces = const {}, + this.searchQuery = ''}); SpaceTreeState copyWith( {List? communitiesList, @@ -32,7 +34,8 @@ class SpaceTreeState extends Equatable { List? selectedSpaces, List? soldCheck, bool? isSearching, - Map>? selectedCommunityAndSpaces}) { + Map>? selectedCommunityAndSpaces, + String? searchQuery}) { return SpaceTreeState( communityList: communitiesList ?? this.communityList, filteredCommunity: filteredCommunity ?? this.filteredCommunity, @@ -42,7 +45,8 @@ class SpaceTreeState extends Equatable { selectedSpaces: selectedSpaces ?? this.selectedSpaces, soldCheck: soldCheck ?? this.soldCheck, isSearching: isSearching ?? this.isSearching, - selectedCommunityAndSpaces: selectedCommunityAndSpaces ?? this.selectedCommunityAndSpaces); + selectedCommunityAndSpaces: selectedCommunityAndSpaces ?? this.selectedCommunityAndSpaces, + searchQuery: searchQuery ?? this.searchQuery); } @override @@ -55,7 +59,8 @@ class SpaceTreeState extends Equatable { selectedSpaces, soldCheck, isSearching, - selectedCommunityAndSpaces + selectedCommunityAndSpaces, + searchQuery ]; } diff --git a/lib/pages/space_tree/view/space_tree_view.dart b/lib/pages/space_tree/view/space_tree_view.dart index de9d088e..da038f7a 100644 --- a/lib/pages/space_tree/view/space_tree_view.dart +++ b/lib/pages/space_tree/view/space_tree_view.dart @@ -39,6 +39,7 @@ class _SpaceTreeViewState extends State { : Column( children: [ CustomSearchBar( + searchQuery: state.searchQuery, onSearchChanged: (query) { context.read().add(SearchQueryEvent(query)); }, From b00b0c82dc975214786c60bf053a865a9c7a2877 Mon Sep 17 00:00:00 2001 From: mohammad Date: Mon, 17 Feb 2025 12:36:04 +0300 Subject: [PATCH 6/6] spaceName --- .../visitor_password/model/device_model.dart | 7 ++++- .../view/add_device_dialog.dart | 30 +++++++++++-------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/pages/visitor_password/model/device_model.dart b/lib/pages/visitor_password/model/device_model.dart index 811e5b60..f9711eed 100644 --- a/lib/pages/visitor_password/model/device_model.dart +++ b/lib/pages/visitor_password/model/device_model.dart @@ -23,6 +23,7 @@ class DeviceModel { dynamic timeZone; dynamic updateTime; dynamic uuid; + dynamic spaceName; DeviceModel({ required this.productUuid, @@ -45,6 +46,7 @@ class DeviceModel { required this.timeZone, required this.updateTime, required this.uuid, + required this.spaceName, }); // Deserialize from JSON @@ -53,7 +55,8 @@ class DeviceModel { DeviceType type = devicesTypesMap[json['productType']] ?? DeviceType.Other; if (type == DeviceType.LightBulb) { tempIcon = Assets.lightBulb; - } else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) { + } else if (type == DeviceType.CeilingSensor || + type == DeviceType.WallSensor) { tempIcon = Assets.sensors; } else if (type == DeviceType.AC) { tempIcon = Assets.ac; @@ -102,6 +105,7 @@ class DeviceModel { timeZone: json['timeZone'], updateTime: json['updateTime'], uuid: json['uuid'], + spaceName: json['spaceName'], ); } @@ -128,6 +132,7 @@ class DeviceModel { 'timeZone': timeZone, 'updateTime': updateTime, 'uuid': uuid, + 'spaceName': spaceName }; } } diff --git a/lib/pages/visitor_password/view/add_device_dialog.dart b/lib/pages/visitor_password/view/add_device_dialog.dart index f560b390..99a50012 100644 --- a/lib/pages/visitor_password/view/add_device_dialog.dart +++ b/lib/pages/visitor_password/view/add_device_dialog.dart @@ -20,7 +20,8 @@ class AddDeviceDialog extends StatelessWidget { Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return BlocProvider( - create: (context) => VisitorPasswordBloc(context.read())..add(FetchDevice()), + create: (context) => + VisitorPasswordBloc(context.read())..add(FetchDevice()), child: BlocBuilder( builder: (BuildContext context, VisitorPasswordState state) { final visitorBloc = BlocProvider.of(context); @@ -36,10 +37,10 @@ class AddDeviceDialog extends StatelessWidget { backgroundColor: Colors.white, title: Text( 'Add Accessible Device', - style: Theme.of(context) - .textTheme - .headlineLarge! - .copyWith(fontWeight: FontWeight.w400, fontSize: 24, color: Colors.black), + style: Theme.of(context).textTheme.headlineLarge!.copyWith( + fontWeight: FontWeight.w400, + fontSize: 24, + color: Colors.black), ), content: SizedBox( height: MediaQuery.of(context).size.height / 1.7, @@ -69,10 +70,13 @@ class AddDeviceDialog extends StatelessWidget { ), Text( 'Only online accessible devices can be added', - style: Theme.of(context).textTheme.bodySmall!.copyWith( - fontWeight: FontWeight.w400, - fontSize: 12, - color: ColorsManager.grayColor), + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + fontWeight: FontWeight.w400, + fontSize: 12, + color: ColorsManager.grayColor), ), ], )), @@ -153,7 +157,8 @@ class AddDeviceDialog extends StatelessWidget { visitorBloc.deviceNameController.clear(); visitorBloc.deviceIdController.clear(); visitorBloc.unitNameController.clear(); - visitorBloc.add(FetchDevice()); // Reset to original list + visitorBloc.add( + FetchDevice()); // Reset to original list }, ), ), @@ -173,7 +178,8 @@ class AddDeviceDialog extends StatelessWidget { selectAll: (p0) { visitorBloc.selectedDeviceIds.clear(); for (var item in state.data) { - visitorBloc.add(SelectDeviceEvent(item.uuid)); + visitorBloc + .add(SelectDeviceEvent(item.uuid)); } }, onRowSelected: (index, isSelected, row) { @@ -194,7 +200,7 @@ class AddDeviceDialog extends StatelessWidget { item.name.toString(), item.uuid.toString(), item.productType.toString(), - '', + item.spaceName.toString(), item.online.value.toString(), ]; }).toList(),