diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index d549dd1..099484a 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -31,10 +31,12 @@ class CreateSceneBloc extends Bloc FutureOr _onAddSceneTask( AddTaskEvent event, Emitter emit) { - tasksList = List.from(tempTasksList); - emit(AddSceneTask(tasksList: tasksList)); + final copyList = List.from(tempTasksList); + tasksList.addAll(copyList); tempTasksList.clear(); + selectedValues.clear(); emit(TempHoldSceneTask(tempTasksList: tempTasksList)); + emit(AddSceneTask(tasksList: tasksList)); } FutureOr _onTempHoldSceneTask( @@ -122,7 +124,9 @@ class CreateSceneBloc extends Bloc CreateSceneWithTasksEvent event, Emitter emit) async { emit(CreateSceneLoading()); try { - final response = await SceneApi.createScene(event.createSceneModel); + final response = event.updateScene + ? await SceneApi.updateScene(event.createSceneModel, event.sceneId) + : await SceneApi.createScene(event.createSceneModel); if (response['success'] == true) { tasksList.clear(); tempTasksList.clear(); @@ -131,7 +135,7 @@ class CreateSceneBloc extends Bloc emit(const CreateSceneError(message: 'Something went wrong')); } } catch (e) { - emit(CreateSceneError(message: e.toString())); + emit(const CreateSceneError(message: 'Something went wrong')); emit(AddSceneTask(tasksList: tasksList)); } } @@ -149,14 +153,16 @@ class CreateSceneBloc extends Bloc try { final response = await SceneApi.getSceneDetails(event.sceneId); if (response.id.isNotEmpty) { - tasksList = List.from(getTaskListFunctionsFromApi( + tasksList = List.from(getTaskListFunctionsFromApi( actions: response.actions, deviceId: response.id)); - emit(AddSceneTask(tasksList: tasksList)); + emit(AddSceneTask( + tasksList: tasksList, + )); } else { emit(const CreateSceneError(message: 'Something went wrong')); } } catch (e) { - emit(CreateSceneError(message: e.toString())); + emit(const CreateSceneError(message: 'Something went wrong')); } } diff --git a/lib/features/scene/bloc/create_scene/create_scene_event.dart b/lib/features/scene/bloc/create_scene/create_scene_event.dart index 491a7ae..d1f91e0 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_event.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_event.dart @@ -8,6 +8,8 @@ sealed class CreateSceneEvent extends Equatable { } class AddTaskEvent extends CreateSceneEvent { + final bool updateTaskListFromTemp; + const AddTaskEvent({required this.updateTaskListFromTemp}); @override List get props => []; } @@ -80,7 +82,13 @@ class RemoveFromSelectedValueById extends CreateSceneEvent { class CreateSceneWithTasksEvent extends CreateSceneEvent { final CreateSceneModel createSceneModel; - const CreateSceneWithTasksEvent({required this.createSceneModel}); + final bool updateScene; + final String sceneId; + const CreateSceneWithTasksEvent({ + required this.createSceneModel, + required this.updateScene, + required this.sceneId, + }); @override List get props => [createSceneModel]; diff --git a/lib/features/scene/bloc/scene_bloc/scene_bloc.dart b/lib/features/scene/bloc/scene_bloc/scene_bloc.dart index 5c4091e..8613528 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_bloc.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_bloc.dart @@ -21,7 +21,7 @@ class SceneBloc extends Bloc { final scenes = await SceneApi.getScenesByUnitId(event.unitId); emit(SceneLoaded(scenes)); } catch (e) { - emit(SceneError(message: e.toString())); + emit(const SceneError(message: 'Something went wrong')); } } @@ -40,7 +40,7 @@ class SceneBloc extends Bloc { emit(const SceneError(message: 'Something went wrong')); } } catch (e) { - emit(SceneError(message: e.toString())); + emit(const SceneError(message: 'Something went wrong')); } } } diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 7a06af1..48ca8ed 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -5,6 +5,9 @@ import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.d import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart'; +import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart'; +import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart'; import 'package:syncrow_app/utils/context_extension.dart'; mixin SceneLogicHelper { @@ -17,8 +20,10 @@ mixin SceneLogicHelper { void handleSaveButtonPress( BuildContext context, TextEditingController sceneNameController, - List tasks, - ) { + List tasks, { + required bool updateScene, + required String sceneId, + }) { if (isOnlyDelayOrDelayLast(tasks)) { // Show snackbar indicating restriction context.showCustomSnackbar( @@ -60,11 +65,72 @@ mixin SceneLogicHelper { }, ), ); - context - .read() - .add(CreateSceneWithTasksEvent(createSceneModel: createSceneModel)); + context.read().add(CreateSceneWithTasksEvent( + createSceneModel: createSceneModel, + updateScene: updateScene, + sceneId: sceneId, + )); Navigator.pop(context); } } + + Widget getTheCorrectDialogBody( + SceneStaticFunction taskItem, + List? listOfSceneStaticFunction, + int? index, + // List functionOperation + ) { + bool checkTaskItemAndOperation() { + return taskItem.code == 'temp_set' || taskItem.code == 'countdown'; + } + + bool checkListAndIndex() { + if (listOfSceneStaticFunction == null || index == null) { + return false; + } + return listOfSceneStaticFunction[index].code == 'temp_set' || + listOfSceneStaticFunction[index].code.contains('countdown') || + listOfSceneStaticFunction[index].code.contains('presence_time'); + } + + if (checkTaskItemAndOperation()) { + if (taskItem.code == 'temp_set') { + return AlertDialogTemperatureBody( + index: index!, + functions: listOfSceneStaticFunction ?? [], + functionValue: taskItem.functionValue, + ); + } else if (taskItem.code == 'countdown') { + return AlertDialogCountdown( + durationValue: taskItem.functionValue, + functionValue: taskItem.functionValue, + function: taskItem, + ); + } + } + + if (checkListAndIndex()) { + if (listOfSceneStaticFunction![index!].code == 'temp_set') { + return AlertDialogTemperatureBody( + index: index, + functions: listOfSceneStaticFunction, + functionValue: taskItem.functionValue, + ); + } else { + return AlertDialogCountdown( + durationValue: listOfSceneStaticFunction[index].functionValue ?? + taskItem.functionValue, + functionValue: taskItem.functionValue, + function: listOfSceneStaticFunction[index], + ); + } + } + + return AlertDialogFunctionsOperationsBody( + index: index ?? 0, + functions: listOfSceneStaticFunction ?? [], + functionValue: taskItem.functionValue, + ); + } } diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index 1b541b5..0f0c1e8 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -1266,4 +1266,606 @@ mixin SceneOperationsDataHelper { return functions; } + + List getOperationsForOneFunction({ + required String deviceId, + required SceneStaticFunction taskItem, + }) { + List functions = []; + switch (taskItem.code) { + case 'sensitivity': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsSensitivityFunction, + operationName: 'Sensitivity', + code: 'sensitivity', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 1, + description: 1.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 2, + description: 2.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 3, + description: 3.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 4, + description: 4.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 5, + description: 5.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 6, + description: 6.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 7, + description: 7.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 8, + description: 8.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 9, + description: 9.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 10, + description: 10.toString(), + ), + ], + ), + ); + break; + case 'normal_open_switch': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'WIFI LOCK PRO', + deviceIcon: Assets.assetsIconsDoorLock, + icon: Assets.assetsIconsDoorLock, + operationName: 'Set Door lock Normal Open', + functionValue: taskItem.functionValue, + code: 'normal_open_switch', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + ); + break; + case 'far_detection': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsFarDetection, + operationName: 'Far Detection', + functionValue: taskItem.functionValue, + code: 'far_detection', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 75, + description: '75cm', + iconValue: '75', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 150, + description: '150cm', + iconValue: '150', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 225, + description: '225cm', + iconValue: '225', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 300, + description: '300cm', + iconValue: '300', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 375, + description: '375cm', + iconValue: '375', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 450, + description: '450cm', + iconValue: '450', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 525, + description: '525cm', + iconValue: '525', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 600, + description: '600cm', + iconValue: '600', + ), + ], + ), + ); + break; + case 'motion_sensitivity_value': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsMotionDetection, + operationName: 'Motion Detection Sensitivity', + functionValue: taskItem.functionValue, + code: 'motion_sensitivity_value', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 1, + description: 1.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 2, + description: 2.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 3, + description: 3.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 4, + description: 4.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 5, + description: 5.toString(), + ), + ], + ), + ); + break; + case 'motionless_sensitivity': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsMotionlessDetection, + operationName: 'Motionless Detection Sensitivity', + functionValue: taskItem.functionValue, + code: 'motion_sensitivity_value', + operationalValues: [ + SceneOperationalValue( + iconValue: '1', + icon: Assets.assetsFarDetectionFunction, + value: 1, + description: '1', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 2, + description: '2', + iconValue: '2', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 3, + description: '3', + iconValue: '3', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 4, + description: '4', + iconValue: '4', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 5, + description: '5', + iconValue: '5', + ), + ], + ), + ); + break; + case 'indicator': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsIndicator, + operationName: 'Indicator', + functionValue: taskItem.functionValue, + code: 'indicator', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + ); + break; + case 'presence_time': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsNobodyTime, + operationName: 'Nobody Time', + functionValue: taskItem.functionValue, + code: 'presence_time', + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ), + ); + break; + case 'switch_alarm_sound': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Multi-Mode Gateway Z-W-B', + deviceIcon: Assets.assetsIconsGateway, + icon: Assets.assetsSwitchAlarmSound, + operationName: 'Switch Alarm Sound', + functionValue: taskItem.functionValue, + code: 'switch_alarm_sound', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false), + ], + ), + ); + break; + case 'master_state': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Multi-Mode Gateway Z-W-B', + deviceIcon: Assets.assetsIconsGateway, + icon: Assets.assetsMasterState, + operationName: 'Master State', + functionValue: taskItem.functionValue, + code: 'master_state', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "Alarm", + value: 'alarm', + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "Normal", + value: 'normal', + ), + ], + ), + ); + break; + case 'factory_reset': + functions.add( + SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Multi-Mode Gateway Z-W-B', + deviceIcon: Assets.assetsIconsGateway, + icon: Assets.assetsFactoryReset, + operationName: 'Reset Factory', + functionValue: taskItem.functionValue, + code: 'factory_reset', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSceneRefresh, + description: "ON", + value: true), + SceneOperationalValue( + icon: Assets.assetsResetOff, + description: "OFF", + value: false, + ), + ], + ), + ); + break; + case 'switch_1': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsAcPower, + operationName: 'Light 1 Switch', + code: 'switch_1', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false), + SceneOperationalValue( + icon: Assets.assetsSceneRefresh, + description: "Reverse Switch", + value: true, + ), + ], + )); + break; + case 'switch_2': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsAcPower, + operationName: 'Light 2 Switch', + code: 'switch_2', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false), + SceneOperationalValue( + icon: Assets.assetsSceneRefresh, + description: "Reverse Switch", + value: true, + ), + ], + )); + break; + case 'switch_3': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsAcPower, + operationName: 'Light 3 Switch', + code: 'switch_3', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false), + SceneOperationalValue( + icon: Assets.assetsSceneRefresh, + description: "Reverse Switch", + value: true, + ), + ], + )); + break; + case 'countdown_1': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsLightCountdown, + operationName: 'Light 1 CountDown', + code: 'countdown_1', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + )); + break; + case 'countdown_2': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsLightCountdown, + operationName: 'Light 2 CountDown', + code: 'countdown_2', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + )); + break; + case 'countdown_3': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsLightCountdown, + operationName: 'Light 3 CountDown', + code: 'countdown_3', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + )); + break; + case 'switch': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsAcPower, + operationName: 'Power', + code: 'switch', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + )); + break; + case 'temp_set': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsTempreture, + operationName: 'Set Temperature', + code: 'temp_set', + functionValue: taskItem.functionValue != null + ? ((taskItem.functionValue / 10) as double).toInt() + : null, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsCelsiusDegrees, + value: 0, + description: 'COOL TO', + ), + ], + )); + break; + case 'mode': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsFreezing, + operationName: 'Mode', + code: 'mode', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcCooling, + description: AcValuesEnums.Cooling.name, + value: TempModes.cold.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcHeating, + description: AcValuesEnums.Heating.name, + value: TempModes.hot.name, + ), + SceneOperationalValue( + icon: Assets.assetsFanSpeed, + description: AcValuesEnums.Ventilation.name, + value: TempModes.wind.name, + ), + ], + )); + break; + case 'level': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsFanSpeed, + operationName: 'Fan Speed', + code: 'level', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcFanLow, + description: ValueACRange.LOW.name, + value: FanSpeeds.low.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanMiddle, + description: ValueACRange.MIDDLE.name, + value: FanSpeeds.middle.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanHigh, + description: ValueACRange.HIGH.name, + value: FanSpeeds.high.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanAuto, + description: ValueACRange.AUTO.name, + value: FanSpeeds.auto.name, + ), + ], + )); + break; + case 'child_lock': + functions.add(SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsChildLock, + operationName: 'Child Lock', + code: 'child_lock', + functionValue: taskItem.functionValue, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSceneChildLock, + description: 'Lock', + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsSceneChildUnlock, + description: 'Unlock', + value: false, + ), + ], + )); + break; + default: + } + + return functions; + } } diff --git a/lib/features/scene/model/create_scene_model.dart b/lib/features/scene/model/create_scene_model.dart index 276ebeb..6b2786b 100644 --- a/lib/features/scene/model/create_scene_model.dart +++ b/lib/features/scene/model/create_scene_model.dart @@ -47,9 +47,9 @@ class CreateSceneModel { ); } - Map toMap() { + Map toMap([String? sceneId]) { return { - 'unitUuid': unitUuid, + if (sceneId != null) 'unitUuid': unitUuid, 'sceneName': sceneName, 'decisionExpr': decisionExpr, 'actions': actions.map((x) => x.toMap()).toList(), @@ -66,7 +66,7 @@ class CreateSceneModel { ); } - String toJson() => json.encode(toMap()); + String toJson([String? sceneId]) => json.encode(toMap(sceneId)); factory CreateSceneModel.fromJson(String source) => CreateSceneModel.fromMap(json.decode(source)); diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index c47b361..c43af8a 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -46,7 +46,9 @@ class DeviceFunctionsView extends StatelessWidget actions: [ TextButton( onPressed: () { - context.read().add(AddTaskEvent()); + context + .read() + .add(const AddTaskEvent(updateTaskListFromTemp: true)); Navigator.popUntil(context, (route) { return route.settings.name == Routes.sceneTasksRoute; }); diff --git a/lib/features/scene/view/scene_tasks_view.dart b/lib/features/scene/view/scene_tasks_view.dart index fab4b2c..399ac39 100644 --- a/lib/features/scene/view/scene_tasks_view.dart +++ b/lib/features/scene/view/scene_tasks_view.dart @@ -64,7 +64,10 @@ class SceneTasksView extends StatelessWidget { left: 40, child: SizedBox( width: context.width * 0.8, - child: const CreateSceneSaveButton(), + child: CreateSceneSaveButton( + sceneName: sceneSettings.sceneName, + sceneId: sceneSettings.sceneId, + ), ), ) ], diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index 711c753..9fa1d62 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart'; import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_view.dart'; diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart index 7e5bd94..7af1ec0 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart @@ -31,16 +31,17 @@ class _AlertDialogFunctionsOperationsBodyState final tempTaskList = context.read().tempTasksList; if (tempTaskList.isEmpty) { context.read().add(const ClearTempTaskListEvent()); - } - - for (var element in tempTaskList) { - if (element.code == widget.functions[widget.index].code) { - groupValue = element.functionValue; - } else { - context.read().add(RemoveFromSelectedValueById( - code: widget.functions[widget.index].code)); + } else if (tempTaskList.isNotEmpty) { + for (var element in tempTaskList) { + if (element.code == widget.functions[widget.index].code) { + groupValue = element.functionValue; + } else { + context.read().add(RemoveFromSelectedValueById( + code: widget.functions[widget.index].code)); + } } } + if (widget.functionValue != null) { setState(() { groupValue = widget.functionValue; @@ -49,6 +50,7 @@ class _AlertDialogFunctionsOperationsBodyState } dynamic groupValue; + @override Widget build(BuildContext context) { return SingleChildScrollView( diff --git a/lib/features/scene/widgets/create_scene_save_button.dart b/lib/features/scene/widgets/create_scene_save_button.dart index ab565d1..defcfc3 100644 --- a/lib/features/scene/widgets/create_scene_save_button.dart +++ b/lib/features/scene/widgets/create_scene_save_button.dart @@ -10,7 +10,11 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class CreateSceneSaveButton extends StatefulWidget { const CreateSceneSaveButton({ super.key, + required this.sceneName, + required this.sceneId, }); + final String sceneName; + final String sceneId; @override State createState() => _CreateSceneSaveButtonState(); @@ -22,7 +26,8 @@ class _CreateSceneSaveButtonState extends State @override void initState() { - sceneNameController = TextEditingController(); + sceneNameController = TextEditingController( + text: widget.sceneName.isNotEmpty ? widget.sceneName : ''); super.initState(); } @@ -59,39 +64,58 @@ class _CreateSceneSaveButtonState extends State }, builder: (context, state) { return DefaultButton( - onPressed: () { - context.customAlertDialog( - alertBody: Padding( - padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), - child: SizedBox( - height: 40, - child: SearchBar( - controller: sceneNameController, - elevation: WidgetStateProperty.all(0), - textStyle: WidgetStateProperty.all(context.bodyMedium), - hintStyle: WidgetStateProperty.all( - context.bodyMedium.copyWith( - fontSize: 14, - color: ColorsManager.secondaryTextColor), - ), - hintText: 'Enter scene name', - backgroundColor: - WidgetStateProperty.all(ColorsManager.backgroundColor), - ), - ), - ), - title: 'Scene Name', - onConfirm: () { - if (sceneNameController.text.isNotEmpty) { + onPressed: widget.sceneName.isNotEmpty + ? () { final tasks = context.read().tasksList; - handleSaveButtonPress(context, sceneNameController, tasks); + handleSaveButtonPress( + context, + sceneNameController, + tasks, + updateScene: true, + sceneId: widget.sceneId, + ); } - }, - ); - }, + : () { + context.customAlertDialog( + alertBody: Padding( + padding: + const EdgeInsets.only(left: 8, right: 8, bottom: 8), + child: SizedBox( + height: 40, + child: SearchBar( + controller: sceneNameController, + elevation: WidgetStateProperty.all(0), + textStyle: + WidgetStateProperty.all(context.bodyMedium), + hintStyle: WidgetStateProperty.all( + context.bodyMedium.copyWith( + fontSize: 14, + color: ColorsManager.secondaryTextColor), + ), + hintText: 'Enter scene name', + backgroundColor: WidgetStateProperty.all( + ColorsManager.backgroundColor), + ), + ), + ), + title: 'Scene Name', + onConfirm: () { + if (sceneNameController.text.isNotEmpty) { + final tasks = context.read().tasksList; + handleSaveButtonPress( + context, + sceneNameController, + tasks, + updateScene: false, + sceneId: widget.sceneId, + ); + } + }, + ); + }, customButtonStyle: ButtonStyle( backgroundColor: WidgetStateProperty.all( - ColorsManager.primaryColorWithOpacity, + ColorsManager.primaryColor, ), ), isLoading: state is CreateSceneLoading, diff --git a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart index 81256b4..f5a99cd 100644 --- a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart +++ b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart @@ -4,10 +4,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/helper/scene_logic_helper.dart'; +import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; -import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart'; -import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart'; -import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart'; + import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; @@ -15,16 +15,17 @@ import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; -class ThenAddedTasksContainer extends StatelessWidget { +class ThenAddedTasksContainer extends StatelessWidget + with SceneOperationsDataHelper, SceneLogicHelper { ThenAddedTasksContainer({ super.key, - required this.taskList, + required this.taskItem, this.sceneId, this.index, this.listOfSceneStaticFunction, }); - final SceneStaticFunction taskList; + final SceneStaticFunction taskItem; String? sceneId; List? listOfSceneStaticFunction; int? index; @@ -32,43 +33,31 @@ class ThenAddedTasksContainer extends StatelessWidget { @override Widget build(BuildContext context) { String operationValue = ''; - if (taskList.code.contains('countdown')) { + if (taskItem.code.contains('countdown')) { final functionValue = - taskList.functionValue ?? taskList.operationalValues.first.value; + taskItem.functionValue ?? taskItem.operationalValues.first.value; final duration = Duration(seconds: int.tryParse(functionValue.toString()) ?? 0); operationValue = "${duration.inHours}h ${duration.inMinutes.remainder(60)}m "; } else { final functionValue = - taskList.functionValue ?? taskList.operationalValues.first.value; + taskItem.functionValue ?? taskItem.operationalValues.first.value; operationValue = functionValue.toString(); } return DefaultContainer( - onTap: () { + onTap: () async { + // List functionOperation = []; + // if (sceneId == null) { + // functionOperation = getOperationsForOneFunction( + // taskItem: taskItem, deviceId: taskItem.deviceId); + // } context.customAlertDialog( - alertBody: taskList.code == 'temp_set' - ? AlertDialogTemperatureBody( - index: index!, - functions: listOfSceneStaticFunction ?? [], - functionValue: taskList.functionValue, - ) - : (listOfSceneStaticFunction![index!] - .code - .contains('countdown') || - listOfSceneStaticFunction![index!] - .code - .contains('presence_time')) - ? AlertDialogCountdown( - durationValue: - listOfSceneStaticFunction![index!].functionValue, - functionValue: taskList.functionValue, - function: listOfSceneStaticFunction![index!], - ) - : AlertDialogFunctionsOperationsBody( - index: index!, - functions: listOfSceneStaticFunction ?? [], - functionValue: taskList.functionValue), + alertBody: getTheCorrectDialogBody( + taskItem, + listOfSceneStaticFunction, + index, + ), title: listOfSceneStaticFunction![index!].operationName, onConfirm: () { // final selectedValue = context.read().selectedValue; @@ -89,7 +78,7 @@ class ThenAddedTasksContainer extends StatelessWidget { }, padding: EdgeInsets.zero, child: Dismissible( - key: Key(taskList.uniqueCustomId.toString()), + key: Key(taskItem.uniqueCustomId.toString()), background: Container( padding: const EdgeInsets.only(right: 10), alignment: AlignmentDirectional.centerEnd, @@ -110,14 +99,14 @@ class ThenAddedTasksContainer extends StatelessWidget { ), direction: DismissDirection.endToStart, onDismissed: (direction) { - String removeFunctionById = taskList.uniqueCustomId; + String removeFunctionById = taskItem.uniqueCustomId; context .read() .add(RemoveTaskByIdEvent(taskId: removeFunctionById)); String removeFunction = - "${taskList.operationName} with value ${taskList.operationalValues.first.value}"; + "${taskItem.operationName} with value ${taskItem.operationalValues.first.value}"; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('$removeFunction removed')), @@ -125,10 +114,10 @@ class ThenAddedTasksContainer extends StatelessWidget { }, child: SceneListTile( padding: EdgeInsets.zero, - assetPath: taskList.icon, + assetPath: taskItem.icon, iconsSize: 32, titleWidget: BodyMedium( - text: taskList.deviceName, + text: taskItem.deviceName, style: context.bodyMedium.copyWith( fontWeight: FontWeight.bold, ), @@ -136,7 +125,7 @@ class ThenAddedTasksContainer extends StatelessWidget { subtitleWidget: Row( children: [ BodyMedium( - text: "${taskList.operationName}: ", + text: "${taskItem.operationName}: ", fontColor: ColorsManager.secondaryTextColor, fontWeight: FontWeight.normal, ), diff --git a/lib/features/scene/widgets/if_then_containers/then_container.dart b/lib/features/scene/widgets/if_then_containers/then_container.dart index 5634325..47bc900 100644 --- a/lib/features/scene/widgets/if_then_containers/then_container.dart +++ b/lib/features/scene/widgets/if_then_containers/then_container.dart @@ -50,70 +50,43 @@ class ThenDefaultContainer extends StatelessWidget { padding: EdgeInsets.zero, ), const LightDivider(), - sceneId.isNotEmpty - ? BlocProvider( - create: (context) => CreateSceneBloc() - ..add(FetchSceneTasksEvent(sceneId: sceneId)), - child: BlocBuilder( - builder: (context, state) { - if (state is CreateSceneLoading) { - return const Center(child: LinearProgressIndicator()); - } - if (state is AddSceneTask) { - final taskLists = state.tasksList; - if (taskLists.isNotEmpty) { - return ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: taskLists.length, - itemBuilder: (context, index) { - return ThenAddedTasksContainer( - taskList: taskLists[index], - index: index, - listOfSceneStaticFunction: taskLists, - sceneId: sceneId, - ); - }, - ); - } - return const SizedBox(); - } - return const SizedBox(); - }, - )) - : BlocBuilder( - builder: (context, state) { - if (state is AddSceneTask) { - final taskLists = state.tasksList; - if (taskLists.isNotEmpty) { - return ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: taskLists.length, - itemBuilder: (context, index) { - return ThenAddedTasksContainer( - taskList: taskLists[index], - ); - }, - ); - } - return SceneListTile( - titleString: '+ Add Task', - textAlign: TextAlign.center, - onPressed: () => context.customBottomSheet( - child: const CustomBottomSheetWidget(), - ), + BlocBuilder( + builder: (context, state) { + if (state is CreateSceneLoading) { + return const Center(child: LinearProgressIndicator()); + } + if (state is AddSceneTask) { + final taskLists = state.tasksList; + if (taskLists.isNotEmpty) { + return ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: taskLists.length, + reverse: true, + itemBuilder: (context, index) { + return ThenAddedTasksContainer( + taskItem: taskLists[index], ); - } - return SceneListTile( - titleString: '+ Add Task', - textAlign: TextAlign.center, - onPressed: () => context.customBottomSheet( - child: const CustomBottomSheetWidget(), - ), - ); - }, - ) + }, + ); + } + return SceneListTile( + titleString: '+ Add Task', + textAlign: TextAlign.center, + onPressed: () => context.customBottomSheet( + child: const CustomBottomSheetWidget(), + ), + ); + } + return SceneListTile( + titleString: '+ Add Task', + textAlign: TextAlign.center, + onPressed: () => context.customBottomSheet( + child: const CustomBottomSheetWidget(), + ), + ); + }, + ) ], ), ); 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 e46c5b9..1830475 100644 --- a/lib/features/scene/widgets/scene_view_widget/scene_item.dart +++ b/lib/features/scene/widgets/scene_view_widget/scene_item.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart'; import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; @@ -35,6 +36,8 @@ class SceneItem extends StatelessWidget { sceneName: scene.name, ), ); + BlocProvider.of(context) + .add(FetchSceneTasksEvent(sceneId: scene.id)); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/services/api/api_links_endpoints.dart b/lib/services/api/api_links_endpoints.dart index 3608b9c..147925b 100644 --- a/lib/services/api/api_links_endpoints.dart +++ b/lib/services/api/api_links_endpoints.dart @@ -9,7 +9,8 @@ abstract class ApiEndpoints { static const String deleteUser = '$baseUrl/authentication/user/delete/{id}'; static const String sendOtp = '$baseUrl/authentication/user/send-otp'; static const String verifyOtp = '$baseUrl/authentication/user/verify-otp'; - static const String forgetPassword = '$baseUrl/authentication/user/forget-password'; + static const String forgetPassword = + '$baseUrl/authentication/user/forget-password'; ////////////////////////////////////// Spaces /////////////////////////////////////// @@ -19,10 +20,12 @@ abstract class ApiEndpoints { static const String addCommunityToUser = '$baseUrl/community/user'; //GET static const String communityByUuid = '$baseUrl/community/{communityUuid}'; - static const String communityChild = '$baseUrl/community/child/{communityUuid}'; + static const String communityChild = + '$baseUrl/community/child/{communityUuid}'; static const String communityUser = '$baseUrl/community/user/{userUuid}'; //PUT - static const String renameCommunity = '$baseUrl/community/rename/{communityUuid}'; + static const String renameCommunity = + '$baseUrl/community/rename/{communityUuid}'; ///Building Module //POST @@ -31,10 +34,12 @@ abstract class ApiEndpoints { //GET static const String buildingByUuid = '$baseUrl/building/{buildingUuid}'; static const String buildingChild = '$baseUrl/building/child/{buildingUuid}'; - static const String buildingParent = '$baseUrl/building/parent/{buildingUuid}'; + static const String buildingParent = + '$baseUrl/building/parent/{buildingUuid}'; static const String buildingUser = '$baseUrl/building/user/{userUuid}'; //PUT - static const String renameBuilding = '$baseUrl/building/rename/{buildingUuid}'; + static const String renameBuilding = + '$baseUrl/building/rename/{buildingUuid}'; ///Floor Module //POST @@ -57,7 +62,8 @@ abstract class ApiEndpoints { static const String unitChild = '$baseUrl/unit/child/'; static const String unitParent = '$baseUrl/unit/parent/{unitUuid}'; static const String unitUser = '$baseUrl/unit/user/'; - static const String invitationCode = '$baseUrl/unit/{unitUuid}/invitation-code'; + static const String invitationCode = + '$baseUrl/unit/{unitUuid}/invitation-code'; static const String verifyInvitationCode = '$baseUrl/unit/user/verify-code'; //PUT @@ -80,7 +86,8 @@ abstract class ApiEndpoints { static const String controlGroup = '$baseUrl/group/control'; //GET static const String groupBySpace = '$baseUrl/group/{unitUuid}'; - static const String devicesByGroupName = '$baseUrl/group/{unitUuid}/devices/{groupName}'; + static const String devicesByGroupName = + '$baseUrl/group/{unitUuid}/devices/{groupName}'; static const String groupByUuid = '$baseUrl/group/{groupUuid}'; //DELETE @@ -92,15 +99,19 @@ abstract class ApiEndpoints { static const String addDeviceToRoom = '$baseUrl/device/room'; static const String addDeviceToGroup = '$baseUrl/device/group'; static const String controlDevice = '$baseUrl/device/{deviceUuid}/control'; - static const String firmwareDevice = '$baseUrl/device/{deviceUuid}/firmware/{firmwareVersion}'; + static const String firmwareDevice = + '$baseUrl/device/{deviceUuid}/firmware/{firmwareVersion}'; static const String getDevicesByUserId = '$baseUrl/device/user/{userId}'; //GET static const String deviceByRoom = '$baseUrl/device/room'; static const String deviceByUuid = '$baseUrl/device/{deviceUuid}'; - static const String deviceFunctions = '$baseUrl/device/{deviceUuid}/functions'; - static const String gatewayApi = '$baseUrl/device/gateway/{gatewayUuid}/devices'; - static const String deviceFunctionsStatus = '$baseUrl/device/{deviceUuid}/functions/status'; + static const String deviceFunctions = + '$baseUrl/device/{deviceUuid}/functions'; + static const String gatewayApi = + '$baseUrl/device/gateway/{gatewayUuid}/devices'; + static const String deviceFunctionsStatus = + '$baseUrl/device/{deviceUuid}/functions/status'; ///Device Permission Module //POST @@ -108,14 +119,16 @@ abstract class ApiEndpoints { //GET static const String devicePermissionList = '$baseUrl/device-permission/list'; //PUT - static const String editDevicePermission = '$baseUrl/device-permission/edit/{userId}'; + static const String editDevicePermission = + '$baseUrl/device-permission/edit/{userId}'; static const String assignDeviceToRoom = '$baseUrl/device/room'; /// Scene API //////////////////// /// POST static const String createScene = '$baseUrl/scene/tap-to-run'; - static const String triggerScene = '$baseUrl/scene/tap-to-run/trigger/{sceneId}'; + static const String triggerScene = + '$baseUrl/scene/tap-to-run/trigger/{sceneId}'; /// GET static const String getUnitScenes = '$baseUrl/scene/tap-to-run/{unitUuid}'; @@ -123,10 +136,11 @@ abstract class ApiEndpoints { static const String getScene = '$baseUrl/scene/tap-to-run/details/{sceneId}'; /// PUT - static const String updateScene = '$baseUrl/scene/{sceneId}'; + static const String updateScene = '$baseUrl/scene/tap-to-run/{sceneId}'; /// DELETE - static const String deleteScene = '$baseUrl/scene/tap-to-run/{sceneUuid}/{sceneId}'; + static const String deleteScene = + '$baseUrl/scene/tap-to-run/{sceneUuid}/{sceneId}'; //////////////////////Door Lock ////////////////////// //online diff --git a/lib/services/api/scene_api.dart b/lib/services/api/scene_api.dart index 4015b69..5b1e383 100644 --- a/lib/services/api/scene_api.dart +++ b/lib/services/api/scene_api.dart @@ -71,7 +71,21 @@ class SceneApi { } } - //deleteScene - //updateScene + static updateScene(CreateSceneModel createSceneModel, String sceneId) async { + try { + final response = await _httpService.put( + path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId), + body: createSceneModel.toJson(sceneId), + expectedResponseModel: (json) { + return json; + }, + ); + return response; + } catch (e) { + rethrow; + } + } + + //deleteScene }