Implemented side tree to devices and rountines screen

This commit is contained in:
Abdullah Alassaf
2025-01-04 17:45:15 +03:00
parent 0341844ea9
commit a98f7e77a3
88 changed files with 1551 additions and 1202 deletions

View File

@ -0,0 +1,118 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_event.dart';
import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_state.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart';
class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {
final daysMap = {
'Sun': 'S',
'Mon': 'M',
'Tue': 'T',
'Wed': 'W',
'Thu': 'T',
'Fri': 'F',
'Sat': 'S',
};
EffectPeriodBloc() : super(EffectPeriodState.initial()) {
on<InitialEffectPeriodEvent>(_initialEvent);
on<SetPeriod>(_onSetPeriod);
on<ToggleDay>(_onToggleDay);
on<SetCustomTime>(_onSetCustomTime);
on<ResetEffectivePeriod>(_onResetEffectivePeriod);
on<ResetDays>(_onResetDays);
on<SetDays>(_setAllDays);
}
void _initialEvent(InitialEffectPeriodEvent event, Emitter<EffectPeriodState> emit) {
add(SetCustomTime(event.effectiveTime.start, event.effectiveTime.end));
emit(state.copyWith(
selectedDaysBinary: event.effectiveTime.loops,
customStartTime: event.effectiveTime.start,
customEndTime: event.effectiveTime.end,
));
}
void _onSetPeriod(SetPeriod event, Emitter<EffectPeriodState> emit) {
String startTime = '';
String endTime = '';
switch (event.period) {
case EnumEffectivePeriodOptions.allDay:
startTime = '00:00';
endTime = '23:59';
break;
case EnumEffectivePeriodOptions.daytime:
startTime = '06:00';
endTime = '18:00';
break;
case EnumEffectivePeriodOptions.night:
startTime = '18:00';
endTime = '06:00';
break;
case EnumEffectivePeriodOptions.custom:
startTime = state.customStartTime ?? '00:00';
endTime = state.customEndTime ?? '23:59';
break;
default:
break;
}
emit(state.copyWith(
selectedPeriod: event.period, customStartTime: startTime, customEndTime: endTime));
}
void _onToggleDay(ToggleDay event, Emitter<EffectPeriodState> emit) {
final daysList = state.selectedDaysBinary.split('');
final dayIndex = getDayIndex(event.day);
if (daysList[dayIndex] == '1') {
daysList[dayIndex] = '0';
} else {
daysList[dayIndex] = '1';
}
final newDaysBinary = daysList.join();
emit(state.copyWith(selectedDaysBinary: newDaysBinary));
}
void _onSetCustomTime(SetCustomTime event, Emitter<EffectPeriodState> emit) {
String startTime = event.startTime;
String endTime = event.endTime;
EnumEffectivePeriodOptions period;
// Determine the period based on start and end times
if (startTime == '00:00' && endTime == '23:59') {
period = EnumEffectivePeriodOptions.allDay;
} else if (startTime == '06:00' && endTime == '18:00') {
period = EnumEffectivePeriodOptions.daytime;
} else if (startTime == '18:00' && endTime == '06:00') {
period = EnumEffectivePeriodOptions.night;
} else {
period = EnumEffectivePeriodOptions.custom;
}
emit(
state.copyWith(customStartTime: startTime, customEndTime: endTime, selectedPeriod: period));
}
void _onResetEffectivePeriod(ResetEffectivePeriod event, Emitter<EffectPeriodState> emit) {
emit(state.copyWith(
selectedPeriod: EnumEffectivePeriodOptions.allDay,
customStartTime: '00:00',
customEndTime: '23:59',
selectedDaysBinary: '1111111'));
}
void _onResetDays(ResetDays event, Emitter<EffectPeriodState> emit) {
emit(state.copyWith(selectedDaysBinary: '1111111'));
}
int getDayIndex(String day) {
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
return days.indexOf(day);
}
FutureOr<void> _setAllDays(SetDays event, Emitter<EffectPeriodState> emit) {
emit(state.copyWith(selectedDaysBinary: event.daysBinary));
}
}

