From cf817fd5dcc572799b0ee5b34db2e1902005dbac Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Wed, 27 Nov 2024 19:41:43 +0300 Subject: [PATCH] push display scenes and automations --- .../view/device_managment_page.dart | 17 +- .../widgets/device_search_filters.dart | 8 - .../bloc/routine_bloc/routine_bloc.dart | 5 +- .../bloc/routine_bloc/routine_event.dart | 5 +- .../create_automation_model.dart | 172 ------------------ lib/pages/routiens/models/routine_model.dart | 4 +- lib/pages/routiens/view/routines_view.dart | 3 +- .../fetch_routine_scenes_automation.dart | 155 ++++++++-------- .../main_routine_view/routine_view_card.dart | 12 +- .../routine_dialogs/discard_dialog.dart | 2 - .../widgets/scenes_and_automations.dart | 6 +- lib/services/routines_api.dart | 32 +++- lib/utils/constants/api_const.dart | 2 + 13 files changed, 141 insertions(+), 282 deletions(-) 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 ffc57131..06adfd6c 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 @@ -18,13 +18,13 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider( - create: (context) => DeviceManagementBloc()..add(FetchDevices()), - ), BlocProvider( create: (context) => SwitchTabsBloc()..add(const TriggerSwitchTabsEvent(false)), ), + BlocProvider( + create: (context) => DeviceManagementBloc()..add(FetchDevices()), + ), ], child: WebScaffold( appBarTitle: FittedBox( @@ -101,12 +101,11 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { builder: (context, deviceState) { if (deviceState is DeviceManagementLoading) { return const Center(child: CircularProgressIndicator()); - } else if (deviceState is DeviceManagementLoaded || - deviceState is DeviceManagementFiltered) { - final devices = (deviceState as dynamic).devices ?? - (deviceState as DeviceManagementFiltered).filteredDevices; - - return DeviceManagementBody(devices: devices); + } else if (deviceState is DeviceManagementLoaded) { + return DeviceManagementBody(devices: deviceState.devices); + } else if (deviceState is DeviceManagementFiltered) { + return DeviceManagementBody( + devices: deviceState.filteredDevices); } else { return const Center(child: Text('Error fetching Devices')); } diff --git a/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart b/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart index e3bec220..b9e36c25 100644 --- a/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart +++ b/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart @@ -18,14 +18,6 @@ class _DeviceSearchFiltersState extends State final TextEditingController unitNameController = TextEditingController(); final TextEditingController productNameController = TextEditingController(); - @override - void dispose() { - communityController.dispose(); - unitNameController.dispose(); - productNameController.dispose(); - super.dispose(); - } - @override Widget build(BuildContext context) { return isExtraLargeScreenSize(context) diff --git a/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart index dd76e01a..8506171b 100644 --- a/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart @@ -13,6 +13,7 @@ part 'routine_event.dart'; part 'routine_state.dart'; const spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; +const communityId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; class RoutineBloc extends Bloc { RoutineBloc() : super(const RoutineState()) { @@ -114,7 +115,7 @@ class RoutineBloc extends Bloc { emit(state.copyWith(isLoading: true, errorMessage: null)); try { - final scenes = await SceneApi.getScenesByUnitId(event.unitId); + final scenes = await SceneApi.getScenesByUnitId(event.unitId, event.communityId); emit(state.copyWith( scenes: scenes, isLoading: false, @@ -233,7 +234,7 @@ class RoutineBloc extends Bloc { final result = await SceneApi.createScene(createSceneModel); if (result['success']) { emit(_resetState()); - add(const LoadScenes(spaceId)); + add(const LoadScenes(spaceId, communityId)); } else { emit(state.copyWith( isLoading: false, diff --git a/lib/pages/routiens/bloc/routine_bloc/routine_event.dart b/lib/pages/routiens/bloc/routine_bloc/routine_event.dart index 575f199d..909e458d 100644 --- a/lib/pages/routiens/bloc/routine_bloc/routine_event.dart +++ b/lib/pages/routiens/bloc/routine_bloc/routine_event.dart @@ -28,11 +28,12 @@ class AddToThenContainer extends RoutineEvent { class LoadScenes extends RoutineEvent { final String unitId; + final String communityId; - const LoadScenes(this.unitId); + const LoadScenes(this.unitId, this.communityId); @override - List get props => [unitId]; + List get props => [unitId, communityId]; } class LoadAutomation extends RoutineEvent { diff --git a/lib/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart b/lib/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart index cd9a9c60..c02e5dab 100644 --- a/lib/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart +++ b/lib/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart @@ -1,177 +1,5 @@ import 'dart:convert'; -import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart'; - -// class CreateAutomationModel { -// String unitUuid; -// String automationName; -// String decisionExpr; -// EffectiveTime effectiveTime; -// List conditions; -// List actions; - -// CreateAutomationModel({ -// required this.unitUuid, -// required this.automationName, -// required this.decisionExpr, -// required this.effectiveTime, -// required this.conditions, -// required this.actions, -// }); - -// CreateAutomationModel copyWith({ -// String? unitUuid, -// String? automationName, -// String? decisionExpr, -// EffectiveTime? effectiveTime, -// List? conditions, -// List? actions, -// }) { -// return CreateAutomationModel( -// unitUuid: unitUuid ?? this.unitUuid, -// automationName: automationName ?? this.automationName, -// decisionExpr: decisionExpr ?? this.decisionExpr, -// effectiveTime: effectiveTime ?? this.effectiveTime, -// conditions: conditions ?? this.conditions, -// actions: actions ?? this.actions, -// ); -// } - -// Map toMap([String? automationId]) { -// return { -// if (automationId == null) 'spaceUuid': unitUuid, -// 'automationName': automationName, -// 'decisionExpr': decisionExpr, -// 'effectiveTime': effectiveTime.toMap(), -// 'conditions': conditions.map((x) => x.toMap()).toList(), -// 'actions': actions.map((x) => x.toMap()).toList(), -// }; -// } - -// factory CreateAutomationModel.fromMap(Map map) { -// return CreateAutomationModel( -// unitUuid: map['spaceUuid'] ?? '', -// automationName: map['automationName'] ?? '', -// decisionExpr: map['decisionExpr'] ?? '', -// effectiveTime: EffectiveTime.fromMap(map['effectiveTime']), -// conditions: List.from( -// map['conditions']?.map((x) => CreateCondition.fromMap(x))), -// actions: List.from( -// map['actions']?.map((x) => CreateSceneAction.fromMap(x))), -// ); -// } - -// String toJson([String? automationId]) => json.encode(toMap(automationId)); - -// factory CreateAutomationModel.fromJson(String source) => -// CreateAutomationModel.fromMap(json.decode(source)); - -// @override -// String toString() { -// return 'CreateAutomationModel(unitUuid: $unitUuid, automationName: $automationName, decisionExpr: $decisionExpr, effectiveTime: $effectiveTime, conditions: $conditions, actions: $actions)'; -// } -// } - -// class EffectiveTime { -// String start; -// String end; -// String loops; - -// EffectiveTime({ -// required this.start, -// required this.end, -// required this.loops, -// }); - -// Map toMap() { -// return { -// 'start': start, -// 'end': end, -// 'loops': loops, -// }; -// } - -// factory EffectiveTime.fromMap(Map map) { -// return EffectiveTime( -// start: map['start'] ?? '', -// end: map['end'] ?? '', -// loops: map['loops'] ?? '', -// ); -// } - -// @override -// String toString() => 'EffectiveTime(start: $start, end: $end, loops: $loops)'; -// } - -// class CreateCondition { -// int code; -// String entityId; -// String entityType; -// ConditionExpr expr; - -// CreateCondition({ -// required this.code, -// required this.entityId, -// required this.entityType, -// required this.expr, -// }); - -// Map toMap() { -// return { -// 'code': code, -// 'entityId': entityId, -// 'entityType': entityType, -// 'expr': expr.toMap(), -// }; -// } - -// factory CreateCondition.fromMap(Map map) { -// return CreateCondition( -// code: map['code'] ?? 0, -// entityId: map['entityId'] ?? '', -// entityType: map['entityType'] ?? '', -// expr: ConditionExpr.fromMap(map['expr']), -// ); -// } - -// @override -// String toString() => -// 'CreateCondition(code: $code, entityId: $entityId, entityType: $entityType, expr: $expr)'; -// } - -// class ConditionExpr { -// String statusCode; -// String comparator; -// dynamic statusValue; - -// ConditionExpr({ -// required this.statusCode, -// required this.comparator, -// required this.statusValue, -// }); - -// Map toMap() { -// return { -// 'statusCode': statusCode, -// 'comparator': comparator, -// 'statusValue': statusValue, -// }; -// } - -// factory ConditionExpr.fromMap(Map map) { -// return ConditionExpr( -// statusCode: map['statusCode'] ?? '', -// comparator: map['comparator'] ?? '', -// statusValue: map['statusValue'], -// ); -// } - -// @override -// String toString() => -// 'ConditionExpr(statusCode: $statusCode, comparator: $comparator, statusValue: $statusValue)'; -// } -import 'dart:convert'; - class CreateAutomationModel { String spaceUuid; String automationName; diff --git a/lib/pages/routiens/models/routine_model.dart b/lib/pages/routiens/models/routine_model.dart index e2075579..3ee7bd03 100644 --- a/lib/pages/routiens/models/routine_model.dart +++ b/lib/pages/routiens/models/routine_model.dart @@ -22,9 +22,9 @@ class ScenesModel { name: json["name"] ?? '', status: json["status"] ?? '', type: json["type"] ?? '', - icon: (isAutomation ?? false) + icon: isAutomation == true ? Assets.automation - : json["icon"] as String?, + : (json["icon"] as String?), ); Map toJson() => { diff --git a/lib/pages/routiens/view/routines_view.dart b/lib/pages/routiens/view/routines_view.dart index 05560b2b..f2dac85f 100644 --- a/lib/pages/routiens/view/routines_view.dart +++ b/lib/pages/routiens/view/routines_view.dart @@ -49,8 +49,7 @@ class RoutinesView extends StatelessWidget { const SizedBox( height: 30, ), - const FetchRoutineScenesAutomation(), - const Spacer(), + const Expanded(child: FetchRoutineScenesAutomation()), ], ), ); diff --git a/lib/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart b/lib/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart index 82c83c3c..81dfa13b 100644 --- a/lib/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart +++ b/lib/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart @@ -4,12 +4,14 @@ import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/routine_view_card.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; class FetchRoutineScenesAutomation extends StatefulWidget { const FetchRoutineScenesAutomation({super.key}); @override - State createState() => _FetchRoutineScenesState(); + State createState() => + _FetchRoutineScenesState(); } class _FetchRoutineScenesState extends State { @@ -17,7 +19,7 @@ class _FetchRoutineScenesState extends State { void initState() { super.initState(); context.read() - ..add(const LoadScenes(spaceId)) + ..add(const LoadScenes(spaceId, communityId)) ..add(const LoadAutomation(spaceId)); } @@ -25,83 +27,84 @@ class _FetchRoutineScenesState extends State { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - debugPrint(state.scenes.toString()); - debugPrint(state.automations.toString()); - - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Scenes (Tab to Run)", - style: Theme.of(context).textTheme.titleLarge?.copyWith( - color: ColorsManager.grayColor, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox( - height: 10, - ), - state.loadScenesErrorMessage != null - ? Text(state.loadScenesErrorMessage ?? '') - : state.scenes.isNotEmpty - ? SizedBox( - height: 200, - child: ListView.builder( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - itemCount: state.scenes.length, - itemBuilder: (context, index) { - return RoutineViewCard( - onTap: () {}, - textString: state.scenes[index].name, - icon: state.scenes[index].icon ?? Assets.logoHorizontal, - ); - }, - ), - ) - : const CircularProgressIndicator(), - const SizedBox( - height: 30, - ), - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + return SizedBox( + height: 500, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (state.isLoading) + const Center( + child: CircularProgressIndicator(), + ), + Text( + "Scenes (Tab to Run)", + style: Theme.of(context).textTheme.titleLarge?.copyWith( + color: ColorsManager.grayColor, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 10), + if (state.scenes.isEmpty) Text( - "Automations", - style: Theme.of(context).textTheme.titleLarge?.copyWith( - color: ColorsManager.grayColor, - fontWeight: FontWeight.bold, - ), + "No scenes found", + style: context.textTheme.bodyMedium?.copyWith( + color: ColorsManager.grayColor, + ), ), - const SizedBox( - height: 10, + if (state.scenes.isNotEmpty) + SizedBox( + height: 200, + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.horizontal, + itemCount: state.scenes.length, + itemBuilder: (context, index) { + return RoutineViewCard( + onTap: () {}, + textString: state.scenes[index].name, + icon: state.scenes[index].icon ?? Assets.logoHorizontal, + ); + }, + ), ), - state.loadAutomationErrorMessage != null - ? Text(state.loadAutomationErrorMessage ?? '') - : state.automations.isNotEmpty - ? Expanded( - child: SizedBox( - height: 200, - child: ListView.builder( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - itemCount: state.automations.length, - itemBuilder: (context, index) { - return RoutineViewCard( - onTap: () {}, - textString: state.automations[index].name, - icon: Assets.automation, - ); - }, - ), - ), - ) - : const CircularProgressIndicator(), - ], - ) - ], + const SizedBox(height: 30), + Text( + "Automations", + style: Theme.of(context).textTheme.titleLarge?.copyWith( + color: ColorsManager.grayColor, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 10), + if (state.automations.isEmpty) + Text( + "No automations found", + style: context.textTheme.bodyMedium?.copyWith( + color: ColorsManager.grayColor, + ), + ), + if (state.automations.isNotEmpty) + SizedBox( + height: 200, + child: ListView.builder( + shrinkWrap: true, + scrollDirection: Axis.horizontal, + itemCount: state.automations.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(right: 8.0), + child: RoutineViewCard( + onTap: () {}, + textString: state.automations[index].name, + icon: state.automations[index].icon ?? + Assets.automation, + ), + ); + }, + ), + ), + ], + ), ); }, ); diff --git a/lib/pages/routiens/widgets/main_routine_view/routine_view_card.dart b/lib/pages/routiens/widgets/main_routine_view/routine_view_card.dart index 6c9f16f6..9d8b2d19 100644 --- a/lib/pages/routiens/widgets/main_routine_view/routine_view_card.dart +++ b/lib/pages/routiens/widgets/main_routine_view/routine_view_card.dart @@ -47,8 +47,16 @@ class RoutineViewCard extends StatelessWidget { ), height: 70, width: 70, - child: (icon is String) && icon.contains('.svg') - ? SvgPicture.asset(icon) + child: (icon is String) + ? icon.endsWith('.svg') + ? SvgPicture.asset( + icon, + fit: BoxFit.contain, + ) + : Image.asset( + icon, + fit: BoxFit.contain, + ) : Icon( icon, color: ColorsManager.dialogBlueTitle, diff --git a/lib/pages/routiens/widgets/routine_dialogs/discard_dialog.dart b/lib/pages/routiens/widgets/routine_dialogs/discard_dialog.dart index 8b22a671..4c8e4688 100644 --- a/lib/pages/routiens/widgets/routine_dialogs/discard_dialog.dart +++ b/lib/pages/routiens/widgets/routine_dialogs/discard_dialog.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_web/pages/common/custom_table.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart'; -import 'package:syncrow_web/pages/home/bloc/home_bloc.dart'; import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; diff --git a/lib/pages/routiens/widgets/scenes_and_automations.dart b/lib/pages/routiens/widgets/scenes_and_automations.dart index 36ee7db2..a0bd1ed6 100644 --- a/lib/pages/routiens/widgets/scenes_and_automations.dart +++ b/lib/pages/routiens/widgets/scenes_and_automations.dart @@ -18,7 +18,7 @@ class _ScenesAndAutomationsState extends State { void initState() { super.initState(); context.read() - ..add(const LoadScenes(spaceId)) + ..add(const LoadScenes(spaceId, communityId)) ..add(const LoadAutomation(spaceId)); } @@ -34,7 +34,9 @@ class _ScenesAndAutomationsState extends State { children: scenes.asMap().entries.map((entry) { final scene = entry.value; if (state.searchText != null && state.searchText!.isNotEmpty) { - return scene.name.toLowerCase().contains(state.searchText!.toLowerCase()) + return scene.name + .toLowerCase() + .contains(state.searchText!.toLowerCase()) ? DraggableCard( imagePath: scene.icon ?? Assets.loginLogo, title: scene.name, diff --git a/lib/services/routines_api.dart b/lib/services/routines_api.dart index 756d533e..048b6d35 100644 --- a/lib/services/routines_api.dart +++ b/lib/services/routines_api.dart @@ -69,14 +69,21 @@ class SceneApi { //get scene by unit id - static Future> getScenesByUnitId(String unitId) async { + static Future> getScenesByUnitId( + String unitId, String communityId, + {showInDevice = false}) async { try { final response = await _httpService.get( - path: ApiEndpoints.getSpaceScenes.replaceAll('{unitUuid}', unitId), + path: ApiEndpoints.getUnitScenes + .replaceAll('{spaceUuid}', unitId) + .replaceAll('{communityUuid}', communityId), + queryParameters: {'showInHomePage': showInDevice}, showServerMessage: false, expectedResponseModel: (json) { + final scenesJson = json['data'] as List; + List scenes = []; - for (var scene in json) { + for (var scene in scenesJson) { scenes.add(ScenesModel.fromJson(scene)); } return scenes; @@ -88,6 +95,25 @@ class SceneApi { } } + // static Future> getScenesByUnitId(String unitId) async { + // try { + // final response = await _httpService.get( + // path: ApiEndpoints.getSpaceScenes.replaceAll('{unitUuid}', unitId), + // showServerMessage: false, + // expectedResponseModel: (json) { + // List scenes = []; + // for (var scene in json) { + // scenes.add(ScenesModel.fromJson(scene)); + // } + // return scenes; + // }, + // ); + // return response; + // } catch (e) { + // rethrow; + // } + // } + //getAutomation static Future> getAutomationByUnitId(String unitId) async { diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index 4bc0e752..1cb3be32 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -55,4 +55,6 @@ abstract class ApiEndpoints { static const String getIconScene = '/scene/icon'; static const String createScene = '/scene/tap-to-run'; static const String createAutomation = '/automation'; + static const String getUnitScenes = + '/communities/{communityUuid}/spaces/{spaceUuid}/scenes'; }