diff --git a/lib/features/app_layout/bloc/home_cubit.dart b/lib/features/app_layout/bloc/home_cubit.dart index dc951ab..8b80c81 100644 --- a/lib/features/app_layout/bloc/home_cubit.dart +++ b/lib/features/app_layout/bloc/home_cubit.dart @@ -7,10 +7,10 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:onesignal_flutter/onesignal_flutter.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:share_plus/share_plus.dart'; +import 'package:syncrow_app/features/app_layout/model/permission_model.dart'; import 'package:syncrow_app/features/app_layout/model/space_model.dart'; import 'package:syncrow_app/features/app_layout/view/widgets/app_bar_home_dropdown.dart'; import 'package:syncrow_app/features/auth/model/user_model.dart'; -import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart'; import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart'; import 'package:syncrow_app/features/devices/model/subspace_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart'; @@ -30,23 +30,30 @@ import 'package:syncrow_app/services/api/profile_api.dart'; import 'package:syncrow_app/services/api/spaces_api.dart'; import 'package:syncrow_app/utils/helpers/snack_bar.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; - part 'home_state.dart'; class HomeCubit extends Cubit { HomeCubit._() : super(HomeInitial()) { // checkIfNotificationPermissionGranted(); - fetchUserInfo(); - if (selectedSpace == null) { - fetchUnitsByUserId(); - // .then((value) { - // if (selectedSpace != null) { - // fetchRoomsByUnitId(selectedSpace!); - // } - // }); - } + fetchUserInfo().then( + (value) { + if (selectedSpace == null) { + fetchUnitsByUserId(); + fetchPermissions(); + + // .then((value) { + // if (selectedSpace != null) { + // fetchRoomsByUnitId(selectedSpace!); + // } + // }); + } + }, + ); } static UserModel? user; + + List? permissionModel = []; + static HomeCubit? _instance; static HomeCubit getInstance() { // If an instance already exists, return it @@ -56,15 +63,87 @@ class HomeCubit extends Cubit { Future fetchUserInfo() async { try { + emit(HomeLoading()); var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey); user = await ProfileApi().fetchUserInfo(uuid); - emit(HomeUserInfoLoaded(user!)); // Emit state after fetching user info + emit(HomeUserInfoLoaded(user!)); } catch (e) { return; } } + static bool manageSupSpace = false; + static bool manageScene = false; + static bool manageDeviceLocation = false; + static bool visitorPasswordManagement = false; + + Future fetchPermissions() async { + try { + emit(HomeLoading()); + final response = await ProfileApi().fetchPermissions(user!.role!.uuid); + permissionModel = PermissionModel.fromJsonList(response); + hasViewPermission(); + emit(PermissionsRoleLoaded(permissionModel!)); + } catch (e) { + emit(HomeError(e.toString())); + } + } + + void hasViewPermission() { + emit(HomeLoading()); + + manageSupSpace = hasPermission( + permissionModel!, + 'SPACE_MANAGEMENT', + 'MANAGE_SPACE', + 'ASSIGN_USER_TO_SPACE', + ); + manageScene = hasPermission( + permissionModel!, + 'AUTOMATION_MANAGEMENT', + 'MANAGE_SCENES', + 'UPDATE', + ); + manageDeviceLocation = hasPermission( + permissionModel!, + 'DEVICE_MANAGEMENT', + 'MANAGE_DEVICE', + 'LOCATION_UPDATE', + ); + visitorPasswordManagement = hasPermission( + permissionModel!, + 'VISITOR_PASSWORD_MANAGEMENT', + 'MANAGE_VISITOR_PASSWORD', + 'VIEW', + ); + emit(HomePermissionUpdated()); + } + + bool hasPermission(List permissions, String mainTitle, + String subTitle, String finalTitle) { + try { + final mainOption = permissions.firstWhere( + (perm) => perm.title == mainTitle, + ); + + final subOption = mainOption.subOptions.firstWhere( + (sub) => sub.title == subTitle, + ); + + if (subOption.subOptions == null) { + return false; + } + + final finalOption = subOption.subOptions!.firstWhere( + (finalSub) => finalSub.title == finalTitle, + ); + return finalOption.isChecked == true; + } catch (e) { + return false; + } + } + void emitSafe(HomeState newState) { final cubit = this; if (!cubit.isClosed) { @@ -89,7 +168,7 @@ class HomeCubit extends Cubit { static HomeCubit get(context) => BlocProvider.of(context); - List? spaces; + List? spaces = []; SpaceModel? selectedSpace; @@ -261,6 +340,7 @@ class HomeCubit extends Cubit { emitSafe(GetSpacesLoading()); try { spaces = await SpacesAPI.getSpacesByUserId(); + emitSafe(GetSpacesSuccess(spaces!)); } catch (failure) { emitSafe(GetSpacesError("No units found")); return; @@ -298,11 +378,13 @@ class HomeCubit extends Cubit { await const FlutterSecureStorage().read(key: UserModel.userUuidKey); var res = await SpacesAPI.activationCodeSpace( activationCode: activationCode, userUuid: uuid); + if (res['success'] == true) { fetchUserInfo(); fetchUnitsByUserId(); } emitSafe(GetSpacesSuccess(spaces!)); + return res['success']; } on DioException catch (e) { final errorMessage = e.response?.data['error']['message']; @@ -378,6 +460,8 @@ class HomeCubit extends Cubit { // ), // onPressed: () {}, // ), + // HomeCubit.permissionModel!.scene!.visible == true + // ? IconButton( icon: const Icon( Icons.add, @@ -413,7 +497,8 @@ class HomeCubit extends Cubit { .read() .add(const ClearTabToRunSetting()); }, - ), + ) + // : const SizedBox(), // IconButton( // icon: const Icon( // Icons.more_vert, @@ -503,3 +588,28 @@ BottomNavigationBarItem defaultBottomNavBarItem( label: label, ); } + + +// class PermissionUtils { +// // Check if the "VIEW" permission exists in "MANAGE_SUBSPACE" +// static bool hasViewPermission(List permissions) { +// return _hasPermission(permissions, 'MANAGE_SUBSPACE', 'VIEW'); +// } + +// // Generalized permission checker +// static bool _hasPermission( +// List permissions, String mainTitle, String subTitle) { +// final mainOption = permissions.firstWhere( +// (perm) => perm['title'] == mainTitle, +// orElse: () => null, +// ); +// if (mainOption != null) { +// final subOption = mainOption['subOptions'].firstWhere( +// (sub) => sub['title'] == subTitle, +// orElse: () => null, +// ); +// return subOption != null && subOption['isChecked'] == true; +// } +// return false; +// } +// } diff --git a/lib/features/app_layout/bloc/home_state.dart b/lib/features/app_layout/bloc/home_state.dart index 6498b0d..1bbe8b8 100644 --- a/lib/features/app_layout/bloc/home_state.dart +++ b/lib/features/app_layout/bloc/home_state.dart @@ -14,9 +14,9 @@ class HomeError extends HomeState { } class HomeSuccess extends HomeState {} +class ActivationSuccess extends HomeState {} + -///specific states -//get spaces class GetSpacesLoading extends HomeLoading {} class GetSpacesSuccess extends HomeSuccess { @@ -64,10 +64,16 @@ class RoomSelected extends HomeState { class RoomUnSelected extends HomeState {} class NavChangePage extends HomeState {} +class HomePermissionUpdated extends HomeState {} + -// Define new state classes class HomeUserInfoLoaded extends HomeState { final UserModel user; HomeUserInfoLoaded(this.user); } + +class PermissionsRoleLoaded extends HomeState { + final List permissionModel; + PermissionsRoleLoaded(this.permissionModel); +} diff --git a/lib/features/app_layout/model/permission_model.dart b/lib/features/app_layout/model/permission_model.dart new file mode 100644 index 0000000..3965d27 --- /dev/null +++ b/lib/features/app_layout/model/permission_model.dart @@ -0,0 +1,39 @@ +class PermissionModel { + final String title; + final List subOptions; + + PermissionModel({required this.title, required this.subOptions}); + + factory PermissionModel.fromJson(Map json) { + return PermissionModel( + title: json['title'], + subOptions: (json['subOptions'] as List) + .map((e) => PermissionAttributes.fromJson(e)) + .toList(), + ); + } + + static List fromJsonList(List jsonList) { + return jsonList.map((json) => PermissionModel.fromJson(json)).toList(); + } +} + +class PermissionAttributes { + final String title; + final List? subOptions; + final bool? isChecked; + + PermissionAttributes({required this.title, this.subOptions, this.isChecked}); + + factory PermissionAttributes.fromJson(Map json) { + return PermissionAttributes( + title: json['title'], + isChecked: json['isChecked'], + subOptions: json['subOptions'] != null + ? (json['subOptions'] as List) + .map((e) => PermissionAttributes.fromJson(e)) + .toList() + : null, + ); + } +} diff --git a/lib/features/app_layout/view/app_layout.dart b/lib/features/app_layout/view/app_layout.dart index 214cce2..5dfe583 100644 --- a/lib/features/app_layout/view/app_layout.dart +++ b/lib/features/app_layout/view/app_layout.dart @@ -17,7 +17,10 @@ class AppLayout extends StatelessWidget { child: BlocBuilder( builder: (context, state) { return DefaultScaffold( - appBar: HomeCubit.getInstance().spaces != null ? const DefaultAppBar() : null, + appBar: HomeCubit.getInstance().spaces != null && + HomeCubit.getInstance().spaces!.isNotEmpty + ? const DefaultAppBar() + : null, bottomNavBar: const DefaultNavBar(), child: const AppBody(), ); diff --git a/lib/features/app_layout/view/widgets/default_app_bar.dart b/lib/features/app_layout/view/widgets/default_app_bar.dart index 2d29b96..2284543 100644 --- a/lib/features/app_layout/view/widgets/default_app_bar.dart +++ b/lib/features/app_layout/view/widgets/default_app_bar.dart @@ -35,8 +35,10 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { ) : null, ), - actions: HomeCubit.appBarActions[ - HomeCubit.bottomNavItems[HomeCubit.pageIndex].label], + actions: HomeCubit.manageScene + ? HomeCubit.appBarActions[ + HomeCubit.bottomNavItems[HomeCubit.pageIndex].label] + : null, )); }, ); diff --git a/lib/features/auth/bloc/auth_cubit.dart b/lib/features/auth/bloc/auth_cubit.dart index f4418b0..2d37c7d 100644 --- a/lib/features/auth/bloc/auth_cubit.dart +++ b/lib/features/auth/bloc/auth_cubit.dart @@ -221,6 +221,7 @@ class AuthCubit extends Cubit { List userFullName = fullName.split(' '); response = await AuthenticationAPI.signUp( model: SignUpModel( + hasAcceptedAppAgreement: true, email: email.toLowerCase(), password: signUpPassword, firstName: userFullName[0], diff --git a/lib/features/auth/model/signup_model.dart b/lib/features/auth/model/signup_model.dart index c4a0adf..c9b4fa1 100644 --- a/lib/features/auth/model/signup_model.dart +++ b/lib/features/auth/model/signup_model.dart @@ -3,10 +3,12 @@ class SignUpModel { final String password; final String firstName; final String lastName; + final bool hasAcceptedAppAgreement; SignUpModel( {required this.email, required this.password, + required this.hasAcceptedAppAgreement, required this.firstName, required this.lastName}); @@ -15,7 +17,8 @@ class SignUpModel { email: json['email'], password: json['password'], firstName: json['firstName'], - lastName: json['lastName']); + lastName: json['lastName'], + hasAcceptedAppAgreement: true); } Map toJson() { @@ -24,6 +27,7 @@ class SignUpModel { 'password': password, 'firstName': firstName, 'lastName': lastName, + "hasAcceptedAppAgreement": hasAcceptedAppAgreement }; } } diff --git a/lib/features/auth/model/user_model.dart b/lib/features/auth/model/user_model.dart index 5e055a7..143b114 100644 --- a/lib/features/auth/model/user_model.dart +++ b/lib/features/auth/model/user_model.dart @@ -15,6 +15,11 @@ class UserModel { final String? timeZone; final String? regionUuid; final bool? isAgreementAccepted; + final bool? hasAcceptedWebAgreement; + final DateTime? webAgreementAcceptedAt; + final bool? hasAcceptedAppAgreement; + final DateTime? appAgreementAcceptedAt; + final Role? role; UserModel({ required this.uuid, @@ -28,7 +33,11 @@ class UserModel { required this.isAgreementAccepted, required this.regionName, required this.timeZone, - // required this.role, + required this.hasAcceptedWebAgreement, + required this.webAgreementAcceptedAt, + required this.hasAcceptedAppAgreement, + required this.appAgreementAcceptedAt, + required this.role, }); factory UserModel.fromJson(Map json) { @@ -44,6 +53,15 @@ class UserModel { regionName: json['region']?['regionName'], timeZone: json['timeZone']?['timeZoneOffset'], regionUuid: json['region']?['uuid'], + hasAcceptedWebAgreement: json['hasAcceptedWebAgreement'], + webAgreementAcceptedAt: json['webAgreementAcceptedAt'] != null + ? DateTime.parse(json['webAgreementAcceptedAt']) + : null, + hasAcceptedAppAgreement: json['hasAcceptedAppAgreement'], + appAgreementAcceptedAt: json['appAgreementAcceptedAt'] != null + ? DateTime.parse(json['appAgreementAcceptedAt']) + : null, + role: json['role'] != null ? Role.fromJson(json['role']) : null, ); } @@ -61,6 +79,15 @@ class UserModel { regionUuid: null, regionName: tempJson['region']?['regionName'], timeZone: tempJson['timezone']?['timeZoneOffset'], + hasAcceptedWebAgreement: tempJson['hasAcceptedWebAgreement'], + webAgreementAcceptedAt: tempJson['webAgreementAcceptedAt'] != null + ? DateTime.parse(tempJson['webAgreementAcceptedAt']) + : null, + hasAcceptedAppAgreement: tempJson['hasAcceptedAppAgreement'], + appAgreementAcceptedAt: tempJson['appAgreementAcceptedAt'] != null + ? DateTime.parse(tempJson['appAgreementAcceptedAt']) + : null, + role: tempJson['role'] != null ? Role.fromJson(tempJson['role']) : null, ); } @@ -85,6 +112,43 @@ class UserModel { 'isAgreementAccepted': isAgreementAccepted, 'regionName': regionName, 'timeZone': timeZone, + 'hasAcceptedWebAgreement': hasAcceptedWebAgreement, + 'webAgreementAcceptedAt': webAgreementAcceptedAt?.toIso8601String(), + 'hasAcceptedAppAgreement': hasAcceptedAppAgreement, + 'appAgreementAcceptedAt': appAgreementAcceptedAt?.toIso8601String(), + 'role': role?.toJson(), + }; + } +} + +class Role { + final String? uuid; + final DateTime? createdAt; + final DateTime? updatedAt; + final String? type; + + Role({ + required this.uuid, + required this.createdAt, + required this.updatedAt, + required this.type, + }); + + factory Role.fromJson(Map json) { + return Role( + uuid: json['uuid'], + createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null, + updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null, + type: json['type'], + ); + } + + Map toJson() { + return { + 'uuid': uuid, + 'createdAt': createdAt?.toIso8601String(), + 'updatedAt': updatedAt?.toIso8601String(), + 'type': type, }; } } diff --git a/lib/features/devices/bloc/acs_bloc/acs_bloc.dart b/lib/features/devices/bloc/acs_bloc/acs_bloc.dart index 4fd7fe0..48fa716 100644 --- a/lib/features/devices/bloc/acs_bloc/acs_bloc.dart +++ b/lib/features/devices/bloc/acs_bloc/acs_bloc.dart @@ -433,7 +433,9 @@ class ACsBloc extends Bloc { seconds = event.seconds; final response = await DevicesAPI.controlDevice( DeviceControlModel( - deviceId: acId, code: 'countdown_time', value: event.duration), + deviceId: acId, + code: 'countdown_time', + value: event.duration), acId); if (response['success'] ?? false) { diff --git a/lib/features/devices/view/device_settings/profile_page.dart b/lib/features/devices/view/device_settings/profile_page.dart index 6e1f254..bb1d1df 100644 --- a/lib/features/devices/view/device_settings/profile_page.dart +++ b/lib/features/devices/view/device_settings/profile_page.dart @@ -38,8 +38,10 @@ class SettingProfilePage extends StatelessWidget { final _bloc = BlocProvider.of(context); return state is DeviceSettingLoadingState ? const Center( - child: - DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()), + child: DefaultContainer( + width: 50, + height: 50, + child: CircularProgressIndicator()), ) : RefreshIndicator( onRefresh: () async { @@ -55,15 +57,18 @@ class SettingProfilePage extends StatelessWidget { child: SvgPicture.asset( Assets.sosHomeIcon, fit: BoxFit.fitHeight, - height: MediaQuery.of(context).size.height * 0.13, + height: + MediaQuery.of(context).size.height * 0.13, )) : CircleAvatar( radius: 55, backgroundColor: ColorsManager.graysColor, child: ClipOval( child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, children: [ Center( child: SvgPicture.asset( @@ -71,7 +76,10 @@ class SettingProfilePage extends StatelessWidget { ? Assets.fourSceneIcon : Assets.sixSceneIcon, fit: BoxFit.contain, - height: MediaQuery.of(context).size.height * 0.08, + height: MediaQuery.of(context) + .size + .height * + 0.08, ), ), ], @@ -89,7 +97,8 @@ class SettingProfilePage extends StatelessWidget { children: [ IntrinsicWidth( child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 200), + constraints: + const BoxConstraints(maxWidth: 200), child: TextFormField( maxLength: 30, style: const TextStyle( @@ -122,7 +131,8 @@ class SettingProfilePage extends StatelessWidget { Assets.sosEditProfile, color: Colors.grey, fit: BoxFit.contain, - height: MediaQuery.of(context).size.height * 0.02, + height: MediaQuery.of(context).size.height * + 0.02, ), ), ), @@ -141,15 +151,17 @@ class SettingProfilePage extends StatelessWidget { padding: const EdgeInsets.all(20), child: InkWell( onTap: () async { - bool? val = await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => LocationSettingPage( - space: spaces!.first, - deviceId: device?.uuid ?? '', - )), - ); - if (val != null && val == true) { - _bloc.add(const DeviceSettingInitialInfo()); + if (HomeCubit.visitorPasswordManagement) { + bool? val = await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => LocationSettingPage( + space: spaces!.first, + deviceId: device?.uuid ?? '', + )), + ); + if (val != null && val == true) { + _bloc.add(const DeviceSettingInitialInfo()); + } } }, child: Row( @@ -162,7 +174,8 @@ class SettingProfilePage extends StatelessWidget { children: [ SizedBox( child: BodyMedium( - text: _bloc.deviceInfo.subspace.subspaceName, + text: _bloc + .deviceInfo.subspace.subspaceName, fontColor: ColorsManager.textGray, ), ), diff --git a/lib/features/devices/view/widgets/smart_door/door_grid.dart b/lib/features/devices/view/widgets/smart_door/door_grid.dart index a37be12..6d49a31 100644 --- a/lib/features/devices/view/widgets/smart_door/door_grid.dart +++ b/lib/features/devices/view/widgets/smart_door/door_grid.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/devices/view/widgets/smart_door/members_management_view.dart'; import 'package:syncrow_app/features/devices/view/widgets/smart_door/smart_linkage_view.dart'; import 'package:syncrow_app/features/devices/view/widgets/smart_door/temporary_password_page.dart'; @@ -14,6 +15,8 @@ class DoorLockGrid extends StatelessWidget { @override Widget build(BuildContext context) { + final buttons = doorLockButtons(val: uuid); + return GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), @@ -23,14 +26,15 @@ class DoorLockGrid extends StatelessWidget { crossAxisSpacing: 10, childAspectRatio: 1.75 / 1, ), - itemCount: 4, + itemCount: buttons.length, itemBuilder: (context, index) => DefaultContainer( onTap: () { //TODO: remove checking after adding the pages doorLockButtons()[index]['page'] != null ? Navigator.of(context).push( MaterialPageRoute( - builder: (context) => doorLockButtons(val: uuid)[index]['page'] as Widget, + builder: (context) => + doorLockButtons(val: uuid)[index]['page'] as Widget, ), ) : null; @@ -75,11 +79,12 @@ List> doorLockButtons({val}) => [ 'image': Assets.assetsIconsDoorlockAssetsMembersManagement, 'page': const MembersManagementView(), }, - { - 'title': 'Temporary Password', - 'image': Assets.assetsIconsDoorlockAssetsTemporaryPassword, - 'page': TemporaryPasswordPage(deviceId: val), - }, + if (HomeCubit.manageDeviceLocation) + { + 'title': 'Temporary Password', + 'image': Assets.assetsIconsDoorlockAssetsTemporaryPassword, + 'page': TemporaryPasswordPage(deviceId: val), + }, { 'title': 'Smart Linkage', 'image': Assets.assetsIconsDoorlockAssetsSmartLinkage, diff --git a/lib/features/menu/bloc/menu_cubit.dart b/lib/features/menu/bloc/menu_cubit.dart index 3850734..b868624 100644 --- a/lib/features/menu/bloc/menu_cubit.dart +++ b/lib/features/menu/bloc/menu_cubit.dart @@ -1,5 +1,15 @@ +import 'dart:ui'; + import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; +import 'package:syncrow_app/features/menu/bloc/privacy_policy.dart'; +import 'package:syncrow_app/features/menu/bloc/user_agreement.dart'; +import 'package:syncrow_app/features/menu/view/widgets/join_home/join_home_view.dart'; +import 'package:syncrow_app/features/menu/view/widgets/manage_home/manage_home_view.dart'; +import 'package:syncrow_app/features/menu/view/widgets/securty/view/securty_view.dart'; +import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/services/api/profile_api.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; part 'menu_state.dart'; @@ -32,4 +42,143 @@ class MenuCubit extends Cubit { emit(MenuError(error.toString())); } } + + List> menuSections = [ + //Home Management + { + 'title': 'Home Management', + 'color': ColorsManager.primaryColor, + 'buttons': [ + // { + // 'title': 'Create a Unit', + // 'Icon': Assets.assetsIconsMenuIconsHomeManagementIconsCreateHome, + // 'page': const CreateUnitView() + // }, + { + 'title': 'Join a Unit', + 'Icon': Assets.assetsIconsMenuIconsHomeManagementIconsJoinAHome, + 'page': const JoinHomeView() + }, + if (HomeCubit.manageSupSpace) + { + 'title': 'Manage Your Units', + 'Icon': + Assets.assetsIconsMenuIconsHomeManagementIconsManageYourHome, + 'page': const ManageHomeView() + }, + ], + }, + //General Settings + // { + // 'title': 'General Settings', + // 'color': const Color(0xFF023DFE), + // 'buttons': [ + // { + // 'title': 'Voice Assistant', + // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsVoiceAssistant, + // 'page': null + // }, + // { + // 'title': 'Temperature unit', + // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsTemperatureUnit, + // 'page': null + // }, + // { + // 'title': 'Touch tone on panel', + // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsTouchTone, + // 'page': null + // }, + // { + // 'title': 'Language', + // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsLanguage, + // 'page': null + // }, + // { + // 'title': 'Network Diagnosis', + // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsNetworkDiagnosis, + // 'page': null + // }, + // { + // 'title': 'Clear Cache', + // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsClearCach, + // 'page': null + // }, + // ], + // }, + // //Messages Center + // { + // 'title': 'Messages Center', + // 'color': const Color(0xFF0088FF), + // 'buttons': [ + // { + // 'title': 'Alerts', + // 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsAlerts, + // 'page': null + // }, + // { + // 'title': 'Messages', + // 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsMessages, + // 'page': null + // }, + // { + // 'title': 'FAQs', + // 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsFAQs, + // 'page': null + // }, + // { + // 'title': 'Help & Feedback', + // 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsHelpAndFeedback, + // 'page': null + // }, + // ], + // }, + //Security And Privacy + { + 'title': 'Security And Privacy', + 'color': const Color(0xFF8AB9FF), + 'buttons': [ + { + 'title': 'Security', + 'Icon': Assets.assetsIconsMenuIconsSecurityAndPrivacyIconsSecurty, + 'page': const SecurtyView() + }, + // { + // 'title': 'Privacy', + // 'Icon': Assets.assetsIconsMenuIconsSecurityAndPrivacyIconsPrivacy, + // 'page': const PrivacyView() + // }, + ], + }, + //Legal Information + { + 'title': 'Legal Information', + 'color': const Color(0xFF001B72), + 'buttons': [ + { + 'title': 'About', + 'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsAbout, + 'page': null + }, + { + 'title': 'Privacy Policy', + 'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsPrivacyPolicy, + 'page': const PrivacyPolicy() + }, + { + 'title': 'User Agreement', + 'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsUserAgreement, + 'page': const UserAgreement() + }, + ], + }, + ]; + + Future fetchMenuSections() async { + emit(MenuLoading()); + try { + emit(MenuItemsLoaded(menuSections)); + } catch (e) { + emit(MenuError(e.toString())); + } + } } diff --git a/lib/features/menu/bloc/menu_state.dart b/lib/features/menu/bloc/menu_state.dart index 9d6e0ca..f3cdbef 100644 --- a/lib/features/menu/bloc/menu_state.dart +++ b/lib/features/menu/bloc/menu_state.dart @@ -11,6 +11,11 @@ class MenuLoaded extends MenuState { MenuLoaded(this.userAgreementHtml); } + +class MenuItemsLoaded extends MenuState { +final List> menuSections; + MenuItemsLoaded(this.menuSections); +} class MenuError extends MenuState { final String message; diff --git a/lib/features/menu/view/menu_view.dart b/lib/features/menu/view/menu_view.dart index aa1ae86..c5e3d54 100644 --- a/lib/features/menu/view/menu_view.dart +++ b/lib/features/menu/view/menu_view.dart @@ -1,69 +1,62 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart'; import 'package:syncrow_app/features/menu/bloc/menu_cubit.dart'; import 'package:syncrow_app/features/menu/view/widgets/menu_list.dart'; import 'package:syncrow_app/features/menu/view/widgets/profile/profile_tab.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/utils/context_extension.dart'; -import 'package:syncrow_app/utils/resource_manager/constants.dart'; class MenuView extends StatelessWidget { - const MenuView({super.key}); + const MenuView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( - create: (BuildContext context) => MenuCubit(), + create: (BuildContext context) => MenuCubit()..fetchMenuSections(), child: BlocBuilder( - builder: (context, state) { - return BlocBuilder( - builder: (context, state) { - return SingleChildScrollView( - physics: const BouncingScrollPhysics(), - child: Column( - children: [ - const ProfileTab(), - for (var section in menuSections) - MenuList( - section: section, - ), - const SizedBox( - height: 15, - ), - BodyMedium(text: dotenv.env['ENV_NAME'] ?? ''), - const SizedBox( - height: 15, - ), - InkWell( - onTap: () { - AuthCubit.get(context).logout(); - }, - child: Row( - children: [ - Expanded( - child: DefaultContainer( - child: Center( - child: BodyLarge( - text: 'Logout', - style: context.bodyLarge.copyWith( - color: Colors.red, - ), + builder: (context, menuState) { + if (menuState is MenuLoading) { + return const Center(child: CircularProgressIndicator()); + } else if (menuState is MenuError) { + return Center(child: Text(menuState.message)); + } else if (menuState is MenuItemsLoaded) { + final sections = menuState.menuSections; + return SingleChildScrollView( + physics: const BouncingScrollPhysics(), + child: Column( + children: [ + const ProfileTab(), + for (var section in sections) MenuList(section: section), + const SizedBox(height: 15), + InkWell( + onTap: () { + AuthCubit.get(context).logout(); + }, + child: Row( + children: [ + Expanded( + child: DefaultContainer( + child: Center( + child: BodyLarge( + text: 'Logout', + style: context.bodyLarge.copyWith( + color: Colors.red, ), ), ), ), - ], - ), - ) - ], - ), - ); - }, - ); + ), + ], + ), + ), + ], + ), + ); + } + // Fallback in case no states match + return const SizedBox.shrink(); }, ), ); diff --git a/lib/features/scene/widgets/scene_view_widget/scene_item.dart b/lib/features/scene/widgets/scene_view_widget/scene_item.dart index ccedaac..38edbbd 100644 --- a/lib/features/scene/widgets/scene_view_widget/scene_item.dart +++ b/lib/features/scene/widgets/scene_view_widget/scene_item.dart @@ -36,34 +36,38 @@ class SceneItem extends StatelessWidget { Widget build(BuildContext context) { return DefaultContainer( onTap: () { - context.read().add(const SmartSceneClearEvent()); - if (disablePlayButton == false) { - BlocProvider.of(context) - .add(FetchSceneTasksEvent(sceneId: scene.id, isAutomation: false)); + if (HomeCubit.manageScene) { + context + .read() + .add(const SmartSceneClearEvent()); + if (disablePlayButton == false) { + BlocProvider.of(context).add( + FetchSceneTasksEvent(sceneId: scene.id, isAutomation: false)); - /// the state to set the scene type must be after the fetch - BlocProvider.of(context) - .add(const SceneTypeEvent(CreateSceneEnum.tabToRun)); - } else { - BlocProvider.of(context) - .add(FetchSceneTasksEvent(sceneId: scene.id, isAutomation: true)); + /// the state to set the scene type must be after the fetch + BlocProvider.of(context) + .add(const SceneTypeEvent(CreateSceneEnum.tabToRun)); + } else { + BlocProvider.of(context).add( + FetchSceneTasksEvent(sceneId: scene.id, isAutomation: true)); - /// the state to set the scene type must be after the fetch - BlocProvider.of(context) - .add(const SceneTypeEvent(CreateSceneEnum.deviceStatusChanges)); + /// the state to set the scene type must be after the fetch + BlocProvider.of(context) + .add(const SceneTypeEvent(CreateSceneEnum.deviceStatusChanges)); + } + + Navigator.pushNamed( + context, + Routes.sceneTasksRoute, + arguments: SceneSettingsRouteArguments( + sceneType: disablePlayButton == false + ? CreateSceneEnum.tabToRun.name + : CreateSceneEnum.deviceStatusChanges.name, + sceneId: scene.id, + sceneName: scene.name, + ), + ); } - - Navigator.pushNamed( - context, - Routes.sceneTasksRoute, - arguments: SceneSettingsRouteArguments( - sceneType: disablePlayButton == false - ? CreateSceneEnum.tabToRun.name - : CreateSceneEnum.deviceStatusChanges.name, - sceneId: scene.id, - sceneName: scene.name, - ), - ); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -79,8 +83,11 @@ class SceneItem extends StatelessWidget { height: 32, width: 32, fit: BoxFit.fill, - errorBuilder: (context, error, stackTrace) => - Image.asset(Assets.assetsIconsLogo, height: 32, width: 32, fit: BoxFit.fill), + errorBuilder: (context, error, stackTrace) => Image.asset( + Assets.assetsIconsLogo, + height: 32, + width: 32, + fit: BoxFit.fill), ), if (disablePlayButton || scene.iconInBytes.isEmpty) SvgPicture.asset( @@ -93,7 +100,9 @@ class SceneItem extends StatelessWidget { ? IconButton( padding: EdgeInsets.zero, onPressed: () { - context.read().add(SceneTrigger(scene.id, scene.name)); + context + .read() + .add(SceneTrigger(scene.id, scene.name)); }, icon: isLoading ? const Center( @@ -115,11 +124,15 @@ class SceneItem extends StatelessWidget { activeColor: ColorsManager.primaryColor, value: scene.status == 'enable' ? true : false, onChanged: (value) { - context.read().add(UpdateAutomationStatus( - automationStatusUpdate: AutomationStatusUpdate( - isEnable: value, - spaceUuid: HomeCubit.getInstance().selectedSpace!.id), - automationId: scene.id)); + context.read().add( + UpdateAutomationStatus( + automationStatusUpdate: + AutomationStatusUpdate( + isEnable: value, + spaceUuid: HomeCubit.getInstance() + .selectedSpace! + .id), + automationId: scene.id)); }, ), ], diff --git a/lib/features/shared_widgets/create_unit.dart b/lib/features/shared_widgets/create_unit.dart index 05db4dd..b2b2d11 100644 --- a/lib/features/shared_widgets/create_unit.dart +++ b/lib/features/shared_widgets/create_unit.dart @@ -16,7 +16,7 @@ class CreateUnitWidget extends StatelessWidget { TextEditingController textEditingController = TextEditingController(); return BlocConsumer( listener: (context, state) { - if (state is ActivationError) {} + // if (state is ActivationError) {} }, builder: (context, state) { return SingleChildScrollView( @@ -96,7 +96,11 @@ class CreateUnitWidget extends StatelessWidget { textEditingController.text)) { CustomSnackBar.displaySnackBar( 'Done successfully'); - Navigator.of(context).pop(); + Future.delayed( + const Duration(milliseconds: 500), + () { + Navigator.of(context).pop(); + }); } else { CustomSnackBar.displaySnackBar( 'Wrong code!'); @@ -109,14 +113,14 @@ class CreateUnitWidget extends StatelessWidget { ], ), ), - state is ActivationError - ? Text( - state.errMessage, - style: const TextStyle( - color: ColorsManager.red, - fontWeight: FontWeight.w400), - ) - : const SizedBox() + // state is ActivationError + // ? Text( + // state.errMessage, + // style: const TextStyle( + // color: ColorsManager.red, + // fontWeight: FontWeight.w400), + // ) + // : const SizedBox() ], ), ], @@ -136,42 +140,42 @@ class CreateUnitWidget extends StatelessWidget { } } - // return SizedBox( - // width: MediaQuery.sizeOf(context).width, - // height: MediaQuery.sizeOf(context).height, - // child: Column( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // SvgPicture.asset( - // Assets.noUnitsIconDashboard, - // width: 100, - // height: 100, - // ), - // const SizedBox( - // height: 50, - // ), - // Flexible( - // child: GestureDetector( - // onTap: () { - // Navigator.pushNamed(context, Routes.createUnit); - // }, - // child: Container( - // padding: const EdgeInsets.symmetric(horizontal: 34, vertical: 14), - // decoration: ShapeDecoration( - // color: const Color(0x99023DFE), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(20), - // ), - // ), - // child: const TitleMedium( - // text: 'Create a unit', - // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: Colors.white), - // ), - // ), - // ), - // ), - // ], - // ), - // ); +// return SizedBox( +// width: MediaQuery.sizeOf(context).width, +// height: MediaQuery.sizeOf(context).height, +// child: Column( +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// SvgPicture.asset( +// Assets.noUnitsIconDashboard, +// width: 100, +// height: 100, +// ), +// const SizedBox( +// height: 50, +// ), +// Flexible( +// child: GestureDetector( +// onTap: () { +// Navigator.pushNamed(context, Routes.createUnit); +// }, +// child: Container( +// padding: const EdgeInsets.symmetric(horizontal: 34, vertical: 14), +// decoration: ShapeDecoration( +// color: const Color(0x99023DFE), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(20), +// ), +// ), +// child: const TitleMedium( +// text: 'Create a unit', +// style: TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: Colors.white), +// ), +// ), +// ), +// ), +// ], +// ), +// ); // } // } diff --git a/lib/services/api/api_links_endpoints.dart b/lib/services/api/api_links_endpoints.dart index b72cc20..b9ec231 100644 --- a/lib/services/api/api_links_endpoints.dart +++ b/lib/services/api/api_links_endpoints.dart @@ -225,4 +225,7 @@ abstract class ApiEndpoints { static const String getDeviceLogs = '/device/report-logs/{uuid}?code={code}'; static const String terms = '/terms'; static const String policy = '/policy'; + static const String getPermission = '/permission/{roleUuid}'; + + ///permission/roleUuid } diff --git a/lib/services/api/devices_api.dart b/lib/services/api/devices_api.dart index 2110a37..ac60f45 100644 --- a/lib/services/api/devices_api.dart +++ b/lib/services/api/devices_api.dart @@ -88,7 +88,8 @@ class DevicesAPI { static Future> getDeviceStatus(String deviceId) async { final response = await _httpService.get( - path: ApiEndpoints.deviceFunctionsStatus.replaceAll('{deviceUuid}', deviceId), + path: ApiEndpoints.deviceFunctionsStatus + .replaceAll('{deviceUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -97,7 +98,8 @@ class DevicesAPI { return response; } - static Future> getPowerClampStatus(String deviceId) async { + static Future> getPowerClampStatus( + String deviceId) async { final response = await _httpService.get( path: ApiEndpoints.powerClamp.replaceAll('{powerClampUuid}', deviceId), showServerMessage: false, @@ -109,7 +111,9 @@ class DevicesAPI { } static Future> renamePass( - {required String name, required String doorLockUuid, required String passwordId}) async { + {required String name, + required String doorLockUuid, + required String passwordId}) async { final response = await _httpService.put( path: ApiEndpoints.renamePassword .replaceAll('{doorLockUuid}', doorLockUuid) @@ -144,7 +148,8 @@ class DevicesAPI { return response; } - static Future getSceneBySwitchName({String? deviceId, String? switchName}) async { + static Future getSceneBySwitchName( + {String? deviceId, String? switchName}) async { final response = await _httpService.get( path: ApiEndpoints.fourSceneByName .replaceAll('{deviceUuid}', deviceId!) @@ -165,7 +170,11 @@ class DevicesAPI { final response = await _httpService.post( path: ApiEndpoints.deviceScene.replaceAll('{deviceUuid}', deviceId!), body: jsonEncode( - {"switchName": switchName, "sceneUuid": sceneUuid, "spaceUuid": spaceUuid}, + { + "switchName": switchName, + "sceneUuid": sceneUuid, + "spaceUuid": spaceUuid + }, ), showServerMessage: false, expectedResponseModel: (json) { @@ -185,7 +194,8 @@ class DevicesAPI { return response; } - static Future> getDeviceByGroupName(String unitId, String groupName) async { + static Future> getDeviceByGroupName( + String unitId, String groupName) async { final response = await _httpService.get( path: ApiEndpoints.devicesByGroupName .replaceAll('{unitUuid}', unitId) @@ -230,7 +240,9 @@ class DevicesAPI { if (json == null || json.isEmpty || json == []) { return []; } - return data.map((device) => DeviceModel.fromJson(device)).toList(); + return data + .map((device) => DeviceModel.fromJson(device)) + .toList(); }, ); @@ -242,7 +254,8 @@ class DevicesAPI { } } - static Future> getDevicesByGatewayId(String gatewayId) async { + static Future> getDevicesByGatewayId( + String gatewayId) async { final response = await _httpService.get( path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId), showServerMessage: false, @@ -264,7 +277,8 @@ class DevicesAPI { String deviceId, ) async { final response = await _httpService.get( - path: ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.getTemporaryPassword + .replaceAll('{doorLockUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -275,7 +289,8 @@ class DevicesAPI { static Future getOneTimePasswords(String deviceId) async { final response = await _httpService.get( - path: ApiEndpoints.getOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.getOneTimeTemporaryPassword + .replaceAll('{doorLockUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -286,7 +301,8 @@ class DevicesAPI { static Future getTimeLimitPasswords(String deviceId) async { final response = await _httpService.get( - path: ApiEndpoints.getMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.getMultipleTimeTemporaryPassword + .replaceAll('{doorLockUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -311,10 +327,12 @@ class DevicesAPI { "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.addTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.addTemporaryPassword + .replaceAll('{doorLockUuid}', deviceId), body: body, showServerMessage: false, expectedResponseModel: (json) => json, @@ -325,7 +343,8 @@ class DevicesAPI { static Future generateOneTimePassword({deviceId}) async { try { final response = await _httpService.post( - path: ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.addOneTimeTemporaryPassword + .replaceAll('{doorLockUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -337,10 +356,12 @@ class DevicesAPI { } } - static Future generateMultiTimePassword({deviceId, effectiveTime, invalidTime}) async { + static Future generateMultiTimePassword( + {deviceId, effectiveTime, invalidTime}) async { try { final response = await _httpService.post( - path: ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.addMultipleTimeTemporaryPassword + .replaceAll('{doorLockUuid}', deviceId), showServerMessage: true, body: {"effectiveTime": effectiveTime, "invalidTime": invalidTime}, expectedResponseModel: (json) { @@ -530,7 +551,9 @@ class DevicesAPI { String code, ) async { final response = await HTTPService().get( - path: ApiEndpoints.getDeviceLogs.replaceAll('{uuid}', uuid).replaceAll('{code}', code), + path: ApiEndpoints.getDeviceLogs + .replaceAll('{uuid}', uuid) + .replaceAll('{code}', code), showServerMessage: false, expectedResponseModel: (json) { return DeviceReport.fromJson(json); diff --git a/lib/services/api/profile_api.dart b/lib/services/api/profile_api.dart index 0c86fef..dcaf168 100644 --- a/lib/services/api/profile_api.dart +++ b/lib/services/api/profile_api.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:developer'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/auth/model/user_model.dart'; import 'package:syncrow_app/features/menu/model/region_model.dart'; @@ -95,6 +94,16 @@ class ProfileApi { return response; } + Future fetchPermissions(roleId) async { + final response = await _httpService.get( + path: ApiEndpoints.getPermission.replaceAll('{roleUuid}', roleId!), + showServerMessage: true, + expectedResponseModel: (json) { + return json; + }); + return response; + } + static Future> fetchRegion() async { final response = await _httpService.get( path: ApiEndpoints.getRegion, @@ -117,7 +126,7 @@ class ProfileApi { return response as List; } - Future fetchUserAgreement() async { + Future fetchUserAgreement() async { final response = await _httpService.get( path: ApiEndpoints.terms, showServerMessage: true, @@ -127,7 +136,7 @@ class ProfileApi { return response; } - Future fetchPrivacyPolicy() async { + Future fetchPrivacyPolicy() async { final response = await _httpService.get( path: ApiEndpoints.policy, showServerMessage: true, diff --git a/lib/utils/resource_manager/constants.dart b/lib/utils/resource_manager/constants.dart index 4d099c3..01dde3c 100644 --- a/lib/utils/resource_manager/constants.dart +++ b/lib/utils/resource_manager/constants.dart @@ -1,5 +1,6 @@ //ignore_for_file: constant_identifier_names import 'dart:ui'; +import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/devices/model/function_model.dart'; import 'package:syncrow_app/features/menu/bloc/privacy_policy.dart'; import 'package:syncrow_app/features/menu/bloc/user_agreement.dart'; @@ -677,134 +678,6 @@ K? getNextItem(Map map, V value) { return null; } -List> menuSections = [ - //Home Management - { - 'title': 'Home Management', - 'color': ColorsManager.primaryColor, - 'buttons': [ - // { - // 'title': 'Create a Unit', - // 'Icon': Assets.assetsIconsMenuIconsHomeManagementIconsCreateHome, - // 'page': const CreateUnitView() - // }, - { - 'title': 'Join a Unit', - 'Icon': Assets.assetsIconsMenuIconsHomeManagementIconsJoinAHome, - 'page': const JoinHomeView() - }, - { - 'title': 'Manage Your Units', - 'Icon': Assets.assetsIconsMenuIconsHomeManagementIconsManageYourHome, - 'page': const ManageHomeView() - }, - ], - }, - //General Settings - // { - // 'title': 'General Settings', - // 'color': const Color(0xFF023DFE), - // 'buttons': [ - // { - // 'title': 'Voice Assistant', - // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsVoiceAssistant, - // 'page': null - // }, - // { - // 'title': 'Temperature unit', - // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsTemperatureUnit, - // 'page': null - // }, - // { - // 'title': 'Touch tone on panel', - // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsTouchTone, - // 'page': null - // }, - // { - // 'title': 'Language', - // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsLanguage, - // 'page': null - // }, - // { - // 'title': 'Network Diagnosis', - // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsNetworkDiagnosis, - // 'page': null - // }, - // { - // 'title': 'Clear Cache', - // 'Icon': Assets.assetsIconsMenuIconsGeneralSettingsIconsClearCach, - // 'page': null - // }, - // ], - // }, - // //Messages Center - // { - // 'title': 'Messages Center', - // 'color': const Color(0xFF0088FF), - // 'buttons': [ - // { - // 'title': 'Alerts', - // 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsAlerts, - // 'page': null - // }, - // { - // 'title': 'Messages', - // 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsMessages, - // 'page': null - // }, - // { - // 'title': 'FAQs', - // 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsFAQs, - // 'page': null - // }, - // { - // 'title': 'Help & Feedback', - // 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsHelpAndFeedback, - // 'page': null - // }, - // ], - // }, - //Security And Privacy - { - 'title': 'Security And Privacy', - 'color': const Color(0xFF8AB9FF), - 'buttons': [ - { - 'title': 'Security', - 'Icon': Assets.assetsIconsMenuIconsSecurityAndPrivacyIconsSecurty, - 'page': const SecurtyView() - }, - // { - // 'title': 'Privacy', - // 'Icon': Assets.assetsIconsMenuIconsSecurityAndPrivacyIconsPrivacy, - // 'page': const PrivacyView() - // }, - ], - }, - //Legal Information - { - 'title': 'Legal Information', - 'color': const Color(0xFF001B72), - 'buttons': [ - { - 'title': 'About', - 'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsAbout, - 'page': null - }, - { - 'title': 'Privacy Policy', - 'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsPrivacyPolicy, - 'page': const PrivacyPolicy() - }, - { - 'title': 'User Agreement', - 'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsUserAgreement, - 'page': const UserAgreement() - }, - ], - }, -]; - enum MemberRole { FamilyMember, OtherMember,