View File

@ -0,0 +1,60 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart';
abstract class EffectPeriodEvent extends Equatable {
const EffectPeriodEvent();
@override
List<Object> get props => [];
}
class InitialEffectPeriodEvent extends EffectPeriodEvent {
final EffectiveTime effectiveTime;
const InitialEffectPeriodEvent(this.effectiveTime);
@override
List<Object> get props => [effectiveTime];
}
class SetPeriod extends EffectPeriodEvent {
final EnumEffectivePeriodOptions period;
const SetPeriod(this.period);
@override
List<Object> get props => [period];
}
class ToggleDay extends EffectPeriodEvent {
final String day;
const ToggleDay(this.day);
@override
List<Object> get props => [day];
}
class SetCustomTime extends EffectPeriodEvent {
final String startTime;
final String endTime;
const SetCustomTime(this.startTime, this.endTime);
@override
List<Object> get props => [startTime, endTime];
}
class ResetEffectivePeriod extends EffectPeriodEvent {}
class ResetDays extends EffectPeriodEvent {
@override
List<Object> get props => [];
}
class SetDays extends EffectPeriodEvent {
final String daysBinary;
const SetDays(this.daysBinary);
}

View File

@ -0,0 +1,54 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart';
class EffectPeriodState extends Equatable {
final EnumEffectivePeriodOptions selectedPeriod;
final String selectedDaysBinary;
final String? customStartTime;
final String? customEndTime;
const EffectPeriodState({
required this.selectedPeriod,
required this.selectedDaysBinary,
this.customStartTime,
this.customEndTime,
});
factory EffectPeriodState.initial() {
return const EffectPeriodState(
selectedPeriod: EnumEffectivePeriodOptions.allDay,
selectedDaysBinary: "1111111", // All days selected
customStartTime: "00:00",
customEndTime: "23:59",
);
}
EffectPeriodState copyWith({
EnumEffectivePeriodOptions? selectedPeriod,
String? selectedDaysBinary,
String? customStartTime,
String? customEndTime,
}) {
return EffectPeriodState(
selectedPeriod: selectedPeriod ?? this.selectedPeriod,
selectedDaysBinary: selectedDaysBinary ?? this.selectedDaysBinary,
customStartTime: customStartTime ?? this.customStartTime,
customEndTime: customEndTime ?? this.customEndTime,
);
}
EnumEffectivePeriodOptions getEffectivePeriod() {
if (customStartTime == '00:00' && customEndTime == '23:59') {
return EnumEffectivePeriodOptions.allDay;
} else if (customStartTime == '06:00' && customEndTime == '18:00') {
return EnumEffectivePeriodOptions.daytime;
} else if (customStartTime == '18:00' && customEndTime == '06:00') {
return EnumEffectivePeriodOptions.night;
} else {
return EnumEffectivePeriodOptions.custom;
}
}
@override
List<Object?> get props => [selectedPeriod, selectedDaysBinary, customStartTime, customEndTime];
}

View File

