mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-14 17:25:47 +00:00
working on functions view
This commit is contained in:
14
assets/icons/functions_icons/sensitivity.svg
Normal file
14
assets/icons/functions_icons/sensitivity.svg
Normal file
@ -0,0 +1,14 @@
|
||||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.5146 19.9607C15.8652 19.9607 16.1494 19.6765 16.1494 19.3259C16.1494 18.9754 15.8652 18.6912 15.5146 18.6912C15.1641 18.6912 14.8799 18.9754 14.8799 19.3259C14.8799 19.6765 15.1641 19.9607 15.5146 19.9607Z" fill="#DDC9F1"/>
|
||||
<path d="M7.33732 19.1868C11.7682 19.1868 21.0841 10.9956 21.0841 4.26414C21.0841 3.59218 20.8674 2.97045 20.3046 2.56246C19.9081 2.35185 19.4641 2.24292 19.0742 2.24292C17.5621 2.24292 16.7455 3.26438 16.3025 3.9008C12.8754 8.82442 9.99403 10.3394 7.8583 11.2551C7.52356 11.4933 7.23271 11.6621 6.96324 11.6298C5.91084 12.0702 5.09334 12.4544 4.54419 13.2512C4.45921 13.3745 4.38131 13.5095 4.31004 13.6532C4.31004 13.6532 3.67896 13.8893 3.43889 14.1227C2.49923 15.036 2.28662 17.0258 2.28662 18.9069C2.70675 18.7839 3.13048 18.6495 3.55615 18.5045V18.5049C4.86851 19.0079 6.31874 19.1868 7.33732 19.1868Z" fill="#DA8BC1"/>
|
||||
<path d="M3.43893 14.123C3.09167 15.1961 2.92139 16.6454 2.92139 18.5051C2.92139 18.5797 2.92194 18.6487 2.92299 18.713C3.13344 18.6463 3.34452 18.5768 3.55615 18.5048V18.5051C3.55615 17.0732 3.65615 14.9729 4.30987 13.6536C3.96642 13.7266 3.67896 13.8897 3.43893 14.123Z" fill="#CA59A6"/>
|
||||
<path d="M6.62797 16.2764C6.80325 16.2764 6.94536 16.1344 6.94536 15.959C6.94536 14.3039 7.34991 11.8794 7.85849 11.2551C7.54373 11.3901 7.24518 11.512 6.96342 11.6299C6.50741 12.8723 6.31055 14.8829 6.31055 15.959C6.31059 16.1344 6.45269 16.2764 6.62797 16.2764Z" fill="#CA59A6"/>
|
||||
<path d="M20.3046 2.5625C20.6108 2.99042 20.7879 3.59222 20.7879 4.26418C20.7879 10.77 11.6554 18.8906 7.33737 18.8906C6.31878 18.8906 5.15161 18.7231 4.24885 18.2599V18.2599C4.0175 18.3447 3.78653 18.4264 3.55615 18.5049C4.48867 19.2643 6.07444 19.5254 7.33737 19.5254C11.9939 19.5254 21.4227 11.1085 21.4227 4.26418C21.4227 3.46493 20.9215 2.89021 20.3046 2.5625Z" fill="#CA59A6"/>
|
||||
<path d="M9.50105 4.48584C9.29555 4.48584 9.15222 6.04419 8.99544 6.20098C8.83865 6.35776 7.74512 6.50448 7.74512 6.71002C7.74512 6.91551 8.83861 7.06223 8.99544 7.21906C9.15222 7.37584 9.29555 8.93419 9.50105 8.93419C9.70654 8.93419 9.84987 7.37584 10.0067 7.21906C10.1634 7.06227 11.257 6.91555 11.257 6.71002C11.257 6.50452 10.1635 6.35781 10.0067 6.20098C9.84991 6.04415 9.70658 4.48584 9.50105 4.48584Z" fill="#DDC9F1"/>
|
||||
<path d="M14.8796 21.9417C15.0665 21.9417 15.2181 21.7902 15.2181 21.6032C15.2181 21.4162 15.0665 21.2646 14.8796 21.2646C14.6926 21.2646 14.541 21.4162 14.541 21.6032C14.541 21.7902 14.6926 21.9417 14.8796 21.9417Z" fill="#DDC9F1"/>
|
||||
<path d="M14.2096 18.1121C14.3966 18.1121 14.5482 17.9606 14.5482 17.7736C14.5482 17.5866 14.3966 17.4351 14.2096 17.4351C14.0227 17.4351 13.8711 17.5866 13.8711 17.7736C13.8711 17.9606 14.0227 18.1121 14.2096 18.1121Z" fill="#ECC3DF"/>
|
||||
<path d="M16.8918 17.9294C16.7165 17.9294 16.5744 17.7874 16.5744 17.6121V16.9773H16.1401C15.9649 16.9773 15.8228 16.8352 15.8228 16.6599C15.8228 16.4846 15.9649 16.3425 16.1401 16.3425H16.5744V15.7078C16.5744 15.5324 16.7165 15.3904 16.8918 15.3904C17.0671 15.3904 17.2092 15.5324 17.2092 15.7078V16.3425H17.6435C17.8188 16.3425 17.9609 16.4846 17.9609 16.6599C17.9609 16.8352 17.8188 16.9773 17.6435 16.9773H17.2092V17.6121C17.2092 17.7873 17.0671 17.9294 16.8918 17.9294Z" fill="#ECC3DF"/>
|
||||
<path d="M7.73855 4.67017C7.56327 4.67017 7.42116 4.52811 7.42116 4.35278V3.71802H6.98682C6.81154 3.71802 6.66943 3.57596 6.66943 3.40063C6.66943 3.22531 6.81154 3.08325 6.98682 3.08325H7.42116V2.44849C7.42116 2.27316 7.56327 2.1311 7.73855 2.1311C7.91383 2.1311 8.05593 2.27316 8.05593 2.44849V3.08325H8.49024C8.66552 3.08325 8.80762 3.22531 8.80762 3.40063C8.80762 3.57596 8.66552 3.71802 8.49024 3.71802H8.05593V4.35278C8.05593 4.52811 7.91383 4.67017 7.73855 4.67017Z" fill="#ECC3DF"/>
|
||||
<path d="M8.65495 0.95223C8.84192 0.95223 8.99349 0.80066 8.99349 0.613688C8.99349 0.426717 8.84192 0.275146 8.65495 0.275146C8.46798 0.275146 8.31641 0.426717 8.31641 0.613688C8.31641 0.80066 8.46798 0.95223 8.65495 0.95223Z" fill="#DDC9F1"/>
|
||||
<path d="M0.39037 19.7094C0.244374 19.7094 0.112977 19.608 0.0806041 19.4596C0.0432376 19.2883 0.151782 19.1192 0.323042 19.0819C6.96125 17.6332 15.102 13.1366 18.3248 6.35624C18.4001 6.19798 18.5894 6.13061 18.7477 6.20585C18.9061 6.28109 18.9734 6.47042 18.8981 6.62873C15.5829 13.6034 7.248 18.2204 0.458332 19.702C0.435523 19.707 0.412756 19.7094 0.39037 19.7094Z" fill="#D5D9F2"/>
|
||||
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -9,7 +11,7 @@ import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/services/api/home_management_api.dart';
|
||||
|
||||
class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
DeviceManagerBloc() : super(DeviceManagerInitial()) {
|
||||
DeviceManagerBloc() : super(DeviceManagerState.initial()) {
|
||||
on<FetchAllDevices>(_onFetchAllDevices);
|
||||
on<FetchDevicesByRoomId>(_onFetchDevicesByRoomId);
|
||||
on<SelectCategory>(_onSelectCategory);
|
||||
@ -18,30 +20,30 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
on<ChangeCategorySwitchValue>(_onChangeCategorySwitchValue);
|
||||
on<TurnOnOffDevice>(_onTurnOnOffDevice);
|
||||
on<ClearCategoriesSelection>(_onClearCategoriesSelection);
|
||||
// on<DeviceControl>(_onDeviceControl);
|
||||
on<DeviceFunctionsEvent>(_getDeviceFunctions);
|
||||
}
|
||||
|
||||
static List<DevicesCategoryModel>? allCategories;
|
||||
|
||||
Future<void> _onFetchAllDevices(
|
||||
FetchAllDevices event, Emitter<DeviceManagerState> emit) async {
|
||||
emit(GetDevicesLoading());
|
||||
emit(state.copyWith(loading: true));
|
||||
try {
|
||||
final allDevices = await HomeManagementAPI.fetchDevicesByUserId();
|
||||
emit(GetDevicesSuccess(allDevices));
|
||||
emit(state.copyWith(devices: allDevices, loading: false));
|
||||
} catch (e) {
|
||||
emit(GetDevicesError(e.toString()));
|
||||
emit(state.copyWith(error: e.toString(), loading: false));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onFetchDevicesByRoomId(
|
||||
FetchDevicesByRoomId event, Emitter<DeviceManagerState> emit) async {
|
||||
emit(GetDevicesLoading());
|
||||
emit(state.copyWith(loading: true));
|
||||
try {
|
||||
final devices = await DevicesAPI.getDevicesByRoomId(event.roomId);
|
||||
emit(GetDevicesSuccess(devices));
|
||||
emit(state.copyWith(devices: devices, loading: false));
|
||||
} catch (e) {
|
||||
emit(GetDevicesError(e.toString()));
|
||||
emit(state.copyWith(error: e.toString(), loading: false));
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +52,7 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
for (var i = 0; i < allCategories!.length; i++) {
|
||||
allCategories![i].isSelected = i == event.index;
|
||||
}
|
||||
emit(DevicesCategoryChanged());
|
||||
emit(state.copyWith(categoryChanged: true));
|
||||
}
|
||||
|
||||
void _onUnselectAllCategories(
|
||||
@ -58,7 +60,7 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
for (var category in allCategories!) {
|
||||
category.isSelected = false;
|
||||
}
|
||||
emit(DevicesCategoryChanged());
|
||||
emit(state.copyWith(categoryChanged: true));
|
||||
}
|
||||
|
||||
void _onSelectDevice(SelectDevice event, Emitter<DeviceManagerState> emit) {
|
||||
@ -67,14 +69,14 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
for (var device in category.devices!) {
|
||||
if (device.isSelected) {
|
||||
category.isSelected = false;
|
||||
emit(DeviceSelected());
|
||||
emit(state.copyWith(deviceSelected: true));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
event.device.isSelected = !event.device.isSelected;
|
||||
emit(DeviceSelected());
|
||||
emit(state.copyWith(deviceSelected: true));
|
||||
}
|
||||
|
||||
void _onChangeCategorySwitchValue(
|
||||
@ -119,28 +121,9 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
}
|
||||
}
|
||||
Navigator.popUntil(event.context, (route) => route.isFirst);
|
||||
emit(DevicesCategoryChanged());
|
||||
emit(state.copyWith(categoryChanged: true)); // Set category changed state
|
||||
}
|
||||
|
||||
// Future<void> _onDeviceControl(
|
||||
// DeviceControl event, Emitter<DeviceManagerState> emit) async {
|
||||
// emit(DeviceControlLoading(code: event.control.code));
|
||||
// try {
|
||||
// var response =
|
||||
// await DevicesAPI.controlDevice(event.control, event.deviceId);
|
||||
// if (response['success'] ?? false) {
|
||||
// emit(DeviceControlSuccess(code: event.control.code));
|
||||
// await Future.delayed(const Duration(milliseconds: 400), () {
|
||||
// add(FetchDevicesByRoomId(event.deviceId));
|
||||
// });
|
||||
// } else {
|
||||
// emit(DeviceControlError('Failed to control the device'));
|
||||
// }
|
||||
// } catch (e) {
|
||||
// emit(DeviceControlError(e.toString()));
|
||||
// }
|
||||
// }
|
||||
|
||||
void _updateDevicesStatus(
|
||||
DevicesCategoryModel category, Emitter<DeviceManagerState> emit) {
|
||||
if (category.devices != null && category.devices!.isNotEmpty) {
|
||||
@ -152,7 +135,20 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
}
|
||||
category.devicesStatus = tempStatus;
|
||||
}
|
||||
emit(CategorySwitchChanged());
|
||||
emit(state.copyWith(categoryChanged: true));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _getDeviceFunctions(
|
||||
DeviceFunctionsEvent event, Emitter<DeviceManagerState> emit) async {
|
||||
emit(state.copyWith(functionsLoading: true));
|
||||
try {
|
||||
final deviceFunctions = await DevicesAPI.deviceFunctions(event.deviceId);
|
||||
|
||||
emit(state.copyWith(
|
||||
functionsLoading: false, deviceFunctions: deviceFunctions));
|
||||
} catch (e) {
|
||||
emit(state.copyWith(functionsLoading: false, error: e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,3 +78,11 @@ class DeviceControl extends DeviceManagerEvent {
|
||||
@override
|
||||
List<Object> get props => [control, deviceId];
|
||||
}
|
||||
|
||||
class DeviceFunctionsEvent extends DeviceManagerEvent {
|
||||
final String deviceId;
|
||||
const DeviceFunctionsEvent(this.deviceId);
|
||||
|
||||
@override
|
||||
List<Object> get props => [deviceId];
|
||||
}
|
||||
|
@ -1,112 +1,73 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/functions.dart';
|
||||
|
||||
abstract class DeviceManagerState extends Equatable {
|
||||
const DeviceManagerState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class DeviceManagerInitial extends DeviceManagerState {}
|
||||
|
||||
class DevicesCategoryChanged extends DeviceManagerState {}
|
||||
|
||||
class DeviceSelected extends DeviceManagerState {}
|
||||
|
||||
class DeviceControlLoading extends DeviceManagerState {
|
||||
final String code;
|
||||
|
||||
const DeviceControlLoading({required this.code});
|
||||
|
||||
@override
|
||||
List<Object> get props => [code];
|
||||
}
|
||||
|
||||
class DeviceControlSuccess extends DeviceManagerState {
|
||||
final String code;
|
||||
|
||||
const DeviceControlSuccess({required this.code});
|
||||
|
||||
@override
|
||||
List<Object> get props => [code];
|
||||
}
|
||||
|
||||
class DeviceControlError extends DeviceManagerState {
|
||||
final String message;
|
||||
|
||||
const DeviceControlError(this.message);
|
||||
|
||||
@override
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
|
||||
class DevicesCategoriesLoading extends DeviceManagerState {}
|
||||
|
||||
class DevicesCategoriesSuccess extends DeviceManagerState {}
|
||||
|
||||
class DevicesCategoriesError extends DeviceManagerState {
|
||||
final String error;
|
||||
|
||||
const DevicesCategoriesError(this.error);
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
|
||||
class GetDevicesLoading extends DeviceManagerState {}
|
||||
|
||||
class GetDevicesSuccess extends DeviceManagerState {
|
||||
class DeviceManagerState extends Equatable {
|
||||
final bool loading;
|
||||
final String? error;
|
||||
final List<DevicesCategoryModel>? allCategories;
|
||||
final List<DeviceModel>? devices;
|
||||
final bool categoryChanged;
|
||||
final bool deviceSelected;
|
||||
final bool functionsLoading;
|
||||
final FunctionsEntity? deviceFunctions;
|
||||
|
||||
const GetDevicesSuccess(this.devices);
|
||||
const DeviceManagerState({
|
||||
required this.loading,
|
||||
this.error,
|
||||
this.allCategories,
|
||||
this.devices,
|
||||
this.categoryChanged = false,
|
||||
this.deviceSelected = false,
|
||||
this.functionsLoading = false,
|
||||
this.deviceFunctions,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [devices ?? []];
|
||||
factory DeviceManagerState.initial() {
|
||||
return const DeviceManagerState(
|
||||
loading: false,
|
||||
error: null,
|
||||
allCategories: null,
|
||||
devices: null,
|
||||
categoryChanged: false,
|
||||
deviceSelected: false,
|
||||
functionsLoading: false,
|
||||
deviceFunctions: null,
|
||||
);
|
||||
}
|
||||
|
||||
class GetDevicesError extends DeviceManagerState {
|
||||
final String error;
|
||||
|
||||
const GetDevicesError(this.error);
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
DeviceManagerState copyWith({
|
||||
bool? loading,
|
||||
String? error,
|
||||
List<DevicesCategoryModel>? allCategories,
|
||||
List<DeviceModel>? devices,
|
||||
bool? categoryChanged,
|
||||
bool? deviceSelected,
|
||||
bool? functionsLoading,
|
||||
FunctionsEntity? deviceFunctions,
|
||||
}) {
|
||||
return DeviceManagerState(
|
||||
loading: loading ?? this.loading,
|
||||
error: error ?? this.error,
|
||||
allCategories: allCategories ?? this.allCategories,
|
||||
devices: devices ?? this.devices,
|
||||
categoryChanged: categoryChanged ?? this.categoryChanged,
|
||||
deviceSelected: deviceSelected ?? this.deviceSelected,
|
||||
functionsLoading: functionsLoading ?? this.functionsLoading,
|
||||
deviceFunctions: deviceFunctions ?? this.deviceFunctions,
|
||||
);
|
||||
}
|
||||
|
||||
class GetDeviceStatusLoading extends DeviceManagerState {
|
||||
final String? code;
|
||||
|
||||
const GetDeviceStatusLoading({this.code});
|
||||
|
||||
@override
|
||||
List<Object> get props => [code ?? ''];
|
||||
List<Object?> get props => [
|
||||
loading,
|
||||
error,
|
||||
allCategories,
|
||||
devices,
|
||||
categoryChanged,
|
||||
deviceSelected,
|
||||
functionsLoading,
|
||||
deviceFunctions,
|
||||
];
|
||||
}
|
||||
|
||||
class GetDeviceStatusSuccess extends DeviceManagerState {
|
||||
final String? code;
|
||||
|
||||
const GetDeviceStatusSuccess({this.code});
|
||||
|
||||
@override
|
||||
List<Object> get props => [code ?? ''];
|
||||
}
|
||||
|
||||
class GetDeviceStatusError extends DeviceManagerState {
|
||||
final String error;
|
||||
|
||||
const GetDeviceStatusError(this.error);
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
|
||||
class CategorySwitchChanged extends DeviceManagerState {}
|
||||
|
||||
class DeviceSwitchChanged extends DeviceManagerState {}
|
||||
|
||||
class CurtainsIsOpening extends DeviceManagerState {}
|
||||
|
||||
class CurtainsIsClosing extends DeviceManagerState {}
|
||||
|
||||
class CurtainsStopped extends DeviceManagerState {}
|
||||
|
@ -331,18 +331,6 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
// }
|
||||
}
|
||||
|
||||
void fetchAllDevices() async {
|
||||
emitSafe(GetDevicesLoading());
|
||||
try {
|
||||
final allDevices = await HomeManagementAPI.fetchDevicesByUserId();
|
||||
|
||||
emitSafe(GetDevicesSuccess(allDevices));
|
||||
} catch (e) {
|
||||
emitSafe(GetDevicesError(e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fetchDevicesStatues(String deviceUuid, int roomIndex, {String? code}) async {
|
||||
emitSafe(GetDeviceStatusLoading(code: code));
|
||||
int deviceIndex = HomeCubit.getInstance()
|
||||
|
58
lib/features/devices/model/functions.dart
Normal file
58
lib/features/devices/model/functions.dart
Normal file
@ -0,0 +1,58 @@
|
||||
class FunctionsEntity {
|
||||
final String productUuid;
|
||||
final String productType;
|
||||
final List<DeviceFunction> functions;
|
||||
|
||||
FunctionsEntity({
|
||||
required this.productUuid,
|
||||
required this.productType,
|
||||
required this.functions,
|
||||
});
|
||||
|
||||
factory FunctionsEntity.fromJson(Map<String, dynamic> json) =>
|
||||
FunctionsEntity(
|
||||
productUuid: json["productUuid"],
|
||||
productType: json["productType"],
|
||||
functions: List<DeviceFunction>.from(
|
||||
json["functions"].map((x) => DeviceFunction.fromJson(x)),
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"productUuid": productUuid,
|
||||
"productType": productType,
|
||||
"functions": List<dynamic>.from(functions.map((x) => x.toJson())),
|
||||
};
|
||||
}
|
||||
|
||||
class DeviceFunction {
|
||||
final String code;
|
||||
final String values;
|
||||
final String dataType;
|
||||
|
||||
DeviceFunction({
|
||||
required this.code,
|
||||
required this.values,
|
||||
required this.dataType,
|
||||
});
|
||||
|
||||
factory DeviceFunction.fromJson(Map<String, dynamic> json) => DeviceFunction(
|
||||
code: _formatCode(json["code"]),
|
||||
values: json["values"],
|
||||
dataType: json["dataType"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"code": code,
|
||||
"values": values,
|
||||
"dataType": dataType,
|
||||
};
|
||||
|
||||
static String _formatCode(String originalCode) {
|
||||
return originalCode
|
||||
.replaceAll('_', ' ')
|
||||
.split(' ')
|
||||
.map((word) => word[0].toUpperCase() + word.substring(1))
|
||||
.join(' ');
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
@ -6,8 +8,6 @@ part 'create_scene_state.dart';
|
||||
|
||||
class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState> {
|
||||
CreateSceneBloc() : super(CreateSceneInitial()) {
|
||||
on<CreateSceneEvent>((event, emit) {
|
||||
// TODO: implement event handler
|
||||
});
|
||||
on<CreateSceneEvent>((event, emit) => null as FutureOr<void>);
|
||||
}
|
||||
}
|
||||
|
@ -6,3 +6,5 @@ sealed class CreateSceneEvent extends Equatable {
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,3 +8,7 @@ sealed class CreateSceneState extends Equatable {
|
||||
}
|
||||
|
||||
final class CreateSceneInitial extends CreateSceneState {}
|
||||
|
||||
class CreateSceneLoading extends CreateSceneState {}
|
||||
|
||||
|
||||
|
50
lib/features/scene/helper/scene_helper.dart
Normal file
50
lib/features/scene/helper/scene_helper.dart
Normal file
@ -0,0 +1,50 @@
|
||||
import 'package:syncrow_app/features/devices/model/function_model.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
mixin SceneHelper {
|
||||
get lightBulbFunctions => null;
|
||||
|
||||
get wallSensorFunctions => null;
|
||||
|
||||
get acFunctions => null;
|
||||
|
||||
get doorLockFunctions => null;
|
||||
|
||||
get curtainFunctions => null;
|
||||
|
||||
get threeGangFunctions => null;
|
||||
|
||||
get gatewayFunctions => null;
|
||||
|
||||
getFunctionsWithIcons(
|
||||
{DeviceType? type, required List<FunctionModel> functions}) {
|
||||
switch (type) {
|
||||
case DeviceType.LightBulb:
|
||||
return lightBulbFunctions;
|
||||
case DeviceType.CeilingSensor:
|
||||
return ceilingSensorFunctions(functions);
|
||||
case DeviceType.WallSensor:
|
||||
return wallSensorFunctions;
|
||||
case DeviceType.AC:
|
||||
return acFunctions;
|
||||
case DeviceType.DoorLock:
|
||||
return doorLockFunctions;
|
||||
case DeviceType.Curtain:
|
||||
return curtainFunctions;
|
||||
case DeviceType.ThreeGang:
|
||||
return threeGangFunctions;
|
||||
case DeviceType.Gateway:
|
||||
return gatewayFunctions;
|
||||
default:
|
||||
return lightBulbFunctions;
|
||||
}
|
||||
}
|
||||
|
||||
ceilingSensorFunctions(List<FunctionModel> functions) {
|
||||
List<FunctionModel> temp = [];
|
||||
for (var item in functions) {
|
||||
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
}
|
82
lib/features/scene/view/device_functions_view.dart
Normal file
82
lib/features/scene/view/device_functions_view.dart
Normal file
@ -0,0 +1,82 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/scene/helper/scene_helper.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';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.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';
|
||||
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||
|
||||
class DeviceFunctionsView extends StatelessWidget with SceneHelper {
|
||||
const DeviceFunctionsView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final device = ModalRoute.of(context)?.settings.arguments as DeviceModel;
|
||||
// var functions = [];
|
||||
// if (device.functions.isNotEmpty) {
|
||||
// functions = getFunctionsWithIcons(
|
||||
// type: device.productType, functions: device.functions);
|
||||
// }
|
||||
|
||||
return DefaultScaffold(
|
||||
title: '${device.name} ${StringsManager.functions}',
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
child: BodyMedium(
|
||||
text: 'Save',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.secondaryColor.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
],
|
||||
leading: TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.textPrimaryColor.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
leadingWidth: 80,
|
||||
padding: EdgeInsets.zero,
|
||||
child: DefaultContainer(
|
||||
margin: const EdgeInsets.only(top: 24),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: device.functions.length,
|
||||
itemBuilder: (context, index) {
|
||||
final function = device.functions[index];
|
||||
return SceneListTile(
|
||||
assetPath: null,
|
||||
minLeadingWidth: 40,
|
||||
leadingWidget: Image.asset(
|
||||
Assets.assetsIconsLogo,
|
||||
width: 20,
|
||||
),
|
||||
titleWidget: BodyMedium(
|
||||
text: function.code ?? '',
|
||||
style: context.titleSmall.copyWith(
|
||||
color: ColorsManager.secondaryTextColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
trailingWidget: const Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 16,
|
||||
),
|
||||
onPressed: () {},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/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';
|
||||
@ -34,8 +36,10 @@ class SceneAddTasksView extends StatelessWidget {
|
||||
],
|
||||
child: Stack(
|
||||
children: [
|
||||
const SingleChildScrollView(
|
||||
child: Column(
|
||||
SingleChildScrollView(
|
||||
child: BlocProvider(
|
||||
create: (context) => CreateSceneBloc(),
|
||||
child: const Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
@ -54,6 +58,7 @@ class SceneAddTasksView extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
right: 40,
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/bottom_sheet_widget.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
@ -44,12 +46,16 @@ class ThenDefaultContainer extends StatelessWidget {
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
const LightDivider(),
|
||||
SceneListTile(
|
||||
BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||
builder: (context, state) {
|
||||
return SceneListTile(
|
||||
titleString: '+ Add Task',
|
||||
textAlign: TextAlign.center,
|
||||
onPressed: () => context.customBottomSheet(
|
||||
child: const CustomBottomSheetWidget(),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
@ -9,7 +10,7 @@ import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
@ -66,23 +67,17 @@ class SceneDevicesBody extends StatelessWidget {
|
||||
Widget _buildRoomTab(RoomModel room, BuildContext context) {
|
||||
return BlocBuilder<DeviceManagerBloc, DeviceManagerState>(
|
||||
builder: (context, state) {
|
||||
if (state is GetDevicesLoading) {
|
||||
if (state.loading && state.devices == null) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state is GetDevicesSuccess) {
|
||||
} else if (state.devices != null && state.devices!.isNotEmpty) {
|
||||
return ListView.builder(
|
||||
itemCount: state.devices?.length ?? 0,
|
||||
itemCount: state.devices!.length,
|
||||
itemBuilder: (context, index) {
|
||||
final device = state.devices![index];
|
||||
return DefaultContainer(
|
||||
child: SceneListTile(
|
||||
minLeadingWidth: 40,
|
||||
leadingWidget: Image.network(
|
||||
device.icon ?? '',
|
||||
errorBuilder: (context, error, stackTrace) => Image.asset(
|
||||
Assets.assetsIconsLogo,
|
||||
width: 20,
|
||||
),
|
||||
),
|
||||
leadingWidget: SvgPicture.asset(device.icon ?? ''),
|
||||
titleWidget: BodyMedium(
|
||||
text: device.name ?? '',
|
||||
style: context.titleSmall.copyWith(
|
||||
@ -93,20 +88,25 @@ class SceneDevicesBody extends StatelessWidget {
|
||||
),
|
||||
trailingWidget: const Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 16,
|
||||
weight: 0.2,
|
||||
),
|
||||
onPressed: () {
|
||||
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
Routes.deviceFunctionsRoute,
|
||||
arguments: device,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else if (state is GetDevicesError) {
|
||||
return Center(child: Text(state.error));
|
||||
}
|
||||
} else if (state.error != null) {
|
||||
return Center(child: Text(state.error!));
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ class DefaultScaffold extends StatelessWidget {
|
||||
this.appBar,
|
||||
this.bottomNavBar,
|
||||
this.padding,
|
||||
this.leading,
|
||||
this.leadingWidth,
|
||||
});
|
||||
|
||||
final Widget child;
|
||||
@ -23,6 +25,8 @@ class DefaultScaffold extends StatelessWidget {
|
||||
final PreferredSizeWidget? appBar;
|
||||
final Widget? bottomNavBar;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
final Widget? leading;
|
||||
final double? leadingWidth;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnnotatedRegion(
|
||||
@ -45,6 +49,8 @@ class DefaultScaffold extends StatelessWidget {
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
actions: actions,
|
||||
leading: leading,
|
||||
leadingWidth: leadingWidth,
|
||||
),
|
||||
body: Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
|
@ -13,6 +13,7 @@ import 'package:syncrow_app/features/menu/view/widgets/create_home/create_home_v
|
||||
import 'package:syncrow_app/features/menu/view/widgets/profile/profile_view.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart';
|
||||
import 'package:syncrow_app/features/scene/view/device_functions_view.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_add_tasks.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_control_devices.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_view.dart';
|
||||
@ -89,6 +90,11 @@ class Router {
|
||||
child: const SceneControlDevicesView(),
|
||||
),
|
||||
settings: settings);
|
||||
case Routes.deviceFunctionsRoute:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const DeviceFunctionsView(),
|
||||
settings: settings,
|
||||
);
|
||||
default:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => Scaffold(
|
||||
|
@ -19,4 +19,6 @@ class Routes {
|
||||
static const String createUnit = '/create-unit';
|
||||
static const String sceneTasksRoute = '/scene-tasks';
|
||||
static const String sceneControlDevicesRoute = '/scene-control-devices';
|
||||
static const String deviceFunctionsRoute = '/device-functions';
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import 'dart:async';
|
||||
import 'package:syncrow_app/features/devices/model/device_category_model.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/devices/model/functions.dart';
|
||||
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
|
||||
import 'package:syncrow_app/services/api/http_service.dart';
|
||||
|
||||
@ -27,20 +28,26 @@ class DevicesAPI {
|
||||
}
|
||||
|
||||
static Future<List<DevicesCategoryModel>> fetchGroups(String spaceId) async {
|
||||
Map<String, dynamic> params = {"homeId": spaceId, "pageSize": 100, "pageNo": 1};
|
||||
Map<String, dynamic> params = {
|
||||
"homeId": spaceId,
|
||||
"pageSize": 100,
|
||||
"pageNo": 1
|
||||
};
|
||||
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.groupBySpace.replaceAll("{spaceUuid}", spaceId),
|
||||
queryParameters: params,
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => DevicesCategoryModel.fromJsonList(json['groups']),
|
||||
expectedResponseModel: (json) =>
|
||||
DevicesCategoryModel.fromJsonList(json['groups']),
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.deviceFunctionsStatus.replaceAll('{deviceUuid}', deviceId),
|
||||
path: ApiEndpoints.deviceFunctionsStatus
|
||||
.replaceAll('{deviceUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@ -49,6 +56,19 @@ class DevicesAPI {
|
||||
return response;
|
||||
}
|
||||
|
||||
/// Get Device Functions
|
||||
static Future<FunctionsEntity> deviceFunctions(String deviceId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.deviceFunctions.replaceAll('{deviceUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
final functions = FunctionsEntity.fromJson(json);
|
||||
return functions;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<List<DeviceModel>> getDevicesByRoomId(String roomId) async {
|
||||
// print("Room ID: $roomId");
|
||||
final response = await _httpService.get(
|
||||
|
@ -39,4 +39,5 @@ class StringsManager {
|
||||
static const whenDeviceStatusChanges = 'When device status changes';
|
||||
static const whenUnusualActivityIsDetected =
|
||||
'Example: when an unusual activity is detected.';
|
||||
static const functions = "Functions";
|
||||
}
|
||||
|
Reference in New Issue
Block a user