mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-14 17:25:47 +00:00
connected all apis , create functionality is working
This commit is contained in:
@ -3,21 +3,24 @@ import 'dart:async';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
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/services/api/scene_api.dart';
|
||||
|
||||
part 'create_scene_event.dart';
|
||||
part 'create_scene_state.dart';
|
||||
|
||||
class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState> {
|
||||
CreateSceneBloc() : super(CreateSceneInitial()) {
|
||||
on<CreateSceneEvent>((event, emit) => null as FutureOr<void>);
|
||||
on<CreateSceneWithTasksEvent>(_createSceneWithTasks);
|
||||
on<AddTaskEvent>(_onAddSceneTask);
|
||||
on<SelectedValueEvent>(_selectedValue);
|
||||
on<RemoveTaskEvent>(_removeTaskById);
|
||||
on<ClearTaskListEvent>(_clearTaskList);
|
||||
}
|
||||
|
||||
List<SceneStaticFunction> tasksList = [];
|
||||
String selectedValue = '';
|
||||
dynamic selectedValue;
|
||||
|
||||
FutureOr<void> _onAddSceneTask(
|
||||
AddTaskEvent event, Emitter<CreateSceneState> emit) {
|
||||
@ -58,4 +61,27 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _createSceneWithTasks(
|
||||
CreateSceneWithTasksEvent event, Emitter<CreateSceneState> emit) async {
|
||||
emit(CreateSceneLoading());
|
||||
try {
|
||||
final response = await SceneApi.createScene(event.createSceneModel);
|
||||
if (response['success'] == true) {
|
||||
tasksList.clear();
|
||||
emit(const CreateSceneWithTasks(success: true));
|
||||
} else {
|
||||
emit(const CreateSceneError(message: 'Something went wrong'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(CreateSceneError(message: e.toString()));
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _clearTaskList(
|
||||
ClearTaskListEvent event, Emitter<CreateSceneState> emit) {
|
||||
tasksList.clear();
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
}
|
||||
}
|
||||
|
@ -28,12 +28,12 @@ class AddTaskEvent extends CreateSceneEvent {
|
||||
}
|
||||
|
||||
class SelectedValueEvent extends CreateSceneEvent {
|
||||
final String value;
|
||||
final dynamic value;
|
||||
|
||||
const SelectedValueEvent({required this.value});
|
||||
const SelectedValueEvent({this.value});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
List<Object> get props => [value!];
|
||||
}
|
||||
|
||||
class RemoveTaskEvent extends CreateSceneEvent {
|
||||
@ -44,3 +44,18 @@ class RemoveTaskEvent extends CreateSceneEvent {
|
||||
@override
|
||||
List<Object> get props => [taskId];
|
||||
}
|
||||
|
||||
class CreateSceneWithTasksEvent extends CreateSceneEvent {
|
||||
final CreateSceneModel createSceneModel;
|
||||
const CreateSceneWithTasksEvent({required this.createSceneModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [createSceneModel];
|
||||
}
|
||||
|
||||
class ClearTaskListEvent extends CreateSceneEvent {
|
||||
const ClearTaskListEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
@ -11,6 +11,14 @@ final class CreateSceneInitial extends CreateSceneState {}
|
||||
|
||||
class CreateSceneLoading extends CreateSceneState {}
|
||||
|
||||
class CreateSceneError extends CreateSceneState {
|
||||
final String message;
|
||||
const CreateSceneError({required this.message});
|
||||
|
||||
@override
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
|
||||
class AddSceneTask extends CreateSceneState {
|
||||
final List<SceneStaticFunction> tasksList;
|
||||
const AddSceneTask({required this.tasksList});
|
||||
@ -20,9 +28,17 @@ class AddSceneTask extends CreateSceneState {
|
||||
}
|
||||
|
||||
class SelectedTaskValueState extends CreateSceneState {
|
||||
final String value;
|
||||
final dynamic value;
|
||||
const SelectedTaskValueState({required this.value});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
class CreateSceneWithTasks extends CreateSceneState {
|
||||
final bool success;
|
||||
const CreateSceneWithTasks({required this.success});
|
||||
|
||||
@override
|
||||
List<Object> get props => [success];
|
||||
}
|
||||
|
@ -1,28 +1,48 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_model.dart';
|
||||
import 'package:syncrow_app/services/api/scene_api.dart';
|
||||
|
||||
part 'scene_state.dart';
|
||||
|
||||
class SceneBloc extends Bloc<SceneEvent, SceneState> {
|
||||
SceneBloc() : super(SceneInitial()) {
|
||||
on<LoadScenes>(_onLoadScenes);
|
||||
on<SceneTrigger>(_sceneTrigger);
|
||||
}
|
||||
|
||||
void _onLoadScenes(LoadScenes event, Emitter<SceneState> emit) {
|
||||
FutureOr<void> _onLoadScenes(
|
||||
LoadScenes event, Emitter<SceneState> emit) async {
|
||||
emit(SceneLoading());
|
||||
|
||||
try {
|
||||
final scenes = _loadScenes();
|
||||
final scenes = await SceneApi.getScenesByUnitId(event.unitId);
|
||||
if (scenes.isNotEmpty) {
|
||||
emit(SceneLoaded(scenes));
|
||||
} catch (_) {
|
||||
emit(SceneError());
|
||||
} else {
|
||||
emit(SceneTriggerError(message: 'Something went wrong'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(SceneError(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
List<SceneModel> _loadScenes() {
|
||||
//TODO: Load scenes
|
||||
return [];
|
||||
FutureOr<void> _sceneTrigger(
|
||||
SceneTrigger event, Emitter<SceneState> emit) async {
|
||||
emit(SceneTriggerLoading());
|
||||
|
||||
try {
|
||||
final success = await SceneApi.triggerScene(event.sceneId);
|
||||
if (success) {
|
||||
emit(SceneTriggerState(success: true));
|
||||
} else {
|
||||
emit(SceneTriggerError(message: 'Something went wrong'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(SceneTriggerError(message: e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class SceneEvent extends Equatable {
|
||||
@ -6,4 +5,20 @@ abstract class SceneEvent extends Equatable {
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class LoadScenes extends SceneEvent {}
|
||||
class LoadScenes extends SceneEvent {
|
||||
final String unitId;
|
||||
|
||||
LoadScenes(this.unitId);
|
||||
|
||||
@override
|
||||
List<Object> get props => [unitId];
|
||||
}
|
||||
|
||||
class SceneTrigger extends SceneEvent {
|
||||
final String sceneId;
|
||||
|
||||
SceneTrigger(this.sceneId);
|
||||
|
||||
@override
|
||||
List<Object> get props => [sceneId];
|
||||
}
|
||||
|
@ -18,4 +18,31 @@ class SceneLoaded extends SceneState {
|
||||
List<Object> get props => [scenes];
|
||||
}
|
||||
|
||||
class SceneError extends SceneState {}
|
||||
class SceneError extends SceneState {
|
||||
final String message;
|
||||
|
||||
SceneError({required this.message});
|
||||
|
||||
@override
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
|
||||
class SceneTriggerState extends SceneState {
|
||||
final bool success;
|
||||
|
||||
SceneTriggerState({required this.success});
|
||||
|
||||
@override
|
||||
List<Object> get props => [success];
|
||||
}
|
||||
|
||||
class SceneTriggerLoading extends SceneState {}
|
||||
|
||||
class SceneTriggerError extends SceneState {
|
||||
final String message;
|
||||
|
||||
SceneTriggerError({required this.message});
|
||||
|
||||
@override
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
|
69
lib/features/scene/helper/scene_logic_helper.dart
Normal file
69
lib/features/scene/helper/scene_logic_helper.dart
Normal file
@ -0,0 +1,69 @@
|
||||
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/model/create_scene_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
|
||||
mixin SceneLogicHelper {
|
||||
bool isOnlyDelayOrDelayLast(List<SceneStaticFunction> tasks) {
|
||||
final lastTask = tasks.last;
|
||||
return tasks.every((task) => task.code == 'delay') ||
|
||||
lastTask.code == 'delay';
|
||||
}
|
||||
|
||||
void handleSaveButtonPress(
|
||||
BuildContext context,
|
||||
TextEditingController sceneNameController,
|
||||
List<SceneStaticFunction> tasks,
|
||||
) {
|
||||
if (isOnlyDelayOrDelayLast(tasks)) {
|
||||
// Show snackbar indicating restriction
|
||||
context.showCustomSnackbar(
|
||||
message: 'Only a single delay or delay-last operations are allowed.',
|
||||
icon: const Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final createSceneModel = CreateSceneModel(
|
||||
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
||||
sceneName: sceneNameController.text,
|
||||
decisionExpr: 'and',
|
||||
actions: List.generate(
|
||||
tasks.length,
|
||||
(index) {
|
||||
final task = tasks[index];
|
||||
if (task.code == 'delay') {
|
||||
return CreateSceneAction(
|
||||
entityId: tasks[index].deviceId,
|
||||
actionExecutor: 'delay',
|
||||
executorProperty: CreateSceneExecutorProperty(
|
||||
functionCode: task.code,
|
||||
functionValue: task.operationalValues.first.value,
|
||||
delaySeconds: 0,
|
||||
),
|
||||
);
|
||||
}
|
||||
return CreateSceneAction(
|
||||
entityId: task.deviceId,
|
||||
actionExecutor: 'device_issue',
|
||||
executorProperty: CreateSceneExecutorProperty(
|
||||
functionCode: task.code,
|
||||
functionValue: task.operationalValues.first.value,
|
||||
delaySeconds: 0,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(CreateSceneWithTasksEvent(createSceneModel: createSceneModel));
|
||||
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
mixin SceneHelper {
|
||||
mixin SceneOperationsDataHelper {
|
||||
List<SceneStaticFunction> getFunctionsWithIcons({
|
||||
DeviceType? type,
|
||||
required List<FunctionModel> functions,
|
||||
@ -79,25 +79,25 @@ mixin SceneHelper {
|
||||
code: 'sensitivity',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "1"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 1),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "2"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 2),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "3"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 3),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "4"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 4),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "5"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 5),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "6"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 6),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "7"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 7),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "8"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 8),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "9"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 9),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: "10"),
|
||||
icon: Assets.assetsSensitivityOperationIcon, value: 10),
|
||||
],
|
||||
),
|
||||
];
|
||||
@ -151,10 +151,15 @@ List<SceneStaticFunction> threeGangFunctions(
|
||||
operationName: 'Light 1 Switch',
|
||||
code: 'switch_1',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: Assets.assetsAcPower, value: "ON"),
|
||||
SceneOperationalValue(icon: Assets.assetsAcPowerOFF, value: "OFF"),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneRefresh, value: "Reverse Switch"),
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneRefresh,
|
||||
description: "Reverse Switch",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
@ -164,10 +169,15 @@ List<SceneStaticFunction> threeGangFunctions(
|
||||
operationName: 'Light 2 Switch',
|
||||
code: 'switch_2',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: Assets.assetsAcPower, value: "ON"),
|
||||
SceneOperationalValue(icon: Assets.assetsAcPowerOFF, value: "OFF"),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneRefresh, value: "Reverse Switch"),
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneRefresh,
|
||||
description: "Reverse Switch",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
@ -177,10 +187,15 @@ List<SceneStaticFunction> threeGangFunctions(
|
||||
operationName: 'Light 3 Switch',
|
||||
code: 'switch_3',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: Assets.assetsAcPower, value: "ON"),
|
||||
SceneOperationalValue(icon: Assets.assetsAcPowerOFF, value: "OFF"),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneRefresh, value: "Reverse Switch"),
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneRefresh,
|
||||
description: "Reverse Switch",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
@ -190,7 +205,7 @@ List<SceneStaticFunction> threeGangFunctions(
|
||||
operationName: 'Light 1 CountDown',
|
||||
code: 'countdown_1',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: '', value: "0"),
|
||||
SceneOperationalValue(icon: '', value: 0),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
@ -200,7 +215,7 @@ List<SceneStaticFunction> threeGangFunctions(
|
||||
operationName: 'Light 2 CountDown',
|
||||
code: 'countdown_1',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: '', value: "0"),
|
||||
SceneOperationalValue(icon: '', value: 0),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
@ -210,7 +225,7 @@ List<SceneStaticFunction> threeGangFunctions(
|
||||
operationName: 'Light 3 CountDown',
|
||||
code: 'countdown_1',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: '', value: "0"),
|
||||
SceneOperationalValue(icon: '', value: 0),
|
||||
],
|
||||
),
|
||||
];
|
||||
@ -229,8 +244,16 @@ List<SceneStaticFunction> acFunctions(
|
||||
operationName: 'Power',
|
||||
code: 'switch',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: Assets.assetsAcPower, value: "ON"),
|
||||
SceneOperationalValue(icon: Assets.assetsAcPowerOFF, value: "OFF"),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower,
|
||||
description: "ON",
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF,
|
||||
description: "OFF",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
@ -242,15 +265,18 @@ List<SceneStaticFunction> acFunctions(
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcCooling,
|
||||
value: AcValuesEnums.Cooling.name,
|
||||
description: AcValuesEnums.Cooling.name,
|
||||
value: TempModes.cold.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcHeating,
|
||||
value: AcValuesEnums.Heating.name,
|
||||
description: AcValuesEnums.Heating.name,
|
||||
value: TempModes.hot.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFanSpeed,
|
||||
value: AcValuesEnums.Ventilation.name,
|
||||
description: AcValuesEnums.Ventilation.name,
|
||||
value: TempModes.wind.name,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -262,7 +288,10 @@ List<SceneStaticFunction> acFunctions(
|
||||
code: 'temp_set',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsCelsiusDegrees, value: "COOL TO"),
|
||||
icon: Assets.assetsCelsiusDegrees,
|
||||
value: 0,
|
||||
description: 'COOL TO',
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
@ -274,19 +303,23 @@ List<SceneStaticFunction> acFunctions(
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanLow,
|
||||
value: ValueACRange.LOW.name,
|
||||
description: ValueACRange.LOW.name,
|
||||
value: FanSpeeds.low.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanMiddle,
|
||||
value: ValueACRange.MIDDLE.name,
|
||||
description: ValueACRange.MIDDLE.name,
|
||||
value: FanSpeeds.middle.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanHigh,
|
||||
value: ValueACRange.HIGH.name,
|
||||
description: ValueACRange.HIGH.name,
|
||||
value: FanSpeeds.high.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanAuto,
|
||||
value: ValueACRange.AUTO.name,
|
||||
description: ValueACRange.AUTO.name,
|
||||
value: FanSpeeds.auto.name,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -299,11 +332,13 @@ List<SceneStaticFunction> acFunctions(
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneChildLock,
|
||||
value: 'Lock',
|
||||
description: 'Lock',
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneChildUnlock,
|
||||
value: 'Unlock',
|
||||
description: 'Unlock',
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
222
lib/features/scene/model/create_scene_model.dart
Normal file
222
lib/features/scene/model/create_scene_model.dart
Normal file
@ -0,0 +1,222 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class CreateSceneModel {
|
||||
/*
|
||||
{
|
||||
"unitUuid": "string",
|
||||
"sceneName": "string",
|
||||
"decisionExpr": "string",
|
||||
"actions": [
|
||||
{
|
||||
"entityId": "string",
|
||||
"actionExecutor": "string",
|
||||
"executorProperty": {
|
||||
"functionCode": "string",
|
||||
"functionValue": {},
|
||||
"delaySeconds": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
String unitUuid;
|
||||
String sceneName;
|
||||
String decisionExpr;
|
||||
List<CreateSceneAction> actions;
|
||||
CreateSceneModel({
|
||||
required this.unitUuid,
|
||||
required this.sceneName,
|
||||
required this.decisionExpr,
|
||||
required this.actions,
|
||||
});
|
||||
|
||||
CreateSceneModel copyWith({
|
||||
String? unitUuid,
|
||||
String? sceneName,
|
||||
String? decisionExpr,
|
||||
List<CreateSceneAction>? actions,
|
||||
}) {
|
||||
return CreateSceneModel(
|
||||
unitUuid: unitUuid ?? this.unitUuid,
|
||||
sceneName: sceneName ?? this.sceneName,
|
||||
decisionExpr: decisionExpr ?? this.decisionExpr,
|
||||
actions: actions ?? this.actions,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'unitUuid': unitUuid,
|
||||
'sceneName': sceneName,
|
||||
'decisionExpr': decisionExpr,
|
||||
'actions': actions.map((x) => x.toMap()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
factory CreateSceneModel.fromMap(Map<String, dynamic> map) {
|
||||
return CreateSceneModel(
|
||||
unitUuid: map['unitUuid'] ?? '',
|
||||
sceneName: map['sceneName'] ?? '',
|
||||
decisionExpr: map['decisionExpr'] ?? '',
|
||||
actions: List<CreateSceneAction>.from(
|
||||
map['actions']?.map((x) => CreateSceneAction.fromMap(x))),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory CreateSceneModel.fromJson(String source) =>
|
||||
CreateSceneModel.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CreateSceneModel(unitUuid: $unitUuid, sceneName: $sceneName, decisionExpr: $decisionExpr, actions: $actions)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is CreateSceneModel &&
|
||||
other.unitUuid == unitUuid &&
|
||||
other.sceneName == sceneName &&
|
||||
other.decisionExpr == decisionExpr &&
|
||||
listEquals(other.actions, actions);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return unitUuid.hashCode ^
|
||||
sceneName.hashCode ^
|
||||
decisionExpr.hashCode ^
|
||||
actions.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
class CreateSceneAction {
|
||||
String entityId;
|
||||
String actionExecutor;
|
||||
CreateSceneExecutorProperty executorProperty;
|
||||
CreateSceneAction({
|
||||
required this.entityId,
|
||||
required this.actionExecutor,
|
||||
required this.executorProperty,
|
||||
});
|
||||
|
||||
CreateSceneAction copyWith({
|
||||
String? entityId,
|
||||
String? actionExecutor,
|
||||
CreateSceneExecutorProperty? executorProperty,
|
||||
}) {
|
||||
return CreateSceneAction(
|
||||
entityId: entityId ?? this.entityId,
|
||||
actionExecutor: actionExecutor ?? this.actionExecutor,
|
||||
executorProperty: executorProperty ?? this.executorProperty,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'entityId': entityId,
|
||||
'actionExecutor': actionExecutor,
|
||||
'executorProperty': executorProperty.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
factory CreateSceneAction.fromMap(Map<String, dynamic> map) {
|
||||
return CreateSceneAction(
|
||||
entityId: map['entityId'] ?? '',
|
||||
actionExecutor: map['actionExecutor'] ?? '',
|
||||
executorProperty:
|
||||
CreateSceneExecutorProperty.fromMap(map['executorProperty']),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory CreateSceneAction.fromJson(String source) =>
|
||||
CreateSceneAction.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'CreateSceneAction(entityId: $entityId, actionExecutor: $actionExecutor, executorProperty: $executorProperty)';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is CreateSceneAction &&
|
||||
other.entityId == entityId &&
|
||||
other.actionExecutor == actionExecutor &&
|
||||
other.executorProperty == executorProperty;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
entityId.hashCode ^ actionExecutor.hashCode ^ executorProperty.hashCode;
|
||||
}
|
||||
|
||||
class CreateSceneExecutorProperty {
|
||||
String functionCode;
|
||||
dynamic functionValue;
|
||||
int delaySeconds;
|
||||
CreateSceneExecutorProperty({
|
||||
required this.functionCode,
|
||||
required this.functionValue,
|
||||
required this.delaySeconds,
|
||||
});
|
||||
|
||||
CreateSceneExecutorProperty copyWith({
|
||||
String? functionCode,
|
||||
dynamic functionValue,
|
||||
int? delaySeconds,
|
||||
}) {
|
||||
return CreateSceneExecutorProperty(
|
||||
functionCode: functionCode ?? this.functionCode,
|
||||
functionValue: functionValue ?? this.functionValue,
|
||||
delaySeconds: delaySeconds ?? this.delaySeconds,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'functionCode': functionCode,
|
||||
'functionValue': functionValue,
|
||||
'delaySeconds': delaySeconds,
|
||||
};
|
||||
}
|
||||
|
||||
factory CreateSceneExecutorProperty.fromMap(Map<String, dynamic> map) {
|
||||
return CreateSceneExecutorProperty(
|
||||
functionCode: map['functionCode'] ?? '',
|
||||
functionValue: map['functionValue'] ?? '',
|
||||
delaySeconds: map['delaySeconds']?.toInt() ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory CreateSceneExecutorProperty.fromJson(String source) =>
|
||||
CreateSceneExecutorProperty.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'CreateSceneExecutorProperty(functionCode: $functionCode, functionValue: $functionValue, delaySeconds: $delaySeconds)';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is CreateSceneExecutorProperty &&
|
||||
other.functionCode == functionCode &&
|
||||
other.functionValue == functionValue &&
|
||||
other.delaySeconds == delaySeconds;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
functionCode.hashCode ^ functionValue.hashCode ^ delaySeconds.hashCode;
|
||||
}
|
@ -1,46 +1,54 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class SceneModel {
|
||||
final String id;
|
||||
final String name;
|
||||
final String description;
|
||||
final String imageUrl;
|
||||
final String location;
|
||||
final String type;
|
||||
final String rating;
|
||||
final String price;
|
||||
final String duration;
|
||||
final String date;
|
||||
final String time;
|
||||
final String status;
|
||||
final Status status;
|
||||
final Type type;
|
||||
|
||||
SceneModel({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.imageUrl,
|
||||
required this.location,
|
||||
required this.type,
|
||||
required this.rating,
|
||||
required this.price,
|
||||
required this.duration,
|
||||
required this.date,
|
||||
required this.time,
|
||||
required this.status,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
factory SceneModel.fromJson(Map<String, dynamic> json) {
|
||||
return SceneModel(
|
||||
id: json['id'],
|
||||
name: json['name'],
|
||||
description: json['description'],
|
||||
imageUrl: json['imageUrl'],
|
||||
location: json['location'],
|
||||
type: json['type'],
|
||||
rating: json['rating'],
|
||||
price: json['price'],
|
||||
duration: json['duration'],
|
||||
date: json['date'],
|
||||
time: json['time'],
|
||||
status: json['status'],
|
||||
factory SceneModel.fromRawJson(String str) =>
|
||||
SceneModel.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory SceneModel.fromJson(Map<String, dynamic> json) => SceneModel(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
status: statusValues.map[json["status"]]!,
|
||||
type: typeValues.map[json["type"]]!,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"status": statusValues.reverse[status],
|
||||
"type": typeValues.reverse[type],
|
||||
};
|
||||
}
|
||||
|
||||
enum Status { ENABLE }
|
||||
|
||||
final statusValues = EnumValues({"enable": Status.ENABLE});
|
||||
|
||||
enum Type { TAP_TO_RUN }
|
||||
|
||||
final typeValues = EnumValues({"tap_to_run": Type.TAP_TO_RUN});
|
||||
|
||||
class EnumValues<T> {
|
||||
Map<String, T> map;
|
||||
late Map<T, String> reverseMap;
|
||||
|
||||
EnumValues(this.map);
|
||||
|
||||
Map<T, String> get reverse {
|
||||
reverseMap = map.map((k, v) => MapEntry(v, k));
|
||||
return reverseMap;
|
||||
}
|
||||
}
|
||||
|
@ -99,34 +99,36 @@ class SceneStaticFunction {
|
||||
|
||||
class SceneOperationalValue {
|
||||
final String icon;
|
||||
final String value;
|
||||
final dynamic value;
|
||||
final String? description;
|
||||
|
||||
SceneOperationalValue({
|
||||
required this.icon,
|
||||
required this.value,
|
||||
this.description,
|
||||
});
|
||||
|
||||
SceneOperationalValue copyWith({
|
||||
String? icon,
|
||||
String? value,
|
||||
dynamic value,
|
||||
String? description,
|
||||
}) {
|
||||
return SceneOperationalValue(
|
||||
icon: icon ?? this.icon,
|
||||
value: value ?? this.value,
|
||||
description: description ?? this.description,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'icon': icon,
|
||||
'value': value,
|
||||
};
|
||||
return {'icon': icon, 'value': value, 'description': description};
|
||||
}
|
||||
|
||||
factory SceneOperationalValue.fromMap(Map<String, dynamic> map) {
|
||||
return SceneOperationalValue(
|
||||
icon: map['icon'] ?? '',
|
||||
value: map['value'] ?? '',
|
||||
value: map['value'],
|
||||
description: map['description'],
|
||||
);
|
||||
}
|
||||
|
||||
@ -137,7 +139,7 @@ class SceneOperationalValue {
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'StaticFunctionOperationHelper(icon: $icon, value: $value)';
|
||||
'StaticFunctionOperationHelper(icon: $icon, value: $value, description: $description)';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
@ -145,9 +147,10 @@ class SceneOperationalValue {
|
||||
|
||||
return other is SceneOperationalValue &&
|
||||
other.icon == icon &&
|
||||
other.description == description &&
|
||||
other.value == value;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => icon.hashCode ^ value.hashCode;
|
||||
int get hashCode => icon.hashCode ^ value.hashCode ^ description.hashCode;
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
|
||||
class SceneRepo {
|
||||
Future<bool> deviceControl({
|
||||
required DeviceControlModel controlModel,
|
||||
required String deviceId,
|
||||
}) async {
|
||||
final response = await DevicesAPI.controlDevice(controlModel, deviceId);
|
||||
if (response['success'] == true) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,7 @@ class CreateSceneView extends StatelessWidget {
|
||||
Routes.sceneTasksRoute,
|
||||
arguments: CreateSceneEnum.tabToRun,
|
||||
);
|
||||
context.read<CreateSceneBloc>().tasksList.clear();
|
||||
context.read<CreateSceneBloc>().add(ClearTaskListEvent());
|
||||
},
|
||||
),
|
||||
DefaultContainer(
|
||||
@ -53,3 +53,5 @@ class CreateSceneView extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,11 +3,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/helper/scene_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_dialog_countdown.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/alert_dialog_functions_body.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/alert_dialog_temperature_body.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/default_scaffold.dart';
|
||||
@ -18,12 +18,13 @@ import 'package:syncrow_app/utils/context_extension.dart';
|
||||
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class DeviceFunctionsView extends StatelessWidget with SceneHelper {
|
||||
class DeviceFunctionsView extends StatelessWidget
|
||||
with SceneOperationsDataHelper {
|
||||
const DeviceFunctionsView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
/// this whole widget i need to revamp it later
|
||||
/// this whole widget needs a refactor later
|
||||
///
|
||||
/// static functions based on type
|
||||
final device = ModalRoute.of(context)?.settings.arguments as DeviceModel;
|
||||
|
@ -1,10 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/create_scene_save_button.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/if_then_containers/if_container.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
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';
|
||||
@ -60,18 +59,7 @@ class SceneTasksView extends StatelessWidget {
|
||||
left: 40,
|
||||
child: SizedBox(
|
||||
width: context.width * 0.8,
|
||||
child: DefaultButton(
|
||||
onPressed: () {},
|
||||
customButtonStyle: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all<Color>(
|
||||
ColorsManager.primaryColorWithOpacity,
|
||||
),
|
||||
),
|
||||
child: BodyLarge(
|
||||
text: 'Save',
|
||||
style: context.bodyLarge.copyWith(color: Colors.white),
|
||||
),
|
||||
),
|
||||
child: const CreateSceneSaveButton(),
|
||||
),
|
||||
)
|
||||
],
|
||||
|
@ -48,8 +48,10 @@ class SceneView extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Image.asset(
|
||||
height: 50,
|
||||
@ -85,8 +87,10 @@ class SceneView extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Image.asset(
|
||||
height: 50,
|
||||
|
@ -6,7 +6,7 @@ import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.d
|
||||
class AlertDialogCountdown extends StatefulWidget {
|
||||
const AlertDialogCountdown({super.key, required this.durationValue});
|
||||
|
||||
final String durationValue;
|
||||
final int durationValue;
|
||||
|
||||
@override
|
||||
State<AlertDialogCountdown> createState() => _AlertDialogCountdownState();
|
||||
@ -16,7 +16,7 @@ class _AlertDialogCountdownState extends State<AlertDialogCountdown> {
|
||||
int durationInSeconds = 0;
|
||||
// Convert seconds to Duration.
|
||||
Duration get duration =>
|
||||
Duration(seconds: int.tryParse(widget.durationValue) ?? 0);
|
||||
Duration(seconds: widget.durationValue) ;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
@ -32,7 +32,7 @@ class _AlertDialogCountdownState extends State<AlertDialogCountdown> {
|
||||
});
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(SelectedValueEvent(value: newDuration.inSeconds.toString()));
|
||||
.add(SelectedValueEvent(value: newDuration.inSeconds));
|
||||
},
|
||||
),
|
||||
);
|
@ -21,7 +21,7 @@ class AlertDialogFunctionsOperationsBody extends StatefulWidget {
|
||||
|
||||
class _AlertDialogFunctionsOperationsBodyState
|
||||
extends State<AlertDialogFunctionsOperationsBody> {
|
||||
String? groupValue = "";
|
||||
dynamic groupValue;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
@ -36,7 +36,7 @@ class _AlertDialogFunctionsOperationsBodyState
|
||||
minLeadingWidth: 15,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
assetPath: operation.icon,
|
||||
titleString: operation.value,
|
||||
titleString: operation.description.toString(),
|
||||
textAlign: TextAlign.start,
|
||||
trailingWidget: Radio(
|
||||
value: operation.value,
|
||||
@ -58,7 +58,7 @@ class _AlertDialogFunctionsOperationsBodyState
|
||||
});
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(SelectedValueEvent(value: groupValue!));
|
||||
.add(SelectedValueEvent(value: groupValue));
|
||||
},
|
||||
);
|
||||
},
|
@ -40,7 +40,7 @@ class _AlertDialogTemperatureBodyState
|
||||
});
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(SelectedValueEvent(value: temperature.toString()));
|
||||
.add(SelectedValueEvent(value: temperature * 10));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.remove,
|
||||
@ -70,7 +70,8 @@ class _AlertDialogTemperatureBodyState
|
||||
],
|
||||
),
|
||||
subtitle: BodyLarge(
|
||||
text: widget.functions[widget.index].operationalValues[0].value,
|
||||
text: widget.functions[widget.index].operationalValues[0].description
|
||||
.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
trailing: IconButton(
|
||||
@ -82,7 +83,7 @@ class _AlertDialogTemperatureBodyState
|
||||
});
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(SelectedValueEvent(value: temperature.toString()));
|
||||
.add(SelectedValueEvent(value: temperature * 10));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.add,
|
106
lib/features/scene/widgets/create_scene_save_button.dart
Normal file
106
lib/features/scene/widgets/create_scene_save_button.dart
Normal file
@ -0,0 +1,106 @@
|
||||
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/helper/scene_logic_helper.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class CreateSceneSaveButton extends StatefulWidget {
|
||||
const CreateSceneSaveButton({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<CreateSceneSaveButton> createState() => _CreateSceneSaveButtonState();
|
||||
}
|
||||
|
||||
class _CreateSceneSaveButtonState extends State<CreateSceneSaveButton>
|
||||
with SceneLogicHelper {
|
||||
late TextEditingController sceneNameController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
sceneNameController = TextEditingController();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
sceneNameController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocConsumer<CreateSceneBloc, CreateSceneState>(
|
||||
listener: (context, state) {
|
||||
if (state is CreateSceneWithTasks) {
|
||||
if (state.success == true) {
|
||||
context.showCustomSnackbar(
|
||||
message: 'Scene created successfully',
|
||||
icon: const Icon(
|
||||
Icons.check,
|
||||
color: Colors.green,
|
||||
),
|
||||
);
|
||||
sceneNameController.text = '';
|
||||
}
|
||||
} else if (state is CreateSceneError) {
|
||||
context.showCustomSnackbar(
|
||||
message: state.message,
|
||||
icon: const Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
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) {
|
||||
final tasks = context.read<CreateSceneBloc>().tasksList;
|
||||
handleSaveButtonPress(context, sceneNameController, tasks);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
customButtonStyle: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all<Color>(
|
||||
ColorsManager.primaryColorWithOpacity,
|
||||
),
|
||||
),
|
||||
isLoading: state is CreateSceneLoading,
|
||||
child: BodyLarge(
|
||||
text: 'Save',
|
||||
style: context.bodyLarge.copyWith(color: Colors.white),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -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
|
||||
@ -95,8 +101,10 @@ abstract class ApiEndpoints {
|
||||
//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 deviceFunctionsStatus = '$baseUrl/device/{deviceUuid}/functions/status';
|
||||
static const String deviceFunctions =
|
||||
'$baseUrl/device/{deviceUuid}/functions';
|
||||
static const String deviceFunctionsStatus =
|
||||
'$baseUrl/device/{deviceUuid}/functions/status';
|
||||
|
||||
///Device Permission Module
|
||||
//POST
|
||||
@ -104,7 +112,26 @@ 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}';
|
||||
|
||||
/// GET
|
||||
static const String getUnitScenes = '$baseUrl/scene/tap-to-run/{unitUuid}';
|
||||
|
||||
static const String getScene = '$baseUrl/scene/tap-to-run/details/{sceneId}';
|
||||
|
||||
/// PUT
|
||||
static const String updateScene = '$baseUrl/scene/{sceneId}';
|
||||
|
||||
/// DELETE
|
||||
static const String deleteScene =
|
||||
'$baseUrl/scene/tap-to-run/{sceneUuid}/{sceneId}';
|
||||
}
|
||||
|
57
lib/services/api/scene_api.dart
Normal file
57
lib/services/api/scene_api.dart
Normal file
@ -0,0 +1,57 @@
|
||||
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_model.dart';
|
||||
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
|
||||
import 'package:syncrow_app/services/api/http_service.dart';
|
||||
|
||||
class SceneApi {
|
||||
static final HTTPService _httpService = HTTPService();
|
||||
|
||||
static Future<Map<String, dynamic>> createScene(
|
||||
CreateSceneModel createSceneModel) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.createScene,
|
||||
body: createSceneModel.toJson(),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<List<SceneModel>> getScenesByUnitId(String unitId) async {
|
||||
try {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getUnitScenes.replaceAll('{unitUuid}', unitId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
List<SceneModel> scenes = [];
|
||||
for (var scene in json) {
|
||||
scenes.add(SceneModel.fromJson(scene));
|
||||
}
|
||||
return scenes;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool> triggerScene(String sceneId) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.triggerScene.replaceAll('{sceneUuid}', sceneId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => json['success'],
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
@ -47,6 +47,19 @@ extension ContextExtension on BuildContext {
|
||||
);
|
||||
}
|
||||
|
||||
void showCustomSnackbar({required String message, Widget? icon}) {
|
||||
ScaffoldMessenger.of(this).showSnackBar(
|
||||
SnackBar(
|
||||
content: Row(
|
||||
children: [
|
||||
Expanded(child: Text(message)),
|
||||
icon ?? const SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void customAlertDialog(
|
||||
{required Widget alertBody,
|
||||
required String title,
|
||||
|
Reference in New Issue
Block a user