@ -0,0 +1,65 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
part 'functions_bloc_event.dart';
part 'functions_bloc_state.dart';
class FunctionBloc extends Bloc<FunctionBlocEvent, FunctionBlocState> {
FunctionBloc() : super(const FunctionBlocState()) {
on<InitializeFunctions>(_onInitializeFunctions);
on<AddFunction>(_onAddFunction);
on<SelectFunction>(_onSelectFunction);
}
void _onAddFunction(AddFunction event, Emitter<FunctionBlocState> emit) {
final functions = List<DeviceFunctionData>.from(state.addedFunctions);
final existingIndex = functions.indexWhere(
(f) => f.functionCode == event.functionData.functionCode,
);
if (existingIndex != -1) {
final existingData = functions[existingIndex];
functions[existingIndex] = DeviceFunctionData(
entityId: event.functionData.entityId,
functionCode: event.functionData.functionCode,
operationName: event.functionData.operationName,
value: event.functionData.value ?? existingData.value,
valueDescription: event.functionData.valueDescription ?? existingData.valueDescription,
condition: event.functionData.condition ?? existingData.condition,
);
} else {
functions.add(event.functionData);
}
emit(state.copyWith(
addedFunctions: functions,
selectedFunction: event.functionData.functionCode,
));
}
void _onInitializeFunctions(
InitializeFunctions event,
Emitter<FunctionBlocState> emit,
) {
emit(state.copyWith(addedFunctions: event.functions));
}
DeviceFunctionData? getFunction(String functionCode) {
return state.addedFunctions.firstWhere(
(data) => data.functionCode == functionCode,
orElse: () => DeviceFunctionData(
entityId: '',
functionCode: functionCode,
operationName: '',
value: null,
),
);
}
FutureOr<void> _onSelectFunction(SelectFunction event, Emitter<FunctionBlocState> emit) {
emit(state.copyWith(
selectedFunction: event.functionCode, selectedOperationName: event.operationName));
}
}

View File

@ -0,0 +1,41 @@
part of 'functions_bloc_bloc.dart';
abstract class FunctionBlocEvent extends Equatable {
const FunctionBlocEvent();
@override
List<Object?> get props => [];
}
class AddFunction extends FunctionBlocEvent {
final DeviceFunctionData functionData;
const AddFunction({
required this.functionData,
});
@override
List<Object?> get props => [functionData];
}
class SelectFunction extends FunctionBlocEvent {
final String functionCode;
final String operationName;
const SelectFunction({
required this.functionCode,
required this.operationName,
});
@override
List<Object?> get props => [functionCode, operationName];
}
class InitializeFunctions extends FunctionBlocEvent {
final List<DeviceFunctionData> functions;
const InitializeFunctions(this.functions);
@override
List<Object?> get props => [functions];
}

View File

