fix image on tab to run, and add delete for automation and scene

This commit is contained in:
ashrafzarkanisala
2024-11-28 10:43:35 +03:00
parent 1c54011ed4
commit 57dec8af08
6 changed files with 302 additions and 146 deletions

View File

@ -9,8 +9,6 @@ import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/models/routine_details_model.dart';
import 'package:syncrow_web/pages/routiens/models/routine_model.dart';
import 'package:syncrow_web/services/routines_api.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:uuid/uuid.dart';
part 'routine_event.dart';
part 'routine_state.dart';
@ -36,7 +34,9 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
on<ResetRoutineState>(_onResetRoutineState);
on<GetSceneDetails>(_onGetSceneDetails);
on<GetAutomationDetails>(_onGetAutomationDetails);
on<InitializeRoutineState>(_onInitializeRoutineState);
// on<InitializeRoutineState>(_onInitializeRoutineState);
on<DeleteScene>(_deleteScene);
on<DeleteAutomation>(_deleteAutomation);
// on<RemoveFunction>(_onRemoveFunction);
// on<ClearFunctions>(_onClearFunctions);
}
@ -45,8 +45,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems);
// Find the index of the item in teh current itemsList
int index =
updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
int index = updatedIfItems.indexWhere(
(map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
// Replace the map if the index is valid
if (index != -1) {
updatedIfItems[index] = event.item;
@ -55,18 +55,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}
if (event.isTabToRun) {
emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
emit(state.copyWith(
ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
} else {
emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: false, isAutomation: true));
emit(state.copyWith(
ifItems: updatedIfItems, isTabToRun: false, isAutomation: true));
}
}
void _onAddToThenContainer(AddToThenContainer event, Emitter<RoutineState> emit) {
void _onAddToThenContainer(
AddToThenContainer event, Emitter<RoutineState> emit) {
final currentItems = List<Map<String, dynamic>>.from(state.thenItems);
// Find the index of the item in teh current itemsList
int index =
currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
int index = currentItems.indexWhere(
(map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
// Replace the map if the index is valid
if (index != -1) {
currentItems[index] = event.item;
@ -77,22 +80,26 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
emit(state.copyWith(thenItems: currentItems));
}
void _onAddFunctionsToRoutine(AddFunctionToRoutine event, Emitter<RoutineState> emit) {
void _onAddFunctionsToRoutine(
AddFunctionToRoutine event, Emitter<RoutineState> emit) {
try {
if (event.functions.isEmpty) return;
List<DeviceFunctionData> selectedFunction = List<DeviceFunctionData>.from(event.functions);
List<DeviceFunctionData> selectedFunction =
List<DeviceFunctionData>.from(event.functions);
Map<String, List<DeviceFunctionData>> currentSelectedFunctions =
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
List<DeviceFunctionData> currentFunctions =
List<DeviceFunctionData>.from(currentSelectedFunctions[event.uniqueCustomId] ?? []);
List<DeviceFunctionData>.from(
currentSelectedFunctions[event.uniqueCustomId] ?? []);
List<String> functionCode = [];
for (int i = 0; i < selectedFunction.length; i++) {
for (int j = 0; j < currentFunctions.length; j++) {
if (selectedFunction[i].functionCode == currentFunctions[j].functionCode) {
if (selectedFunction[i].functionCode ==
currentFunctions[j].functionCode) {
currentFunctions[j] = selectedFunction[i];
if (!functionCode.contains(currentFunctions[j].functionCode)) {
functionCode.add(currentFunctions[j].functionCode);
@ -102,13 +109,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}
for (int i = 0; i < functionCode.length; i++) {
selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]);
selectedFunction
.removeWhere((code) => code.functionCode == functionCode[i]);
}
currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions)
..addAll(selectedFunction);
currentSelectedFunctions[event.uniqueCustomId] =
List.from(currentFunctions)..addAll(selectedFunction);
} else {
currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions);
currentSelectedFunctions[event.uniqueCustomId] =
List.from(event.functions);
}
emit(state.copyWith(selectedFunctions: currentSelectedFunctions));
@ -117,11 +126,13 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}
}
Future<void> _onLoadScenes(LoadScenes event, Emitter<RoutineState> emit) async {
Future<void> _onLoadScenes(
LoadScenes event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null));
try {
final scenes = await SceneApi.getScenesByUnitId(event.unitId, event.communityId);
final scenes =
await SceneApi.getScenesByUnitId(event.unitId, event.communityId);
emit(state.copyWith(
scenes: scenes,
isLoading: false,
@ -136,7 +147,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}
}
Future<void> _onLoadAutomation(LoadAutomation event, Emitter<RoutineState> emit) async {
Future<void> _onLoadAutomation(
LoadAutomation event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null));
try {
@ -164,14 +176,16 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}
}
FutureOr<void> _onSearchRoutines(SearchRoutines event, Emitter<RoutineState> emit) async {
FutureOr<void> _onSearchRoutines(
SearchRoutines event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null));
await Future.delayed(const Duration(seconds: 1));
emit(state.copyWith(isLoading: false, errorMessage: null));
emit(state.copyWith(searchText: event.query));
}
FutureOr<void> _onAddSelectedIcon(AddSelectedIcon event, Emitter<RoutineState> emit) {
FutureOr<void> _onAddSelectedIcon(
AddSelectedIcon event, Emitter<RoutineState> emit) {
emit(state.copyWith(selectedIcon: event.icon));
}
@ -180,7 +194,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
return actions.first['deviceId'] == 'delay';
}
Future<void> _onCreateScene(CreateSceneEvent event, Emitter<RoutineState> emit) async {
Future<void> _onCreateScene(
CreateSceneEvent event, Emitter<RoutineState> emit) async {
try {
// Check if first action is delay
if (_isFirstActionDelay(state.thenItems)) {
@ -255,7 +270,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}
}
Future<void> _onCreateAutomation(CreateAutomationEvent event, Emitter<RoutineState> emit) async {
Future<void> _onCreateAutomation(
CreateAutomationEvent event, Emitter<RoutineState> emit) async {
try {
if (state.routineName == null || state.routineName!.isEmpty) {
emit(state.copyWith(
@ -355,17 +371,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}
}
FutureOr<void> _onRemoveDragCard(RemoveDragCard event, Emitter<RoutineState> emit) {
FutureOr<void> _onRemoveDragCard(
RemoveDragCard event, Emitter<RoutineState> emit) {
if (event.isFromThen) {
final thenItems = List<Map<String, dynamic>>.from(state.thenItems);
final selectedFunctions = Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
final selectedFunctions =
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
thenItems.removeAt(event.index);
selectedFunctions.remove(event.key);
emit(state.copyWith(thenItems: thenItems, selectedFunctions: selectedFunctions));
emit(state.copyWith(
thenItems: thenItems, selectedFunctions: selectedFunctions));
} else {
final ifItems = List<Map<String, dynamic>>.from(state.ifItems);
final selectedFunctions = Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
final selectedFunctions =
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
ifItems.removeAt(event.index);
selectedFunctions.remove(event.key);
@ -376,7 +396,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
isAutomation: false,
isTabToRun: false));
} else {
emit(state.copyWith(ifItems: ifItems, selectedFunctions: selectedFunctions));
emit(state.copyWith(
ifItems: ifItems, selectedFunctions: selectedFunctions));
}
}
}
@ -388,15 +409,18 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
));
}
FutureOr<void> _onEffectiveTimeEvent(EffectiveTimePeriodEvent event, Emitter<RoutineState> emit) {
FutureOr<void> _onEffectiveTimeEvent(
EffectiveTimePeriodEvent event, Emitter<RoutineState> emit) {
emit(state.copyWith(effectiveTime: event.effectiveTime));
}
FutureOr<void> _onSetRoutineName(SetRoutineName event, Emitter<RoutineState> emit) {
FutureOr<void> _onSetRoutineName(
SetRoutineName event, Emitter<RoutineState> emit) {
emit(state.copyWith(routineName: event.name));
}
Future<void> _onGetSceneDetails(GetSceneDetails event, Emitter<RoutineState> emit) async {
Future<void> _onGetSceneDetails(
GetSceneDetails event, Emitter<RoutineState> emit) async {
try {
emit(state.copyWith(
isLoading: true,
@ -424,7 +448,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
isTabToRun: false,
isUpdate: true,
));
final automationDetails = await SceneApi.getAutomationDetails(event.automationId);
final automationDetails =
await SceneApi.getAutomationDetails(event.automationId);
add(InitializeRoutineState(automationDetails));
} catch (e) {
emit(state.copyWith(
@ -434,81 +459,83 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}
}
void _onInitializeRoutineState(InitializeRoutineState event, Emitter<RoutineState> emit) {
final routineDetails = event.routineDetails;
// void _onInitializeRoutineState(
// InitializeRoutineState event, Emitter<RoutineState> emit) {
// final routineDetails = event.routineDetails;
// Convert actions to draggable cards for the THEN container
final thenItems = routineDetails.actions.map((action) {
final Map<String, dynamic> cardData = {
'entityId': action.entityId,
'uniqueCustomId': const Uuid().v4(),
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
'title': action.actionExecutor == 'delay' ? 'Delay' : 'Device',
// fix this
'imagePath': action.actionExecutor == 'delay' ? Assets.delay : Assets.logo,
};
// // Convert actions to draggable cards for the THEN container
// final thenItems = routineDetails.actions.map((action) {
// final Map<String, dynamic> cardData = {
// 'entityId': action.entityId,
// 'uniqueCustomId': const Uuid().v4(),
// 'deviceId':
// action.actionExecutor == 'delay' ? 'delay' : action.entityId,
// 'title': action.actionExecutor == 'delay' ? 'Delay' : 'Device',
// // fix this
// 'imagePath':
// action.actionExecutor == 'delay' ? Assets.delay : Assets.logo,
// };
// Add functions to selectedFunctions
if (action.executorProperty != null) {
final functions = <DeviceFunctionData>[
DeviceFunctionData(
entityId: action.entityId,
functionCode: action.executorProperty!.functionCode ?? '',
value: action.executorProperty!.functionValue,
// // Add functions to selectedFunctions
// if (action.executorProperty != null) {
// final functions = <DeviceFunctionData>[
// DeviceFunctionData(
// entityId: action.entityId,
// functionCode: action.executorProperty!.functionCode ?? '',
// value: action.executorProperty!.functionValue,
/// fix this
operationName: action.executorProperty?.functionCode ?? ''),
];
state.selectedFunctions[cardData['uniqueCustomId']] = functions;
}
// /// fix this
// operationName: action.executorProperty?.functionCode ?? ''),
// ];
// state.selectedFunctions[cardData['uniqueCustomId']] = functions;
// }
return cardData;
}).toList() ??
[];
// return cardData;
// }).toList();
// Convert conditions to draggable cards for the IF container
final ifItems = routineDetails.conditions?.map((condition) {
final Map<String, dynamic> cardData = {
'entityId': condition.entityId,
'uniqueCustomId': const Uuid().v4(),
'deviceId': condition.entityId,
// // Convert conditions to draggable cards for the IF container
// final ifItems = routineDetails.conditions?.map((condition) {
// final Map<String, dynamic> cardData = {
// 'entityId': condition.entityId,
// 'uniqueCustomId': const Uuid().v4(),
// 'deviceId': condition.entityId,
/// fix this
'title': 'Device',
// /// fix this
// 'title': 'Device',
/// fix this
'imagePath': Assets.logo,
};
// /// fix this
// 'imagePath': Assets.logo,
// };
// Add functions to selectedFunctions
final functions = <DeviceFunctionData>[
DeviceFunctionData(
entityId: condition.entityId,
functionCode: condition.expr.statusCode,
value: condition.expr.statusValue,
condition: condition.expr.comparator,
operationName: condition.expr.comparator,
),
];
state.selectedFunctions[cardData['uniqueCustomId']] = functions;
// // Add functions to selectedFunctions
// final functions = <DeviceFunctionData>[
// DeviceFunctionData(
// entityId: condition.entityId,
// functionCode: condition.expr.statusCode,
// value: condition.expr.statusValue,
// condition: condition.expr.comparator,
// operationName: condition.expr.comparator,
// ),
// ];
// state.selectedFunctions[cardData['uniqueCustomId']] = functions;
return cardData;
}).toList() ??
[];
// return cardData;
// }).toList() ??
// [];
emit(state.copyWith(
isLoading: false,
routineName: routineDetails.name,
selectedIcon: routineDetails.iconId,
selectedAutomationOperator: routineDetails.decisionExpr,
effectiveTime: routineDetails.effectiveTime,
isAutomation: routineDetails.conditions != null,
isTabToRun: routineDetails.conditions == null,
thenItems: thenItems,
ifItems: ifItems,
selectedFunctions: Map.from(state.selectedFunctions),
));
}
// emit(state.copyWith(
// isLoading: false,
// routineName: routineDetails.name,
// selectedIcon: routineDetails.iconId,
// selectedAutomationOperator: routineDetails.decisionExpr,
// effectiveTime: routineDetails.effectiveTime,
// isAutomation: routineDetails.conditions != null,
// isTabToRun: routineDetails.conditions == null,
// thenItems: thenItems,
// ifItems: ifItems,
// selectedFunctions: Map.from(state.selectedFunctions),
// ));
// }
RoutineState _resetState() {
return const RoutineState(
@ -531,7 +558,38 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
);
}
FutureOr<void> _onResetRoutineState(ResetRoutineState event, Emitter<RoutineState> emit) {
FutureOr<void> _onResetRoutineState(
ResetRoutineState event, Emitter<RoutineState> emit) {
emit(_resetState());
}
FutureOr<void> _deleteScene(DeleteScene event, Emitter<RoutineState> emit) {
try {
// emit(state.copyWith(isLoading: true));
SceneApi.deleteScene(unitUuid: spaceId, sceneId: event.sceneId);
add(const LoadScenes(spaceId, communityId));
//emit(_resetState());
} catch (e) {
emit(state.copyWith(
isLoading: false,
errorMessage: 'Failed to delete scene',
));
}
}
FutureOr<void> _deleteAutomation(
DeleteAutomation event, Emitter<RoutineState> emit) {
try {
//emit(state.copyWith(isLoading: true));
SceneApi.deleteAutomation(
unitUuid: spaceId, automationId: event.automationId);
add(const LoadAutomation(spaceId));
// emit(_resetState());
} catch (e) {
emit(state.copyWith(
isLoading: false,
errorMessage: 'Failed to delete automation',
));
}
}
}

View File

@ -158,6 +158,22 @@ class InitializeRoutineState extends RoutineEvent {
List<Object> get props => [routineDetails];
}
class DeleteScene extends RoutineEvent {
final String sceneId;
final String unitUuid;
const DeleteScene({required this.sceneId, required this.unitUuid});
@override
List<Object> get props => [sceneId];
}
class DeleteAutomation extends RoutineEvent {
final String automationId;
final String unitUuid;
const DeleteAutomation({required this.automationId, required this.unitUuid});
@override
List<Object> get props => [automationId];
}
class ResetRoutineState extends RoutineEvent {}
class ClearFunctions extends RoutineEvent {}

View File

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
@ -81,7 +83,9 @@ class DraggableCard extends StatelessWidget {
? SvgPicture.asset(
imagePath,
)
: Image.network(imagePath),
: Image.memory(
base64Decode(imagePath),
),
),
const SizedBox(height: 8),
Padding(

View File

@ -11,7 +11,8 @@ class FetchRoutineScenesAutomation extends StatefulWidget {
const FetchRoutineScenesAutomation({super.key});
@override
State<FetchRoutineScenesAutomation> createState() => _FetchRoutineScenesState();
State<FetchRoutineScenesAutomation> createState() =>
_FetchRoutineScenesState();
}
class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
@ -66,12 +67,49 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
padding: EdgeInsets.only(
right: isSmallScreenSize(context) ? 4.0 : 8.0,
),
child: RoutineViewCard(
child: Stack(
children: [
RoutineViewCard(
onTap: () {},
textString: state.scenes[index].name,
icon: state.scenes[index].icon ?? Assets.logoHorizontal,
icon: state.scenes[index].icon ??
Assets.logoHorizontal,
isFromScenes: true,
iconInBytes: state.scenes[index].iconInBytes,
iconInBytes:
state.scenes[index].iconInBytes,
),
Positioned(
top: 0,
right: 0,
child: InkWell(
onTap: () => context
.read<RoutineBloc>()
.add(
DeleteScene(
sceneId: state.scenes[index].id,
unitUuid: spaceId,
),
),
child: Container(
height: 20,
width: 20,
decoration: BoxDecoration(
color: ColorsManager.whiteColors,
shape: BoxShape.circle,
border: Border.all(
color: ColorsManager.grayColor,
width: 2.0,
),
),
child: const Center(
child: Icon(Icons.delete,
size: 15,
color: ColorsManager.grayColor),
),
),
),
),
],
),
),
),
@ -104,10 +142,46 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
padding: EdgeInsets.only(
right: isSmallScreenSize(context) ? 4.0 : 8.0,
),
child: RoutineViewCard(
child: Stack(
children: [
RoutineViewCard(
onTap: () {},
textString: state.automations[index].name,
icon: state.automations[index].icon ?? Assets.automation,
icon: state.automations[index].icon ??
Assets.automation,
),
Positioned(
top: 0,
right: 0,
child: InkWell(
onTap: () =>
context.read<RoutineBloc>().add(
DeleteAutomation(
automationId: state
.automations[index].id,
unitUuid: spaceId,
),
),
child: Container(
height: 20,
width: 20,
decoration: BoxDecoration(
color: ColorsManager.whiteColors,
shape: BoxShape.circle,
border: Border.all(
color: ColorsManager.grayColor,
width: 2.0,
),
),
child: const Center(
child: Icon(Icons.delete,
size: 15,
color: ColorsManager.grayColor),
),
),
),
),
],
),
),
),

View File

@ -212,38 +212,39 @@ class SceneApi {
// }
// }
//
// //delete Scene
//
// static Future<bool> deleteScene(
// {required String unitUuid, required String sceneId}) async {
// try {
// final response = await _httpService.delete(
// path: ApiEndpoints.deleteScene
// .replaceAll('{sceneId}', sceneId)
// .replaceAll('{unitUuid}', unitUuid),
// showServerMessage: false,
// expectedResponseModel: (json) => json['statusCode'] == 200,
// );
// return response;
// } catch (e) {
// rethrow;
// }
// }
//
// // delete automation
// static Future<bool> deleteAutomation(
// {required String unitUuid, required String automationId}) async {
// try {
// final response = await _httpService.delete(
// path: ApiEndpoints.deleteAutomation
// .replaceAll('{automationId}', automationId)
// .replaceAll('{unitUuid}', unitUuid),
// showServerMessage: false,
// expectedResponseModel: (json) => json['statusCode'] == 200,
// );
// return response;
// } catch (e) {
// rethrow;
// }
// }
//delete Scene
static Future<bool> deleteScene(
{required String unitUuid, required String sceneId}) async {
try {
final response = await _httpService.delete(
path: ApiEndpoints.deleteScene
.replaceAll('{sceneId}', sceneId)
.replaceAll('{unitUuid}', unitUuid),
showServerMessage: false,
expectedResponseModel: (json) => json['statusCode'] == 200,
);
return response;
} catch (e) {
rethrow;
}
}
// delete automation
static Future<bool> deleteAutomation(
{required String unitUuid, required String automationId}) async {
try {
final response = await _httpService.delete(
path: ApiEndpoints.deleteAutomation
.replaceAll('{automationId}', automationId)
.replaceAll('{unitUuid}', unitUuid),
showServerMessage: false,
expectedResponseModel: (json) => json['statusCode'] == 200,
);
return response;
} catch (e) {
rethrow;
}
}
}

View File

@ -59,4 +59,7 @@ abstract class ApiEndpoints {
static const String getAutomationDetails =
'/automation/details/{automationId}';
static const String getScene = '/scene/tap-to-run/{sceneId}';
static const String deleteScene = '/scene/tap-to-run/{sceneId}';
static const String deleteAutomation = '/automation/{automationId}';
}