@ -0,0 +1,29 @@
part of 'functions_bloc_bloc.dart';
class FunctionBlocState extends Equatable {
final List<DeviceFunctionData> addedFunctions;
final String? selectedFunction;
final String? selectedOperationName;
const FunctionBlocState({
this.addedFunctions = const [],
this.selectedFunction,
this.selectedOperationName,
});
FunctionBlocState copyWith({
List<DeviceFunctionData>? addedFunctions,
String? selectedFunction,
String? selectedOperationName,
}) {
return FunctionBlocState(
addedFunctions: addedFunctions ?? this.addedFunctions,
selectedFunction: selectedFunction ?? this.selectedFunction,
selectedOperationName:
selectedOperationName ?? this.selectedOperationName,
);
}
@override
List<Object?> get props =>
[addedFunctions, selectedFunction, selectedOperationName];
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,210 @@
part of 'routine_bloc.dart';
abstract class RoutineEvent extends Equatable {
const RoutineEvent();
@override
List<Object> get props => [];
}
class AddToIfContainer extends RoutineEvent {
final Map<String, dynamic> item;
final bool isTabToRun;
const AddToIfContainer(this.item, this.isTabToRun);
@override
List<Object> get props => [item, isTabToRun];
}
class AddToThenContainer extends RoutineEvent {
final Map<String, dynamic> item;
const AddToThenContainer(this.item);
@override
List<Object> get props => [item];
}
class LoadScenes extends RoutineEvent {
final String spaceId;
final String communityId;
const LoadScenes(this.spaceId, this.communityId);
@override
List<Object> get props => [spaceId, communityId];
}
class LoadAutomation extends RoutineEvent {
final String spaceId;
const LoadAutomation(this.spaceId);
@override
List<Object> get props => [spaceId];
}
class AddFunctionToRoutine extends RoutineEvent {
final List<DeviceFunctionData> functions;
final String uniqueCustomId;
const AddFunctionToRoutine(this.functions, this.uniqueCustomId);
@override
List<Object> get props => [functions, uniqueCustomId];
}
class RemoveFunction extends RoutineEvent {
final DeviceFunctionData function;
const RemoveFunction(this.function);
@override
List<Object> get props => [function];
}
class SearchRoutines extends RoutineEvent {
final String query;
const SearchRoutines(this.query);
@override
List<Object> get props => [query];
}
class AddSelectedIcon extends RoutineEvent {
final String icon;
const AddSelectedIcon(this.icon);
@override
List<Object> get props => [icon];
}
class CreateSceneEvent extends RoutineEvent {
const CreateSceneEvent();
@override
List<Object> get props => [];
}
class RemoveDragCard extends RoutineEvent {
final int index;
final bool isFromThen;
final String key;
const RemoveDragCard({required this.index, required this.isFromThen, required this.key});
@override
List<Object> get props => [index, isFromThen, key];
}
class ChangeAutomationOperator extends RoutineEvent {
final String operator;
const ChangeAutomationOperator({required this.operator});
@override
List<Object> get props => [operator];
}
class EffectiveTimePeriodEvent extends RoutineEvent {
final EffectiveTime effectiveTime;
const EffectiveTimePeriodEvent(this.effectiveTime);
@override
List<Object> get props => [effectiveTime];
}
class CreateAutomationEvent extends RoutineEvent {
final String? automationId;
final bool updateAutomation;
const CreateAutomationEvent({
this.automationId,
this.updateAutomation = false,
});
@override
List<Object> get props => [];
}
class SetRoutineName extends RoutineEvent {
final String name;
const SetRoutineName(this.name);
@override
List<Object> get props => [name];
}
class GetSceneDetails extends RoutineEvent {
final String sceneId;
final bool isUpdate;
final bool isTabToRun;
const GetSceneDetails({
required this.sceneId,
required this.isUpdate,
required this.isTabToRun,
});
@override
List<Object> get props => [sceneId];
}
class GetAutomationDetails extends RoutineEvent {
final String automationId;
final bool isUpdate;
final bool isAutomation;
const GetAutomationDetails({
required this.automationId,
this.isUpdate = false,
this.isAutomation = false,
});
@override
List<Object> get props => [automationId];
}
class InitializeRoutineState extends RoutineEvent {
final RoutineDetailsModel routineDetails;
const InitializeRoutineState(this.routineDetails);
@override
List<Object> get props => [routineDetails];
}
class DeleteScene extends RoutineEvent {
const DeleteScene();
@override
List<Object> get props => [];
}
// class DeleteAutomation extends RoutineEvent {
// final String automationId;
// const DeleteAutomation({required this.automationId});
// @override
// List<Object> get props => [automationId];
// }
class UpdateScene extends RoutineEvent {
const UpdateScene();
@override
List<Object> get props => [];
}
class UpdateAutomation extends RoutineEvent {
const UpdateAutomation();
@override
List<Object> get props => [];
}
class SetAutomationActionExecutor extends RoutineEvent {
final String automationActionExecutor;
const SetAutomationActionExecutor({required this.automationActionExecutor});
@override
List<Object> get props => [automationActionExecutor];
}
class TriggerSwitchTabsEvent extends RoutineEvent {
final bool isRoutineTab;
const TriggerSwitchTabsEvent({required this.isRoutineTab});
@override
List<Object> get props => [isRoutineTab];
}
class CreateNewRoutineViewEvent extends RoutineEvent {
final bool createRoutineView;
const CreateNewRoutineViewEvent({required this.createRoutineView});
@override
List<Object> get props => [createRoutineView];
}
class FetchDevicesInRoutine extends RoutineEvent {}
class ResetRoutineState extends RoutineEvent {}
class ClearFunctions extends RoutineEvent {}
class ResetErrorMessage extends RoutineEvent {}

View File

@ -0,0 +1,136 @@
part of 'routine_bloc.dart';
class RoutineState extends Equatable {
final List<Map<String, dynamic>> ifItems;
final List<Map<String, dynamic>> thenItems;
final List<Map<String, String>> availableCards;
final List<ScenesModel> scenes;
final List<ScenesModel> automations;
final Map<String, List<DeviceFunctionData>> selectedFunctions;
final bool isLoading;
final String? errorMessage;
final String? loadScenesErrorMessage;
final String? loadAutomationErrorMessage;
final String? routineName;
final String? selectedIcon;
final String? searchText;
final bool isTabToRun;
final bool isAutomation;
final String selectedAutomationOperator;
final EffectiveTime? effectiveTime;
final String? sceneId;
final String? automationId;
final bool? isUpdate;
final List<AllDevicesModel> devices;
// final String? automationActionExecutor;
final bool routineTab;
final bool createRoutineView;
const RoutineState(
{this.ifItems = const [],
this.thenItems = const [],
this.availableCards = const [],
this.scenes = const [],
this.automations = const [],
this.selectedFunctions = const {},
this.isLoading = false,
this.errorMessage,
this.routineName,
this.selectedIcon,
this.loadScenesErrorMessage,
this.loadAutomationErrorMessage,
this.searchText,
this.isTabToRun = false,
this.isAutomation = false,
this.selectedAutomationOperator = 'or',
this.effectiveTime,
this.sceneId,
this.automationId,
this.isUpdate,
this.devices = const [],
// this.automationActionExecutor,
this.routineTab = false,
this.createRoutineView = false});
RoutineState copyWith({
List<Map<String, dynamic>>? ifItems,
List<Map<String, dynamic>>? thenItems,
List<ScenesModel>? scenes,
List<ScenesModel>? automations,
Map<String, List<DeviceFunctionData>>? selectedFunctions,
bool? isLoading,
String? errorMessage,
String? routineName,
String? selectedIcon,
String? loadAutomationErrorMessage,
String? loadScenesErrorMessage,
String? searchText,
bool? isTabToRun,
bool? isAutomation,
String? selectedAutomationOperator,
EffectiveTime? effectiveTime,
String? sceneId,
String? automationId,
bool? isUpdate,
List<AllDevicesModel>? devices,
// String? automationActionExecutor,
TextEditingController? nameController,
bool? routineTab,
bool? createRoutineView,
}) {
return RoutineState(
ifItems: ifItems ?? this.ifItems,
thenItems: thenItems ?? this.thenItems,
scenes: scenes ?? this.scenes,
automations: automations ?? this.automations,
selectedFunctions: selectedFunctions ?? this.selectedFunctions,
isLoading: isLoading ?? this.isLoading,
errorMessage: errorMessage ?? this.errorMessage,
routineName: routineName ?? this.routineName,
selectedIcon: selectedIcon ?? this.selectedIcon,
loadScenesErrorMessage:
loadScenesErrorMessage ?? this.loadScenesErrorMessage,
loadAutomationErrorMessage:
loadAutomationErrorMessage ?? this.loadAutomationErrorMessage,
searchText: searchText ?? this.searchText,
isTabToRun: isTabToRun ?? this.isTabToRun,
isAutomation: isAutomation ?? this.isAutomation,
selectedAutomationOperator:
selectedAutomationOperator ?? this.selectedAutomationOperator,
effectiveTime: effectiveTime ?? this.effectiveTime,
sceneId: sceneId ?? this.sceneId,
automationId: automationId ?? this.automationId,
isUpdate: isUpdate ?? this.isUpdate,
devices: devices ?? this.devices,
// automationActionExecutor: automationActionExecutor ?? this.automationActionExecutor,
routineTab: routineTab ?? this.routineTab,
createRoutineView: createRoutineView ?? this.createRoutineView);
}
@override
List<Object?> get props => [
ifItems,
thenItems,
scenes,
automations,
selectedFunctions,
isLoading,
errorMessage,
routineName,
selectedIcon,
loadScenesErrorMessage,
loadAutomationErrorMessage,
searchText,
isTabToRun,
isAutomation,
selectedAutomationOperator,
effectiveTime,
sceneId,
automationId,
isUpdate,
devices,
// automationActionExecutor,
routineTab,
createRoutineView
];
}

View File

@ -0,0 +1,53 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routines/bloc/setting_bloc/setting_event.dart';
import 'package:syncrow_web/pages/routines/bloc/setting_bloc/setting_state.dart';
import 'package:syncrow_web/pages/routines/models/icon_model.dart';
import 'package:syncrow_web/services/routines_api.dart';
class SettingBloc extends Bloc<SettingEvent, SettingState> {
bool isExpanded = false;
String selectedIcon = '';
List<IconModel> iconModelList = [];
SettingBloc() : super(const InitialState()) {
on<InitialEvent>(_initialSetting);
on<FetchIcons>(_fetchIcons);
on<SelectIcon>(_selectIcon);
}
void _initialSetting(InitialEvent event, Emitter<SettingState> emit) async {
try {
emit(const LoadingState());
selectedIcon = event.selectedIcon;
emit(TabToRunSettingLoaded(
showInDevice: true, selectedIcon: event.selectedIcon, iconList: iconModelList));
} catch (e) {
emit(const FailedState(error: 'Something went wrong'));
}
}
void _fetchIcons(FetchIcons event, Emitter<SettingState> emit) async {
try {
isExpanded = event.expanded;
emit(const LoadingState());
if (isExpanded) {
iconModelList = await SceneApi.getIcon();
emit(TabToRunSettingLoaded(
showInDevice: true, selectedIcon: selectedIcon, iconList: iconModelList));
}
} catch (e) {
emit(const FailedState(error: 'Something went wrong'));
}
}
void _selectIcon(SelectIcon event, Emitter<SettingState> emit) async {
try {
emit(const LoadingState());
selectedIcon = event.iconId;
emit(TabToRunSettingLoaded(
showInDevice: true, selectedIcon: event.iconId, iconList: iconModelList));
} catch (e) {
emit(const FailedState(error: 'Something went wrong'));
}
}
}

View File

@ -0,0 +1,32 @@
import 'package:equatable/equatable.dart';
abstract class SettingEvent extends Equatable {
const SettingEvent();
@override
List<Object> get props => [];
}
class InitialEvent extends SettingEvent {
final String selectedIcon;
const InitialEvent({required this.selectedIcon});
@override
List<Object> get props => [selectedIcon];
}
class FetchIcons extends SettingEvent {
final bool expanded;
const FetchIcons({required this.expanded});
@override
List<Object> get props => [expanded];
}
class SelectIcon extends SettingEvent {
final String iconId;
const SelectIcon({required this.iconId});
@override
List<Object> get props => [iconId];
}

View File

@ -0,0 +1,56 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/routines/models/icon_model.dart';
abstract class SettingState extends Equatable {
const SettingState();
@override
List<Object> get props => [];
}
class LoadingState extends SettingState {
const LoadingState();
@override
List<Object> get props => [];
}
class InitialState extends SettingState {
const InitialState();
@override
List<Object> get props => [];
}
class IconLoadedState extends SettingState {
final List<String> status;
const IconLoadedState(this.status);
@override
List<Object> get props => [status];
}
class TabToRunSettingLoaded extends SettingState {
final String selectedIcon;
final List<IconModel> iconList;
final bool showInDevice;
const TabToRunSettingLoaded({
required this.selectedIcon,
required this.iconList,
required this.showInDevice,
});
@override
List<Object> get props => [selectedIcon, iconList, showInDevice];
}
class FailedState extends SettingState {
final String error;
const FailedState({required this.error});
@override
List<Object> get props => [error];
}