mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
Merge branch 'dev' of https://github.com/SyncrowIOT/web into dev
This commit is contained in:
4
assets/icons/device_tag_ic.svg
Normal file
4
assets/icons/device_tag_ic.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="8" height="9" viewBox="0 0 8 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.13918 0.5H4.10294C4.0408 0.5 3.98117 0.524721 3.93722 0.568668L0.251783 4.25398C-0.0839278 4.58982 -0.0839278 5.13617 0.251783 5.47188L3.02848 8.24852C3.1906 8.41064 3.40686 8.49994 3.63734 8.5H3.6374C3.86794 8.5 4.0842 8.41064 4.24638 8.24846L7.9317 4.56308C7.97565 4.51914 8.00037 4.4595 8.00037 4.39736L8.00043 1.36113C8.00037 0.886312 7.61399 0.5 7.13918 0.5ZM7.53159 4.30031L3.91488 7.91702C3.84127 7.9907 3.74269 8.03122 3.6374 8.03122C3.53205 8.03122 3.43353 7.9907 3.35992 7.91708L0.583222 5.14045C0.43026 4.98748 0.43026 4.73845 0.583222 4.58542L4.19999 0.968775H7.13918C7.35556 0.968775 7.53165 1.14481 7.53165 1.36119L7.53159 4.30031Z" fill="#999999"/>
|
||||
<path d="M5.93455 1.8291C5.73782 1.8291 5.55288 1.90577 5.41377 2.04487C5.27466 2.18392 5.19806 2.36886 5.19806 2.56559C5.19806 2.76232 5.27466 2.94726 5.41377 3.08637C5.55288 3.22548 5.73782 3.30208 5.93455 3.30208C6.13121 3.30208 6.31616 3.22548 6.45527 3.08637C6.59437 2.94726 6.67098 2.76232 6.67098 2.56559C6.67098 2.36886 6.59437 2.18392 6.45533 2.04487C6.31622 1.90577 6.13128 1.8291 5.93455 1.8291ZM6.12383 2.75487C6.07329 2.80547 6.00602 2.83331 5.93455 2.83331C5.86301 2.83331 5.79581 2.80547 5.74527 2.75487C5.69467 2.70433 5.66683 2.63707 5.66683 2.56559C5.66683 2.49412 5.69467 2.42685 5.74527 2.37631C5.79581 2.32571 5.86307 2.29788 5.93455 2.29788C6.00602 2.29788 6.07323 2.32571 6.12383 2.37631C6.17443 2.42685 6.20226 2.49412 6.20226 2.56559C6.20226 2.63707 6.17437 2.70433 6.12383 2.75487Z" fill="#999999"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
@ -331,9 +331,13 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
|
||||
|
||||
try {
|
||||
final scaledValue = totalMinutes ~/ 6;
|
||||
await DevicesManagementApi().deviceControl(
|
||||
deviceId,
|
||||
Status(code: 'countdown_time', value: scaledValue),
|
||||
await _runDebounce(
|
||||
isBatch: false,
|
||||
deviceId: deviceId,
|
||||
code: 'countdown_time',
|
||||
value: scaledValue,
|
||||
oldValue: scaledValue,
|
||||
emit: emit,
|
||||
);
|
||||
_startCountdownTimer(emit);
|
||||
emit(currentState.copyWith(isTimerActive: timerActive));
|
||||
@ -342,9 +346,13 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
|
||||
emit(AcsFailedState(error: e.toString()));
|
||||
}
|
||||
} else {
|
||||
await DevicesManagementApi().deviceControl(
|
||||
deviceId,
|
||||
Status(code: 'countdown_time', value: 0),
|
||||
await _runDebounce(
|
||||
isBatch: false,
|
||||
deviceId: deviceId,
|
||||
code: 'countdown_time',
|
||||
value: 0,
|
||||
oldValue: 0,
|
||||
emit: emit,
|
||||
);
|
||||
_countdownTimer?.cancel();
|
||||
scheduledHours = 0;
|
||||
|
@ -0,0 +1,18 @@
|
||||
class DeviceSubSpace {
|
||||
String? id;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
String? subspaceName;
|
||||
bool? disabled;
|
||||
|
||||
DeviceSubSpace({this.id, this.createdAt, this.updatedAt, this.subspaceName, this.disabled});
|
||||
|
||||
DeviceSubSpace.fromJson(Map<String, dynamic> json) {
|
||||
id = json['uuid']?.toString() ?? '';
|
||||
createdAt = json['createdAt']?.toString() ?? '';
|
||||
updatedAt = json['updatedAt']?.toString() ?? '';
|
||||
subspaceName = json['subspaceName']?.toString() ?? '';
|
||||
subspaceName = json['subspaceName']?.toString() ?? '';
|
||||
disabled = json['disabled'] ?? false;
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
class DeviceTagModel {
|
||||
String? id;
|
||||
String? createdAt;
|
||||
String? updatedAt;
|
||||
String? name;
|
||||
|
||||
DeviceTagModel({
|
||||
this.id,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.name,
|
||||
});
|
||||
|
||||
DeviceTagModel.fromJson(Map<String, dynamic> json) {
|
||||
id = json['uuid']?.toString() ?? '';
|
||||
createdAt = json['createdAt']?.toString() ?? '';
|
||||
updatedAt = json['updatedAt']?.toString() ?? '';
|
||||
name = json['name']?.toString() ?? '';
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_community.model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_space_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_sub_space.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_subspace.model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_tag_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/room.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/ac/ac_function.dart';
|
||||
@ -78,38 +80,41 @@ class AllDevicesModel {
|
||||
int? batteryLevel;
|
||||
String? productName;
|
||||
List<DeviceSpaceModel>? spaces;
|
||||
List<DeviceTagModel>? deviceTags;
|
||||
DeviceSubSpace? deviceSubSpace;
|
||||
|
||||
AllDevicesModel({
|
||||
this.room,
|
||||
this.subspace,
|
||||
this.unit,
|
||||
this.community,
|
||||
this.productUuid,
|
||||
this.productType,
|
||||
this.permissionType,
|
||||
this.activeTime,
|
||||
this.category,
|
||||
this.categoryName,
|
||||
this.createTime,
|
||||
this.gatewayId,
|
||||
this.icon,
|
||||
this.ip,
|
||||
this.lat,
|
||||
this.localKey,
|
||||
this.lon,
|
||||
this.model,
|
||||
this.name,
|
||||
this.nodeId,
|
||||
this.online,
|
||||
this.ownerId,
|
||||
this.sub,
|
||||
this.timeZone,
|
||||
this.updateTime,
|
||||
this.uuid,
|
||||
this.batteryLevel,
|
||||
this.productName,
|
||||
this.spaces,
|
||||
});
|
||||
AllDevicesModel(
|
||||
{this.room,
|
||||
this.subspace,
|
||||
this.unit,
|
||||
this.community,
|
||||
this.productUuid,
|
||||
this.productType,
|
||||
this.permissionType,
|
||||
this.activeTime,
|
||||
this.category,
|
||||
this.categoryName,
|
||||
this.createTime,
|
||||
this.gatewayId,
|
||||
this.icon,
|
||||
this.ip,
|
||||
this.lat,
|
||||
this.localKey,
|
||||
this.lon,
|
||||
this.model,
|
||||
this.name,
|
||||
this.nodeId,
|
||||
this.online,
|
||||
this.ownerId,
|
||||
this.sub,
|
||||
this.timeZone,
|
||||
this.updateTime,
|
||||
this.uuid,
|
||||
this.batteryLevel,
|
||||
this.productName,
|
||||
this.spaces,
|
||||
this.deviceTags,
|
||||
this.deviceSubSpace});
|
||||
|
||||
AllDevicesModel.fromJson(Map<String, dynamic> json) {
|
||||
room = (json['room'] != null && (json['room'] is Map))
|
||||
@ -147,12 +152,15 @@ class AllDevicesModel {
|
||||
updateTime = int.tryParse(json['updateTime']?.toString() ?? '');
|
||||
uuid = json['uuid']?.toString();
|
||||
batteryLevel = int.tryParse(json['battery']?.toString() ?? '');
|
||||
|
||||
productName = json['productName']?.toString();
|
||||
deviceTags = json['deviceTag'] != null && json['deviceTag'] is List
|
||||
? (json['deviceTag'] as List).map((tag) => DeviceTagModel.fromJson(tag)).toList()
|
||||
: [];
|
||||
deviceSubSpace = json['subspace'] != null
|
||||
? DeviceSubSpace.fromJson(json['subspace'])
|
||||
: DeviceSubSpace(subspaceName: '');
|
||||
if (json['spaces'] != null && json['spaces'] is List) {
|
||||
spaces = (json['spaces'] as List)
|
||||
.map((space) => DeviceSpaceModel.fromJson(space))
|
||||
.toList();
|
||||
spaces = (json['spaces'] as List).map((space) => DeviceSpaceModel.fromJson(space)).toList();
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,8 +208,7 @@ SOS
|
||||
String tempIcon = '';
|
||||
if (type == DeviceType.LightBulb) {
|
||||
tempIcon = Assets.lightBulb;
|
||||
} else if (type == DeviceType.CeilingSensor ||
|
||||
type == DeviceType.WallSensor) {
|
||||
} else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
|
||||
tempIcon = Assets.sensors;
|
||||
} else if (type == DeviceType.AC) {
|
||||
tempIcon = Assets.ac;
|
||||
@ -248,76 +255,51 @@ SOS
|
||||
switch (productType) {
|
||||
case 'AC':
|
||||
return [
|
||||
SwitchFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ModeFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
TempSetFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
CurrentTempFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
LevelFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ChildLockFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
SwitchFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ModeFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
TempSetFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
CurrentTempFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
LevelFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ChildLockFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
];
|
||||
|
||||
case '1G':
|
||||
return [
|
||||
OneGangSwitchFunction(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
OneGangCountdownFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
OneGangCountdownFunction(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
];
|
||||
|
||||
case '2G':
|
||||
return [
|
||||
TwoGangSwitch1Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangSwitch2Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangCountdown1Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangCountdown2Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangCountdown1Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangCountdown2Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
];
|
||||
|
||||
case '3G':
|
||||
return [
|
||||
ThreeGangSwitch1Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch2Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch3Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown1Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown2Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown3Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch1Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch2Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch3Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown1Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown2Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown3Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
];
|
||||
case 'WPS':
|
||||
return [
|
||||
//IF Functions
|
||||
PresenceStateFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
CurrentDistanceFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
IlluminanceValueFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
PresenceTimeFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
PresenceStateFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
CurrentDistanceFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
IlluminanceValueFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
PresenceTimeFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
|
||||
//THEN Functions
|
||||
FarDetectionFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
MotionSensitivityFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
MotionLessSensitivityFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
IndicatorFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
NoOneTimeFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
|
||||
FarDetectionFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
MotionSensitivityFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
MotionLessSensitivityFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
IndicatorFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
NoOneTimeFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
];
|
||||
case 'GW':
|
||||
return [
|
||||
|
@ -62,9 +62,6 @@ class ToggleWidget extends StatelessWidget {
|
||||
)),
|
||||
if (showToggle)
|
||||
Container(
|
||||
height: 20,
|
||||
width: 35,
|
||||
padding: const EdgeInsets.only(right: 16, top: 10),
|
||||
child: CupertinoSwitch(
|
||||
value: value,
|
||||
activeColor: ColorsManager.dialogBlueTitle,
|
||||
|
@ -30,6 +30,7 @@ class FunctionBloc extends Bloc<FunctionBlocEvent, FunctionBlocState> {
|
||||
condition: event.functionData.condition ?? existingData.condition,
|
||||
);
|
||||
} else {
|
||||
functions.clear();
|
||||
functions.add(event.functionData);
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
TriggerSwitchTabsEvent event,
|
||||
Emitter<RoutineState> emit,
|
||||
) {
|
||||
emit(state.copyWith(
|
||||
routineTab: event.isRoutineTab, createRoutineView: false));
|
||||
emit(state.copyWith(routineTab: event.isRoutineTab, createRoutineView: false));
|
||||
add(ResetRoutineState());
|
||||
if (event.isRoutineTab) {
|
||||
add(const LoadScenes());
|
||||
@ -91,8 +90,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;
|
||||
@ -101,21 +100,18 @@ 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;
|
||||
@ -126,45 +122,42 @@ 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<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) {
|
||||
currentFunctions[j] = selectedFunction[i];
|
||||
if (!functionCode.contains(currentFunctions[j].functionCode)) {
|
||||
functionCode.add(currentFunctions[j].functionCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
|
||||
// List<DeviceFunctionData> currentFunctions =
|
||||
// List<DeviceFunctionData>.from(currentSelectedFunctions[event.uniqueCustomId] ?? []);
|
||||
|
||||
for (int i = 0; i < functionCode.length; i++) {
|
||||
selectedFunction
|
||||
.removeWhere((code) => code.functionCode == functionCode[i]);
|
||||
}
|
||||
// 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) {
|
||||
// currentFunctions[j] = selectedFunction[i];
|
||||
// if (!functionCode.contains(currentFunctions[j].functionCode)) {
|
||||
// functionCode.add(currentFunctions[j].functionCode);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
currentSelectedFunctions[event.uniqueCustomId] =
|
||||
List.from(currentFunctions)..addAll(selectedFunction);
|
||||
} else {
|
||||
currentSelectedFunctions[event.uniqueCustomId] =
|
||||
List.from(event.functions);
|
||||
}
|
||||
// for (int i = 0; i < functionCode.length; i++) {
|
||||
// selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]);
|
||||
// }
|
||||
|
||||
// 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));
|
||||
} catch (e) {
|
||||
@ -172,30 +165,24 @@ 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));
|
||||
List<ScenesModel> scenes = [];
|
||||
try {
|
||||
BuildContext context = NavigationService.navigatorKey.currentContext!;
|
||||
var createRoutineBloc = context.read<CreateRoutineBloc>();
|
||||
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||
if (createRoutineBloc.selectedSpaceId == '' &&
|
||||
createRoutineBloc.selectedCommunityId == '') {
|
||||
if (createRoutineBloc.selectedSpaceId == '' && createRoutineBloc.selectedCommunityId == '') {
|
||||
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||
for (var communityId in spaceBloc.state.selectedCommunities) {
|
||||
List<String> spacesList =
|
||||
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
|
||||
List<String> spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
|
||||
for (var spaceId in spacesList) {
|
||||
scenes.addAll(
|
||||
await SceneApi.getScenes(spaceId, communityId, projectUuid));
|
||||
scenes.addAll(await SceneApi.getScenes(spaceId, communityId, projectUuid));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scenes.addAll(await SceneApi.getScenes(
|
||||
createRoutineBloc.selectedSpaceId,
|
||||
createRoutineBloc.selectedCommunityId,
|
||||
projectUuid));
|
||||
createRoutineBloc.selectedSpaceId, createRoutineBloc.selectedCommunityId, projectUuid));
|
||||
}
|
||||
|
||||
emit(state.copyWith(
|
||||
@ -212,8 +199,7 @@ 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));
|
||||
List<ScenesModel> automations = [];
|
||||
final projectId = await ProjectManager.getProjectUUID() ?? '';
|
||||
@ -221,23 +207,17 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
BuildContext context = NavigationService.navigatorKey.currentContext!;
|
||||
var createRoutineBloc = context.read<CreateRoutineBloc>();
|
||||
try {
|
||||
|
||||
if (createRoutineBloc.selectedSpaceId == '' &&
|
||||
createRoutineBloc.selectedCommunityId == '') {
|
||||
if (createRoutineBloc.selectedSpaceId == '' && createRoutineBloc.selectedCommunityId == '') {
|
||||
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||
for (var communityId in spaceBloc.state.selectedCommunities) {
|
||||
List<String> spacesList =
|
||||
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
|
||||
List<String> spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
|
||||
for (var spaceId in spacesList) {
|
||||
automations.addAll(
|
||||
await SceneApi.getAutomation(spaceId, communityId, projectId));
|
||||
automations.addAll(await SceneApi.getAutomation(spaceId, communityId, projectId));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
automations.addAll(await SceneApi.getAutomation(
|
||||
createRoutineBloc.selectedSpaceId,
|
||||
createRoutineBloc.selectedCommunityId,
|
||||
projectId));
|
||||
createRoutineBloc.selectedSpaceId, createRoutineBloc.selectedCommunityId, projectId));
|
||||
}
|
||||
emit(state.copyWith(
|
||||
automations: automations,
|
||||
@ -253,16 +233,14 @@ 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));
|
||||
}
|
||||
|
||||
@ -276,8 +254,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
return actions.last['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)) {
|
||||
@ -290,8 +267,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
|
||||
if (_isLastActionDelay(state.thenItems)) {
|
||||
emit(state.copyWith(
|
||||
errorMessage:
|
||||
'A delay condition cannot be the only or the last action',
|
||||
errorMessage: 'A delay condition cannot be the only or the last action',
|
||||
isLoading: false,
|
||||
));
|
||||
return;
|
||||
@ -367,8 +343,7 @@ 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 {
|
||||
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
||||
@ -390,8 +365,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
|
||||
if (_isLastActionDelay(state.thenItems)) {
|
||||
emit(state.copyWith(
|
||||
errorMessage:
|
||||
'A delay condition cannot be the only or the last action',
|
||||
errorMessage: 'A delay condition cannot be the only or the last action',
|
||||
isLoading: false,
|
||||
));
|
||||
CustomSnackBar.redSnackBar('Cannot have delay as the last action');
|
||||
@ -482,8 +456,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
actions: actions,
|
||||
);
|
||||
|
||||
final result =
|
||||
await SceneApi.createAutomation(createAutomationModel, projectUuid);
|
||||
final result = await SceneApi.createAutomation(createAutomationModel, projectUuid);
|
||||
if (result['success']) {
|
||||
add(ResetRoutineState());
|
||||
add(const LoadAutomation());
|
||||
@ -504,21 +477,17 @@ 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);
|
||||
@ -529,8 +498,7 @@ 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -542,141 +510,138 @@ 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,
|
||||
));
|
||||
}
|
||||
|
||||
(
|
||||
List<Map<String, dynamic>>,
|
||||
List<Map<String, dynamic>>,
|
||||
Map<String, List<DeviceFunctionData>>
|
||||
) _createCardData(
|
||||
List<RoutineAction> actions,
|
||||
List<RoutineCondition>? conditions,
|
||||
Map<String, List<DeviceFunctionData>> currentFunctions,
|
||||
bool isTabToRun,
|
||||
) {
|
||||
final ifItems = isTabToRun
|
||||
? [
|
||||
{
|
||||
'entityId': 'tab_to_run',
|
||||
'uniqueCustomId': const Uuid().v4(),
|
||||
'deviceId': 'tab_to_run',
|
||||
'title': 'Tab to run',
|
||||
'productType': 'tab_to_run',
|
||||
'imagePath': Assets.tabToRun,
|
||||
}
|
||||
]
|
||||
: conditions?.map((condition) {
|
||||
final matchingDevice = state.devices.firstWhere(
|
||||
(device) => device.uuid == condition.entityId,
|
||||
orElse: () => AllDevicesModel(
|
||||
uuid: condition.entityId,
|
||||
name: condition.entityId,
|
||||
productType: condition.entityType,
|
||||
),
|
||||
);
|
||||
// (
|
||||
// List<Map<String, dynamic>>,
|
||||
// List<Map<String, dynamic>>,
|
||||
// Map<String, List<DeviceFunctionData>>
|
||||
// ) _createCardData(
|
||||
// List<RoutineAction> actions,
|
||||
// List<RoutineCondition>? conditions,
|
||||
// Map<String, List<DeviceFunctionData>> currentFunctions,
|
||||
// bool isTabToRun,
|
||||
// ) {
|
||||
// final ifItems = isTabToRun
|
||||
// ? [
|
||||
// {
|
||||
// 'entityId': 'tab_to_run',
|
||||
// 'uniqueCustomId': const Uuid().v4(),
|
||||
// 'deviceId': 'tab_to_run',
|
||||
// 'title': 'Tab to run',
|
||||
// 'productType': 'tab_to_run',
|
||||
// 'imagePath': Assets.tabToRun,
|
||||
// }
|
||||
// ]
|
||||
// : conditions?.map((condition) {
|
||||
// final matchingDevice = state.devices.firstWhere(
|
||||
// (device) => device.uuid == condition.entityId,
|
||||
// orElse: () => AllDevicesModel(
|
||||
// uuid: condition.entityId,
|
||||
// name: condition.entityId,
|
||||
// productType: condition.entityType,
|
||||
// ),
|
||||
// );
|
||||
|
||||
final cardData = {
|
||||
'entityId': condition.entityId,
|
||||
'uniqueCustomId': const Uuid().v4(),
|
||||
'deviceId': condition.entityId,
|
||||
'title': matchingDevice.name ?? condition.entityId,
|
||||
'productType': condition.entityType,
|
||||
'imagePath':
|
||||
matchingDevice.getDefaultIcon(condition.entityType),
|
||||
};
|
||||
// final cardData = {
|
||||
// 'entityId': condition.entityId,
|
||||
// 'uniqueCustomId': const Uuid().v4(),
|
||||
// 'deviceId': condition.entityId,
|
||||
// 'title': matchingDevice.name ?? condition.entityId,
|
||||
// 'productType': condition.entityType,
|
||||
// 'imagePath':
|
||||
// matchingDevice.getDefaultIcon(condition.entityType),
|
||||
// };
|
||||
|
||||
final functions = matchingDevice.functions;
|
||||
// final functions = matchingDevice.functions;
|
||||
|
||||
for (var function in functions) {
|
||||
if (function.code == condition.expr.statusCode) {
|
||||
currentFunctions[cardData['uniqueCustomId'] ?? ''] = [
|
||||
DeviceFunctionData(
|
||||
entityId: condition.entityId,
|
||||
functionCode: condition.expr.statusCode,
|
||||
value: condition.expr.statusValue,
|
||||
operationName: function.operationName,
|
||||
),
|
||||
];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// for (var function in functions) {
|
||||
// if (function.code == condition.expr.statusCode) {
|
||||
// currentFunctions[cardData['uniqueCustomId'] ?? ''] = [
|
||||
// DeviceFunctionData(
|
||||
// entityId: condition.entityId,
|
||||
// functionCode: condition.expr.statusCode,
|
||||
// value: condition.expr.statusValue,
|
||||
// operationName: function.operationName,
|
||||
// ),
|
||||
// ];
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
return cardData;
|
||||
}).toList() ??
|
||||
[];
|
||||
// return cardData;
|
||||
// }).toList() ??
|
||||
// [];
|
||||
|
||||
final thenItems = actions.map((action) {
|
||||
final matchingDevice = state.devices.firstWhere(
|
||||
(device) => device.uuid == action.entityId,
|
||||
orElse: () => AllDevicesModel(
|
||||
uuid: action.entityId,
|
||||
name: action.entityId,
|
||||
productType: action.productType,
|
||||
),
|
||||
);
|
||||
// final thenItems = actions.map((action) {
|
||||
// final matchingDevice = state.devices.firstWhere(
|
||||
// (device) => device.uuid == action.entityId,
|
||||
// orElse: () => AllDevicesModel(
|
||||
// uuid: action.entityId,
|
||||
// name: action.entityId,
|
||||
// productType: action.productType,
|
||||
// ),
|
||||
// );
|
||||
|
||||
final cardData = {
|
||||
'entityId': action.entityId,
|
||||
'uniqueCustomId': const Uuid().v4(),
|
||||
'deviceId':
|
||||
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||
'title': action.actionExecutor == 'delay'
|
||||
? 'Delay'
|
||||
: (matchingDevice.name ?? 'Device'),
|
||||
'productType': action.productType,
|
||||
'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
||||
};
|
||||
// final cardData = {
|
||||
// 'entityId': action.entityId,
|
||||
// 'uniqueCustomId': const Uuid().v4(),
|
||||
// 'deviceId':
|
||||
// action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||
// 'title': action.actionExecutor == 'delay'
|
||||
// ? 'Delay'
|
||||
// : (matchingDevice.name ?? 'Device'),
|
||||
// 'productType': action.productType,
|
||||
// 'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
||||
// };
|
||||
|
||||
final functions = matchingDevice.functions;
|
||||
// final functions = matchingDevice.functions;
|
||||
|
||||
if (action.executorProperty != null && action.actionExecutor != 'delay') {
|
||||
final functionCode = action.executorProperty!.functionCode;
|
||||
for (var function in functions) {
|
||||
if (function.code == functionCode) {
|
||||
currentFunctions[cardData['uniqueCustomId'] ?? ''] = [
|
||||
DeviceFunctionData(
|
||||
entityId: action.entityId,
|
||||
functionCode: functionCode ?? '',
|
||||
value: action.executorProperty!.functionValue,
|
||||
operationName: function.operationName,
|
||||
),
|
||||
];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (action.actionExecutor == 'delay') {
|
||||
final delayFunction = DelayFunction(
|
||||
deviceId: action.entityId,
|
||||
deviceName: 'Delay',
|
||||
);
|
||||
currentFunctions[cardData['uniqueCustomId'] ?? ''] = [
|
||||
DeviceFunctionData(
|
||||
entityId: action.entityId,
|
||||
functionCode: 'delay',
|
||||
value: action.executorProperty?.delaySeconds ?? 0,
|
||||
operationName: delayFunction.operationName,
|
||||
),
|
||||
];
|
||||
}
|
||||
// if (action.executorProperty != null && action.actionExecutor != 'delay') {
|
||||
// final functionCode = action.executorProperty!.functionCode;
|
||||
// for (var function in functions) {
|
||||
// if (function.code == functionCode) {
|
||||
// currentFunctions[cardData['uniqueCustomId'] ?? ''] = [
|
||||
// DeviceFunctionData(
|
||||
// entityId: action.entityId,
|
||||
// functionCode: functionCode ?? '',
|
||||
// value: action.executorProperty!.functionValue,
|
||||
// operationName: function.operationName,
|
||||
// ),
|
||||
// ];
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// } else if (action.actionExecutor == 'delay') {
|
||||
// final delayFunction = DelayFunction(
|
||||
// deviceId: action.entityId,
|
||||
// deviceName: 'Delay',
|
||||
// );
|
||||
// currentFunctions[cardData['uniqueCustomId'] ?? ''] = [
|
||||
// DeviceFunctionData(
|
||||
// entityId: action.entityId,
|
||||
// functionCode: 'delay',
|
||||
// value: action.executorProperty?.delaySeconds ?? 0,
|
||||
// operationName: delayFunction.operationName,
|
||||
// ),
|
||||
// ];
|
||||
// }
|
||||
|
||||
return cardData;
|
||||
}).toList();
|
||||
// return cardData;
|
||||
// }).toList();
|
||||
|
||||
return (thenItems, ifItems, currentFunctions);
|
||||
}
|
||||
// return (thenItems, ifItems, currentFunctions);
|
||||
// }
|
||||
|
||||
Future<void> _onGetSceneDetails(
|
||||
GetSceneDetails event, Emitter<RoutineState> emit) async {
|
||||
Future<void> _onGetSceneDetails(GetSceneDetails event, Emitter<RoutineState> emit) async {
|
||||
try {
|
||||
emit(state.copyWith(
|
||||
isLoading: true,
|
||||
@ -724,12 +689,10 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
if (!deviceCards.containsKey(deviceId)) {
|
||||
deviceCards[deviceId] = {
|
||||
'entityId': action.entityId,
|
||||
'deviceId':
|
||||
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||
'uniqueCustomId':
|
||||
action.type == 'automation' || action.actionExecutor == 'delay'
|
||||
? const Uuid().v4()
|
||||
: action.entityId,
|
||||
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||
'uniqueCustomId': action.type == 'automation' || action.actionExecutor == 'delay'
|
||||
? const Uuid().v4()
|
||||
: action.entityId,
|
||||
'title': action.actionExecutor == 'delay'
|
||||
? 'Delay'
|
||||
: action.type == 'automation'
|
||||
@ -764,16 +727,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
),
|
||||
);
|
||||
// emit(state.copyWith(automationActionExecutor: action.actionExecutor));
|
||||
} else if (action.executorProperty != null &&
|
||||
action.actionExecutor != 'delay') {
|
||||
if (!updatedFunctions.containsKey(uniqueCustomId)) {
|
||||
updatedFunctions[uniqueCustomId] = [];
|
||||
}
|
||||
} else if (action.executorProperty != null && action.actionExecutor != 'delay') {
|
||||
// if (!updatedFunctions.containsKey(uniqueCustomId)) {
|
||||
// updatedFunctions[uniqueCustomId] = [];
|
||||
// }
|
||||
final functions = matchingDevice?.functions;
|
||||
final functionCode = action.executorProperty?.functionCode;
|
||||
for (DeviceFunction function in functions ?? []) {
|
||||
if (function.code == functionCode) {
|
||||
updatedFunctions[uniqueCustomId]!.add(
|
||||
updatedFunctions[const Uuid().v4()]!.add(
|
||||
DeviceFunctionData(
|
||||
entityId: action.entityId,
|
||||
functionCode: functionCode ?? '',
|
||||
@ -837,8 +799,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onResetRoutineState(
|
||||
ResetRoutineState event, Emitter<RoutineState> emit) {
|
||||
FutureOr<void> _onResetRoutineState(ResetRoutineState event, Emitter<RoutineState> emit) {
|
||||
emit(state.copyWith(
|
||||
ifItems: [],
|
||||
thenItems: [],
|
||||
@ -861,6 +822,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
isUpdate: false,
|
||||
createRoutineView: false));
|
||||
}
|
||||
|
||||
FutureOr<void> _deleteScene(DeleteScene event, Emitter<RoutineState> emit) async {
|
||||
try {
|
||||
final projectId = await ProjectManager.getProjectUUID() ?? '';
|
||||
@ -900,7 +862,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FutureOr<void> _deleteAutomation(DeleteAutomation event, Emitter<RoutineState> emit) {
|
||||
// try {
|
||||
// emit(state.copyWith(isLoading: true));
|
||||
@ -915,8 +877,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
// }
|
||||
// }
|
||||
|
||||
FutureOr<void> _fetchDevices(
|
||||
FetchDevicesInRoutine event, Emitter<RoutineState> emit) async {
|
||||
FutureOr<void> _fetchDevices(FetchDevicesInRoutine event, Emitter<RoutineState> emit) async {
|
||||
emit(state.copyWith(isLoading: true));
|
||||
try {
|
||||
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||
@ -925,21 +886,17 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
var createRoutineBloc = context.read<CreateRoutineBloc>();
|
||||
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||
|
||||
if (createRoutineBloc.selectedSpaceId == '' &&
|
||||
createRoutineBloc.selectedCommunityId == '') {
|
||||
if (createRoutineBloc.selectedSpaceId == '' && createRoutineBloc.selectedCommunityId == '') {
|
||||
for (var communityId in spaceBloc.state.selectedCommunities) {
|
||||
List<String> spacesList =
|
||||
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
|
||||
List<String> spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
|
||||
for (var spaceId in spacesList) {
|
||||
devices.addAll(await DevicesManagementApi()
|
||||
.fetchDevices(communityId, spaceId, projectUuid));
|
||||
devices.addAll(
|
||||
await DevicesManagementApi().fetchDevices(communityId, spaceId, projectUuid));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
devices.addAll(await DevicesManagementApi().fetchDevices(
|
||||
createRoutineBloc.selectedCommunityId,
|
||||
createRoutineBloc.selectedSpaceId,
|
||||
projectUuid));
|
||||
createRoutineBloc.selectedCommunityId, createRoutineBloc.selectedSpaceId, projectUuid));
|
||||
}
|
||||
|
||||
emit(state.copyWith(isLoading: false, devices: devices));
|
||||
@ -948,8 +905,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onUpdateScene(
|
||||
UpdateScene event, Emitter<RoutineState> emit) async {
|
||||
FutureOr<void> _onUpdateScene(UpdateScene event, Emitter<RoutineState> emit) async {
|
||||
try {
|
||||
// Check if first action is delay
|
||||
// if (_isFirstActionDelay(state.thenItems)) {
|
||||
@ -963,8 +919,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
|
||||
if (_isLastActionDelay(state.thenItems)) {
|
||||
emit(state.copyWith(
|
||||
errorMessage:
|
||||
'A delay condition cannot be the only or the last action',
|
||||
errorMessage: 'A delay condition cannot be the only or the last action',
|
||||
isLoading: false,
|
||||
));
|
||||
return;
|
||||
@ -1017,8 +972,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
actions: actions,
|
||||
);
|
||||
|
||||
final result =
|
||||
await SceneApi.updateScene(createSceneModel, state.sceneId ?? '');
|
||||
final result = await SceneApi.updateScene(createSceneModel, state.sceneId ?? '');
|
||||
if (result['success']) {
|
||||
add(ResetRoutineState());
|
||||
add(const LoadScenes());
|
||||
@ -1037,8 +991,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onUpdateAutomation(
|
||||
UpdateAutomation event, Emitter<RoutineState> emit) async {
|
||||
FutureOr<void> _onUpdateAutomation(UpdateAutomation event, Emitter<RoutineState> emit) async {
|
||||
try {
|
||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
||||
emit(state.copyWith(
|
||||
@ -1253,15 +1206,13 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
),
|
||||
);
|
||||
|
||||
final deviceId = action.actionExecutor == 'delay'
|
||||
? '${action.entityId}_delay'
|
||||
: action.entityId;
|
||||
final deviceId =
|
||||
action.actionExecutor == 'delay' ? '${action.entityId}_delay' : action.entityId;
|
||||
|
||||
if (!deviceThenCards.containsKey(deviceId)) {
|
||||
deviceThenCards[deviceId] = {
|
||||
'entityId': action.entityId,
|
||||
'deviceId':
|
||||
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||
'uniqueCustomId': const Uuid().v4(),
|
||||
'title': action.actionExecutor == 'delay'
|
||||
? 'Delay'
|
||||
@ -1281,7 +1232,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
: action.type == 'automation'
|
||||
? 'automation'
|
||||
: 'action',
|
||||
'icon': action.icon ?? ''
|
||||
'icon': action.icon ?? '',
|
||||
};
|
||||
}
|
||||
|
||||
@ -1292,8 +1243,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
updatedFunctions[uniqueCustomId] = [];
|
||||
}
|
||||
|
||||
if (action.executorProperty != null &&
|
||||
action.actionExecutor != 'delay') {
|
||||
if (action.executorProperty != null && action.actionExecutor != 'delay') {
|
||||
final functions = matchingDevice.functions;
|
||||
final functionCode = action.executorProperty!.functionCode;
|
||||
for (var function in functions) {
|
||||
@ -1335,14 +1285,10 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
}
|
||||
}
|
||||
|
||||
final ifItems = deviceIfCards.values
|
||||
.where((card) => card['type'] == 'condition')
|
||||
.toList();
|
||||
final ifItems = deviceIfCards.values.where((card) => card['type'] == 'condition').toList();
|
||||
final thenItems = deviceThenCards.values
|
||||
.where((card) =>
|
||||
card['type'] == 'action' ||
|
||||
card['type'] == 'automation' ||
|
||||
card['type'] == 'scene')
|
||||
card['type'] == 'action' || card['type'] == 'automation' || card['type'] == 'scene')
|
||||
.toList();
|
||||
|
||||
emit(state.copyWith(
|
||||
@ -1364,8 +1310,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onSceneTrigger(
|
||||
SceneTrigger event, Emitter<RoutineState> emit) async {
|
||||
Future<void> _onSceneTrigger(SceneTrigger event, Emitter<RoutineState> emit) async {
|
||||
emit(state.copyWith(loadingSceneId: event.sceneId));
|
||||
|
||||
try {
|
||||
@ -1407,29 +1352,24 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
|
||||
if (success) {
|
||||
final updatedAutomations = await SceneApi.getAutomationByUnitId(
|
||||
event.automationStatusUpdate.spaceUuid,
|
||||
event.communityId,
|
||||
projectId);
|
||||
event.automationStatusUpdate.spaceUuid, event.communityId, projectId);
|
||||
|
||||
// Remove from loading set safely
|
||||
final updatedLoadingIds = {...state.loadingAutomationIds!}
|
||||
..remove(event.automationId);
|
||||
final updatedLoadingIds = {...state.loadingAutomationIds!}..remove(event.automationId);
|
||||
|
||||
emit(state.copyWith(
|
||||
automations: updatedAutomations,
|
||||
loadingAutomationIds: updatedLoadingIds,
|
||||
));
|
||||
} else {
|
||||
final updatedLoadingIds = {...state.loadingAutomationIds!}
|
||||
..remove(event.automationId);
|
||||
final updatedLoadingIds = {...state.loadingAutomationIds!}..remove(event.automationId);
|
||||
emit(state.copyWith(
|
||||
loadingAutomationIds: updatedLoadingIds,
|
||||
errorMessage: 'Update failed',
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
final updatedLoadingIds = {...state.loadingAutomationIds!}
|
||||
..remove(event.automationId);
|
||||
final updatedLoadingIds = {...state.loadingAutomationIds!}..remove(event.automationId);
|
||||
emit(state.copyWith(
|
||||
loadingAutomationIds: updatedLoadingIds,
|
||||
errorMessage: 'Update error: ${e.toString()}',
|
||||
|
@ -8,12 +8,12 @@ class DialogFooter extends StatelessWidget {
|
||||
final int? dialogWidth;
|
||||
|
||||
const DialogFooter({
|
||||
Key? key,
|
||||
super.key,
|
||||
required this.onCancel,
|
||||
required this.onConfirm,
|
||||
required this.isConfirmEnabled,
|
||||
this.dialogWidth,
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -28,21 +28,19 @@ class DialogFooter extends StatelessWidget {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildFooterButton(
|
||||
context,
|
||||
'Cancel',
|
||||
onCancel,
|
||||
),
|
||||
_buildFooterButton(
|
||||
context: context,
|
||||
text: 'Cancel',
|
||||
onTap: onCancel,
|
||||
),
|
||||
if (isConfirmEnabled) ...[
|
||||
Container(width: 1, height: 50, color: ColorsManager.greyColor),
|
||||
Expanded(
|
||||
child: _buildFooterButton(
|
||||
context,
|
||||
'Confirm',
|
||||
onConfirm,
|
||||
),
|
||||
_buildFooterButton(
|
||||
context: context,
|
||||
text: 'Confirm',
|
||||
onTap: onConfirm,
|
||||
textColor:
|
||||
isConfirmEnabled ? ColorsManager.primaryColorWithOpacity : Colors.red,
|
||||
),
|
||||
],
|
||||
],
|
||||
@ -50,24 +48,24 @@ class DialogFooter extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFooterButton(
|
||||
BuildContext context,
|
||||
String text,
|
||||
VoidCallback? onTap,
|
||||
) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: Text(
|
||||
text,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: text == 'Confirm'
|
||||
? ColorsManager.primaryColorWithOpacity
|
||||
: ColorsManager.textGray,
|
||||
),
|
||||
),
|
||||
Widget _buildFooterButton({
|
||||
required BuildContext context,
|
||||
required String text,
|
||||
required VoidCallback? onTap,
|
||||
Color? textColor,
|
||||
}) {
|
||||
return Expanded(
|
||||
child: TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: ColorsManager.primaryColorWithOpacity,
|
||||
disabledForegroundColor: ColorsManager.primaryColor,
|
||||
),
|
||||
onPressed: onTap,
|
||||
child: Text(
|
||||
text,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: textColor ?? ColorsManager.textGray,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -6,6 +6,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
||||
class DraggableCard extends StatelessWidget {
|
||||
@ -70,7 +71,7 @@ class DraggableCard extends StatelessWidget {
|
||||
child: Container(
|
||||
padding: padding ?? const EdgeInsets.all(16),
|
||||
width: 110,
|
||||
height: deviceFunctions.isEmpty ? 123 : null,
|
||||
height: deviceFunctions.isEmpty ? 160 : 170,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@ -78,6 +79,7 @@ class DraggableCard extends StatelessWidget {
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
height: 50,
|
||||
@ -101,19 +103,82 @@ class DraggableCard extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3),
|
||||
child: Text(
|
||||
deviceData['title'] ?? deviceData['name'] ?? title,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
child: Flexible(
|
||||
child: Text(
|
||||
deviceData['title'] ?? deviceData['name'] ?? title,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Visibility(
|
||||
visible: deviceData['tag'] != null && deviceData['tag'] != '',
|
||||
child: Row(
|
||||
spacing: 2,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 8, height: 8, child: SvgPicture.asset(Assets.deviceTagIcon)),
|
||||
Flexible(
|
||||
child: Text(
|
||||
deviceData['tag'] ?? '',
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: ColorsManager.lightGreyColor,
|
||||
fontSize: 9,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: deviceData['subSpace'] != null && deviceData['subSpace'] != '',
|
||||
child: const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: deviceData['subSpace'] != null && deviceData['subSpace'] != '',
|
||||
child: Row(
|
||||
spacing: 2,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 8,
|
||||
height: 8,
|
||||
child: SvgPicture.asset(Assets.spaceLocationIcon)),
|
||||
Flexible(
|
||||
child: Text(
|
||||
deviceData['subSpace'] ?? '',
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: ColorsManager.lightGreyColor,
|
||||
fontSize: 9,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (deviceFunctions.isNotEmpty)
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
if (deviceFunctions.isNotEmpty)
|
||||
...deviceFunctions.map((function) => Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@ -123,7 +188,7 @@ class DraggableCard extends StatelessWidget {
|
||||
'${function.operationName}: ${_formatFunctionValue(function)}',
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
fontSize: 9,
|
||||
color: ColorsManager.textGray,
|
||||
color: ColorsManager.lightGreyColor,
|
||||
height: 1.2,
|
||||
),
|
||||
maxLines: 2,
|
||||
|
@ -51,12 +51,12 @@ class _RoutineDevicesState extends State<RoutineDevices> {
|
||||
'productType': device.productType,
|
||||
'functions': device.functions,
|
||||
'uniqueCustomId': '',
|
||||
'tag': device.deviceTags!.isNotEmpty ? device.deviceTags![0].name : '',
|
||||
'subSpace': device.deviceSubSpace?.subspaceName ?? '',
|
||||
};
|
||||
|
||||
if (state.searchText != null && state.searchText!.isNotEmpty) {
|
||||
return device.name!
|
||||
.toLowerCase()
|
||||
.contains(state.searchText!.toLowerCase())
|
||||
return device.name!.toLowerCase().contains(state.searchText!.toLowerCase())
|
||||
? DraggableCard(
|
||||
imagePath: deviceData['imagePath'] as String,
|
||||
title: deviceData['title'] as String,
|
||||
|
@ -5,7 +5,6 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo
|
||||
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routines/helper/duration_format_helper.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/ac/ac_function.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/gang_switches/one_gang_switch/one_gang_switch.dart';
|
||||
@ -25,23 +24,21 @@ class OneGangSwitchHelper {
|
||||
required String uniqueCustomId,
|
||||
required bool removeComparetors,
|
||||
}) async {
|
||||
List<BaseSwitchFunction> oneGangFunctions =
|
||||
functions.whereType<BaseSwitchFunction>().toList();
|
||||
List<BaseSwitchFunction> oneGangFunctions = functions.whereType<BaseSwitchFunction>().toList();
|
||||
|
||||
return showDialog<Map<String, dynamic>?>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (_) => FunctionBloc()
|
||||
..add(InitializeFunctions(deviceSelectedFunctions ?? [])),
|
||||
create: (_) => FunctionBloc()..add(InitializeFunctions(deviceSelectedFunctions ?? [])),
|
||||
child: AlertDialog(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: BlocBuilder<FunctionBloc, FunctionBlocState>(
|
||||
builder: (context, state) {
|
||||
final selectedFunction = state.selectedFunction;
|
||||
final selectedOperationName = state.selectedOperationName;
|
||||
final selectedFunctionData = state.addedFunctions
|
||||
.firstWhere((f) => f.functionCode == selectedFunction,
|
||||
final selectedFunctionData =
|
||||
state.addedFunctions.firstWhere((f) => f.functionCode == selectedFunction,
|
||||
orElse: () => DeviceFunctionData(
|
||||
entityId: '',
|
||||
functionCode: selectedFunction ?? '',
|
||||
@ -88,12 +85,9 @@ class OneGangSwitchHelper {
|
||||
color: ColorsManager.textGray,
|
||||
),
|
||||
onTap: () {
|
||||
context
|
||||
.read<FunctionBloc>()
|
||||
.add(SelectFunction(
|
||||
context.read<FunctionBloc>().add(SelectFunction(
|
||||
functionCode: function.code,
|
||||
operationName:
|
||||
function.operationName,
|
||||
operationName: function.operationName,
|
||||
));
|
||||
},
|
||||
);
|
||||
@ -226,11 +220,11 @@ class OneGangSwitchHelper {
|
||||
selectedFunctionData,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildCountDownDisplay(context, initialValue, device, operationName,
|
||||
selectedFunctionData, selectCode),
|
||||
_buildCountDownDisplay(
|
||||
context, initialValue, device, operationName, selectedFunctionData, selectCode),
|
||||
const SizedBox(height: 20),
|
||||
_buildCountDownSlider(context, initialValue, device, operationName,
|
||||
selectedFunctionData, selectCode),
|
||||
_buildCountDownSlider(
|
||||
context, initialValue, device, operationName, selectedFunctionData, selectCode),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -271,8 +265,7 @@ class OneGangSwitchHelper {
|
||||
minHeight: 40.0,
|
||||
minWidth: 40.0,
|
||||
),
|
||||
isSelected:
|
||||
conditions.map((c) => c == (currentCondition ?? "==")).toList(),
|
||||
isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(),
|
||||
children: conditions.map((c) => Text(c)).toList(),
|
||||
);
|
||||
}
|
||||
@ -320,8 +313,7 @@ class OneGangSwitchHelper {
|
||||
value: (initialValue ?? 0).toDouble(),
|
||||
min: operationalValues.minValue?.toDouble() ?? 0.0,
|
||||
max: operationalValues.maxValue?.toDouble() ?? 0.0,
|
||||
divisions: (((operationalValues.maxValue ?? 0) -
|
||||
(operationalValues.minValue ?? 0)) /
|
||||
divisions: (((operationalValues.maxValue ?? 0) - (operationalValues.minValue ?? 0)) /
|
||||
(operationalValues.stepValue ?? 1))
|
||||
.round(),
|
||||
onChanged: (value) {
|
||||
@ -373,13 +365,9 @@ class OneGangSwitchHelper {
|
||||
style: context.textTheme.bodyMedium,
|
||||
),
|
||||
trailing: Icon(
|
||||
isSelected
|
||||
? Icons.radio_button_checked
|
||||
: Icons.radio_button_unchecked,
|
||||
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
|
||||
size: 24,
|
||||
color: isSelected
|
||||
? ColorsManager.primaryColorWithOpacity
|
||||
: ColorsManager.textGray,
|
||||
color: isSelected ? ColorsManager.primaryColorWithOpacity : ColorsManager.textGray,
|
||||
),
|
||||
onTap: () {
|
||||
if (!isSelected) {
|
||||
@ -391,8 +379,7 @@ class OneGangSwitchHelper {
|
||||
operationName: operationName,
|
||||
value: value.value,
|
||||
condition: selectedFunctionData?.condition,
|
||||
valueDescription:
|
||||
selectedFunctionData?.valueDescription,
|
||||
valueDescription: selectedFunctionData?.valueDescription,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||
import 'package:syncrow_web/pages/space_tree/view/space_tree_view.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||
@ -107,6 +109,11 @@ class _LoadedSpaceViewState extends State<LoadedSpaceView> {
|
||||
selectedSpaceUuid: widget.selectedSpace?.uuid ??
|
||||
widget.selectedCommunity?.uuid ??
|
||||
'',
|
||||
onCreateCommunity: (name, description) {
|
||||
context.read<SpaceManagementBloc>().add(
|
||||
CreateCommunityEvent(name, description, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
CommunityStructureArea(
|
||||
selectedCommunity: widget.selectedCommunity,
|
||||
|
@ -1,19 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_community/view/create_community_dialog.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class SidebarAddCommunityButton extends StatelessWidget {
|
||||
const SidebarAddCommunityButton({
|
||||
required this.existingCommunityNames,
|
||||
required this.onTap,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final List<String> existingCommunityNames;
|
||||
final void Function() onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -30,22 +26,9 @@ class SidebarAddCommunityButton extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
onPressed: () => _showCreateCommunityDialog(context),
|
||||
onPressed: onTap,
|
||||
icon: SvgPicture.asset(Assets.addIcon),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showCreateCommunityDialog(BuildContext context) => showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => CreateCommunityDialog(
|
||||
isEditMode: false,
|
||||
existingCommunityNames: existingCommunityNames,
|
||||
onCreateCommunity: (name, description) {
|
||||
context.read<SpaceManagementBloc>().add(
|
||||
CreateCommunityEvent(name, description, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -5,9 +5,12 @@ import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
class SidebarHeader extends StatelessWidget {
|
||||
const SidebarHeader({required this.existingCommunityNames, super.key});
|
||||
const SidebarHeader({
|
||||
required this.onAddCommunity,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final List<String> existingCommunityNames;
|
||||
final void Function() onAddCommunity;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -23,7 +26,9 @@ class SidebarHeader extends StatelessWidget {
|
||||
color: ColorsManager.blackColor,
|
||||
),
|
||||
),
|
||||
SidebarAddCommunityButton(existingCommunityNames: existingCommunityNames),
|
||||
SidebarAddCommunityButton(
|
||||
onTap: onAddCommunity,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -8,6 +8,7 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/community_tile.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/sidebar_header.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_tile_widget.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_community/view/create_community_dialog.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/structure_selector/bloc/center_body_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/structure_selector/bloc/center_body_event.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
@ -15,9 +16,11 @@ import 'package:syncrow_web/utils/style.dart';
|
||||
class SidebarWidget extends StatefulWidget {
|
||||
final List<CommunityModel> communities;
|
||||
final String? selectedSpaceUuid;
|
||||
final void Function(String name, String description) onCreateCommunity;
|
||||
|
||||
const SidebarWidget({
|
||||
required this.communities,
|
||||
required this.onCreateCommunity,
|
||||
this.selectedSpaceUuid,
|
||||
super.key,
|
||||
});
|
||||
@ -94,10 +97,7 @@ class _SidebarWidgetState extends State<SidebarWidget> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SidebarHeader(
|
||||
existingCommunityNames:
|
||||
widget.communities.map((community) => community.name).toList(),
|
||||
),
|
||||
SidebarHeader(onAddCommunity: _onAddCommunity),
|
||||
CustomSearchBar(
|
||||
onSearchChanged: (query) => setState(() => _searchQuery = query),
|
||||
),
|
||||
@ -179,4 +179,26 @@ class _SidebarWidgetState extends State<SidebarWidget> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onAddCommunity() => _selectedId?.isNotEmpty ?? true
|
||||
? _clearSelection()
|
||||
: _showCreateCommunityDialog();
|
||||
|
||||
void _clearSelection() {
|
||||
setState(() => _selectedId = '');
|
||||
context.read<SpaceManagementBloc>().add(
|
||||
NewCommunityEvent(communities: widget.communities),
|
||||
);
|
||||
}
|
||||
|
||||
void _showCreateCommunityDialog() {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => CreateCommunityDialog(
|
||||
isEditMode: false,
|
||||
existingCommunityNames: widget.communities.map((e) => e.name).toList(),
|
||||
onCreateCommunity: widget.onCreateCommunity,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_event.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_state.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/widgets/create_subspace_model_chips_box.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/widgets/create_subspace_model_footer_buttons.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
||||
class CreateSubSpaceModelDialog extends StatelessWidget {
|
||||
final bool isEdit;
|
||||
@ -14,211 +15,67 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
|
||||
final List<SubspaceTemplateModel>? existingSubSpaces;
|
||||
final void Function(List<SubspaceTemplateModel> newSubspaces)? onUpdate;
|
||||
|
||||
const CreateSubSpaceModelDialog(
|
||||
{Key? key,
|
||||
required this.isEdit,
|
||||
required this.dialogTitle,
|
||||
this.existingSubSpaces,
|
||||
this.onUpdate})
|
||||
: super(key: key);
|
||||
const CreateSubSpaceModelDialog({
|
||||
required this.isEdit,
|
||||
required this.dialogTitle,
|
||||
this.existingSubSpaces,
|
||||
this.onUpdate,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
final textController = TextEditingController();
|
||||
|
||||
return Dialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: BlocProvider(
|
||||
create: (_) {
|
||||
create: (context) {
|
||||
final bloc = SubSpaceModelBloc();
|
||||
if (existingSubSpaces != null) {
|
||||
for (var subSpace in existingSubSpaces!) {
|
||||
for (final subSpace in existingSubSpaces ?? []) {
|
||||
bloc.add(AddSubSpaceModel(subSpace));
|
||||
}
|
||||
}
|
||||
return bloc;
|
||||
},
|
||||
child: BlocBuilder<SubSpaceModelBloc, SubSpaceModelState>(
|
||||
builder: (context, state) {
|
||||
return Container(
|
||||
color: ColorsManager.whiteColors,
|
||||
child: SizedBox(
|
||||
width: screenWidth * 0.3,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
dialogTitle,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.headlineLarge
|
||||
?.copyWith(color: ColorsManager.blackColor),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
width: screenWidth * 0.35,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10.0, horizontal: 16.0),
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.boxColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Wrap(
|
||||
spacing: 8.0,
|
||||
runSpacing: 8.0,
|
||||
children: [
|
||||
...state.subSpaces.asMap().entries.map(
|
||||
(entry) {
|
||||
final index = entry.key;
|
||||
final subSpace = entry.value;
|
||||
|
||||
final lowerName =
|
||||
subSpace.subspaceName.toLowerCase();
|
||||
|
||||
final duplicateIndices = state.subSpaces
|
||||
.asMap()
|
||||
.entries
|
||||
.where((e) =>
|
||||
e.value.subspaceName.toLowerCase() ==
|
||||
lowerName)
|
||||
.map((e) => e.key)
|
||||
.toList();
|
||||
final isDuplicate =
|
||||
duplicateIndices.length > 1 &&
|
||||
duplicateIndices.indexOf(index) != 0;
|
||||
|
||||
return Chip(
|
||||
label: Text(subSpace.subspaceName,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
?.copyWith(
|
||||
color: ColorsManager.spaceColor,
|
||||
)),
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: BorderSide(
|
||||
color: isDuplicate
|
||||
? ColorsManager.red
|
||||
: ColorsManager.transparentColor,
|
||||
width: 0,
|
||||
),
|
||||
),
|
||||
deleteIcon: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: ColorsManager.lightGrayColor,
|
||||
width: 1.5,
|
||||
),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.close,
|
||||
size: 16,
|
||||
color: ColorsManager.lightGrayColor,
|
||||
),
|
||||
),
|
||||
onDeleted: () => context
|
||||
.read<SubSpaceModelBloc>()
|
||||
.add(RemoveSubSpaceModel(subSpace)),
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: TextField(
|
||||
controller: textController,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: state.subSpaces.isEmpty
|
||||
? 'Please enter the name'
|
||||
: null,
|
||||
hintStyle: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall!
|
||||
.copyWith(
|
||||
color: ColorsManager
|
||||
.lightGrayColor)),
|
||||
onSubmitted: (value) {
|
||||
if (value.trim().isNotEmpty) {
|
||||
context.read<SubSpaceModelBloc>().add(
|
||||
AddSubSpaceModel(
|
||||
SubspaceTemplateModel(
|
||||
subspaceName: value.trim(),
|
||||
disabled: false)));
|
||||
textController.clear();
|
||||
}
|
||||
},
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.copyWith(
|
||||
color: ColorsManager.blackColor)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (state.errorMessage.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16.0),
|
||||
child: Text(state.errorMessage,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
?.copyWith(
|
||||
color: ColorsManager.red,
|
||||
)),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CancelButton(
|
||||
label: 'Cancel',
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: DefaultButton(
|
||||
onPressed: (state.errorMessage.isNotEmpty)
|
||||
? null
|
||||
: () async {
|
||||
final subSpaces = context
|
||||
.read<SubSpaceModelBloc>()
|
||||
.state
|
||||
.subSpaces;
|
||||
Navigator.of(context).pop();
|
||||
if (onUpdate != null) {
|
||||
onUpdate!(subSpaces);
|
||||
}
|
||||
},
|
||||
backgroundColor: ColorsManager.secondaryColor,
|
||||
borderRadius: 10,
|
||||
foregroundColor: state.errorMessage.isNotEmpty
|
||||
? ColorsManager.whiteColorsWithOpacity
|
||||
: ColorsManager.whiteColors,
|
||||
child: const Text('OK'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
builder: (context, state) => Container(
|
||||
color: ColorsManager.whiteColors,
|
||||
width: screenWidth * 0.3,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
dialogTitle,
|
||||
style: context.textTheme.headlineLarge?.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
CreateSubspaceModelChipsBox(subSpaces: state.subSpaces),
|
||||
if (state.errorMessage.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16),
|
||||
child: Text(
|
||||
state.errorMessage,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: ColorsManager.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
},
|
||||
const SizedBox(height: 16),
|
||||
CreateSubspaceModelFooterButtons(
|
||||
onUpdate: onUpdate,
|
||||
errorMessage: state.errorMessage,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -0,0 +1,64 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/widgets/subspace_chip.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/widgets/subspaces_textfield.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class CreateSubspaceModelChipsBox extends StatelessWidget {
|
||||
const CreateSubspaceModelChipsBox({
|
||||
required this.subSpaces,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final List<SubspaceTemplateModel> subSpaces;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
|
||||
return Container(
|
||||
width: screenWidth * 0.35,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10,
|
||||
horizontal: 16,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.boxColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
alignment: WrapAlignment.start,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
...subSpaces.asMap().entries.map(
|
||||
(entry) {
|
||||
final index = entry.key;
|
||||
final subSpace = entry.value;
|
||||
|
||||
final lowerName = subSpace.subspaceName.toLowerCase();
|
||||
|
||||
final duplicateIndices = subSpaces
|
||||
.asMap()
|
||||
.entries
|
||||
.where((e) => e.value.subspaceName.toLowerCase() == lowerName)
|
||||
.map((e) => e.key)
|
||||
.toList();
|
||||
final isDuplicate = duplicateIndices.length > 1 &&
|
||||
duplicateIndices.indexOf(index) != 0;
|
||||
|
||||
return SubspaceChip(
|
||||
subSpace: subSpace,
|
||||
isDuplicate: isDuplicate,
|
||||
);
|
||||
},
|
||||
),
|
||||
SubspacesTextfield(
|
||||
hintText: subSpaces.isEmpty ? 'Please enter the name' : null,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class CreateSubspaceModelFooterButtons extends StatelessWidget {
|
||||
const CreateSubspaceModelFooterButtons({
|
||||
required this.onUpdate,
|
||||
required this.errorMessage,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final void Function(List<SubspaceTemplateModel> newSubspaces)? onUpdate;
|
||||
final String errorMessage;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CancelButton(
|
||||
label: 'Cancel',
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: DefaultButton(
|
||||
onPressed: errorMessage.isEmpty
|
||||
? () {
|
||||
Navigator.of(context).pop();
|
||||
if (onUpdate != null) {
|
||||
final subSpaces =
|
||||
context.read<SubSpaceModelBloc>().state.subSpaces;
|
||||
onUpdate!(subSpaces);
|
||||
}
|
||||
}
|
||||
: null,
|
||||
backgroundColor: ColorsManager.secondaryColor,
|
||||
borderRadius: 10,
|
||||
foregroundColor: errorMessage.isNotEmpty
|
||||
? ColorsManager.whiteColorsWithOpacity
|
||||
: ColorsManager.whiteColors,
|
||||
child: const Text('OK'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_event.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
||||
class SubspaceChip extends StatelessWidget {
|
||||
const SubspaceChip({
|
||||
required this.subSpace,
|
||||
required this.isDuplicate,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final SubspaceTemplateModel subSpace;
|
||||
final bool isDuplicate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Chip(
|
||||
label: Text(
|
||||
subSpace.subspaceName,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: isDuplicate ? ColorsManager.red : ColorsManager.spaceColor,
|
||||
),
|
||||
),
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: BorderSide(
|
||||
color: isDuplicate ? ColorsManager.red : ColorsManager.transparentColor,
|
||||
width: 0,
|
||||
),
|
||||
),
|
||||
deleteIcon: Container(
|
||||
padding: const EdgeInsetsDirectional.all(1),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: ColorsManager.lightGrayColor,
|
||||
width: 1.5,
|
||||
),
|
||||
),
|
||||
child: const FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: ColorsManager.lightGrayColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
onDeleted: () => context.read<SubSpaceModelBloc>().add(
|
||||
RemoveSubSpaceModel(subSpace),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_event.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
||||
class SubspacesTextfield extends StatefulWidget {
|
||||
const SubspacesTextfield({
|
||||
required this.hintText,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final String? hintText;
|
||||
|
||||
@override
|
||||
State<SubspacesTextfield> createState() => _SubspacesTextfieldState();
|
||||
}
|
||||
|
||||
class _SubspacesTextfieldState extends State<SubspacesTextfield> {
|
||||
late final TextEditingController _controller;
|
||||
@override
|
||||
void initState() {
|
||||
_controller = TextEditingController();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: 100,
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: widget.hintText,
|
||||
hintStyle: context.textTheme.bodySmall?.copyWith(
|
||||
color: ColorsManager.lightGrayColor,
|
||||
),
|
||||
),
|
||||
onSubmitted: (value) {
|
||||
final trimmedValue = value.trim();
|
||||
if (trimmedValue.isNotEmpty) {
|
||||
context.read<SubSpaceModelBloc>().add(
|
||||
AddSubSpaceModel(
|
||||
SubspaceTemplateModel(
|
||||
subspaceName: trimmedValue,
|
||||
disabled: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
_controller.clear();
|
||||
}
|
||||
},
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -13,12 +13,10 @@ class Assets {
|
||||
static const String rightLine = "assets/images/right_line.png";
|
||||
static const String google = "assets/images/google.svg";
|
||||
static const String facebook = "assets/images/facebook.svg";
|
||||
static const String invisiblePassword =
|
||||
"assets/images/Password_invisible.svg";
|
||||
static const String invisiblePassword = "assets/images/Password_invisible.svg";
|
||||
static const String visiblePassword = "assets/images/password_visible.svg";
|
||||
static const String accessIcon = "assets/images/access_icon.svg";
|
||||
static const String spaseManagementIcon =
|
||||
"assets/images/spase_management_icon.svg";
|
||||
static const String spaseManagementIcon = "assets/images/spase_management_icon.svg";
|
||||
static const String devicesIcon = "assets/images/devices_icon.svg";
|
||||
static const String moveinIcon = "assets/images/movein_icon.svg";
|
||||
static const String constructionIcon = "assets/images/construction_icon.svg";
|
||||
@ -31,15 +29,13 @@ class Assets {
|
||||
static const String emptyTable = "assets/images/empty_table.svg";
|
||||
|
||||
// General assets
|
||||
static const String motionlessDetection =
|
||||
"assets/icons/motionless_detection.svg";
|
||||
static const String motionlessDetection = "assets/icons/motionless_detection.svg";
|
||||
static const String acHeating = "assets/icons/ac_heating.svg";
|
||||
static const String acPowerOff = "assets/icons/ac_power_off.svg";
|
||||
static const String acFanMiddle = "assets/icons/ac_fan_middle.svg";
|
||||
static const String switchAlarmSound = "assets/icons/switch_alarm_sound.svg";
|
||||
static const String resetOff = "assets/icons/reset_off.svg";
|
||||
static const String sensitivityOperationIcon =
|
||||
"assets/icons/sesitivity_operation_icon.svg";
|
||||
static const String sensitivityOperationIcon = "assets/icons/sesitivity_operation_icon.svg";
|
||||
static const String motionDetection = "assets/icons/motion_detection.svg";
|
||||
static const String freezing = "assets/icons/freezing.svg";
|
||||
static const String indicator = "assets/icons/indicator.svg";
|
||||
@ -60,8 +56,7 @@ class Assets {
|
||||
static const String celsiusDegrees = "assets/icons/celsius_degrees.svg";
|
||||
static const String masterState = "assets/icons/master_state.svg";
|
||||
static const String acPower = "assets/icons/ac_power.svg";
|
||||
static const String farDetectionFunction =
|
||||
"assets/icons/far_detection_function.svg";
|
||||
static const String farDetectionFunction = "assets/icons/far_detection_function.svg";
|
||||
static const String nobodyTime = "assets/icons/nobody_time.svg";
|
||||
|
||||
// Automation functions
|
||||
@ -69,47 +64,33 @@ class Assets {
|
||||
"assets/icons/automation_functions/temp_password_unlock.svg";
|
||||
static const String doorlockNormalOpen =
|
||||
"assets/icons/automation_functions/doorlock_normal_open.svg";
|
||||
static const String doorbell =
|
||||
"assets/icons/automation_functions/doorbell.svg";
|
||||
static const String doorbell = "assets/icons/automation_functions/doorbell.svg";
|
||||
static const String remoteUnlockViaApp =
|
||||
"assets/icons/automation_functions/remote_unlock_via_app.svg";
|
||||
static const String doubleLock =
|
||||
"assets/icons/automation_functions/double_lock.svg";
|
||||
static const String selfTestResult =
|
||||
"assets/icons/automation_functions/self_test_result.svg";
|
||||
static const String lockAlarm =
|
||||
"assets/icons/automation_functions/lock_alarm.svg";
|
||||
static const String presenceState =
|
||||
"assets/icons/automation_functions/presence_state.svg";
|
||||
static const String currentTemp =
|
||||
"assets/icons/automation_functions/current_temp.svg";
|
||||
static const String presence =
|
||||
"assets/icons/automation_functions/presence.svg";
|
||||
static const String doubleLock = "assets/icons/automation_functions/double_lock.svg";
|
||||
static const String selfTestResult = "assets/icons/automation_functions/self_test_result.svg";
|
||||
static const String lockAlarm = "assets/icons/automation_functions/lock_alarm.svg";
|
||||
static const String presenceState = "assets/icons/automation_functions/presence_state.svg";
|
||||
static const String currentTemp = "assets/icons/automation_functions/current_temp.svg";
|
||||
static const String presence = "assets/icons/automation_functions/presence.svg";
|
||||
static const String residualElectricity =
|
||||
"assets/icons/automation_functions/residual_electricity.svg";
|
||||
static const String hijackAlarm =
|
||||
"assets/icons/automation_functions/hijack_alarm.svg";
|
||||
static const String passwordUnlock =
|
||||
"assets/icons/automation_functions/password_unlock.svg";
|
||||
static const String hijackAlarm = "assets/icons/automation_functions/hijack_alarm.svg";
|
||||
static const String passwordUnlock = "assets/icons/automation_functions/password_unlock.svg";
|
||||
static const String remoteUnlockRequest =
|
||||
"assets/icons/automation_functions/remote_unlock_req.svg";
|
||||
static const String cardUnlock =
|
||||
"assets/icons/automation_functions/card_unlock.svg";
|
||||
static const String cardUnlock = "assets/icons/automation_functions/card_unlock.svg";
|
||||
static const String motion = "assets/icons/automation_functions/motion.svg";
|
||||
static const String fingerprintUnlock =
|
||||
"assets/icons/automation_functions/fingerprint_unlock.svg";
|
||||
|
||||
// Presence Sensor Assets
|
||||
static const String sensorMotionIcon = "assets/icons/sensor_motion_ic.svg";
|
||||
static const String sensorPresenceIcon =
|
||||
"assets/icons/sensor_presence_ic.svg";
|
||||
static const String sensorPresenceIcon = "assets/icons/sensor_presence_ic.svg";
|
||||
static const String sensorVacantIcon = "assets/icons/sensor_vacant_ic.svg";
|
||||
static const String illuminanceRecordIcon =
|
||||
"assets/icons/illuminance_record_ic.svg";
|
||||
static const String presenceRecordIcon =
|
||||
"assets/icons/presence_record_ic.svg";
|
||||
static const String helpDescriptionIcon =
|
||||
"assets/icons/help_description_ic.svg";
|
||||
static const String illuminanceRecordIcon = "assets/icons/illuminance_record_ic.svg";
|
||||
static const String presenceRecordIcon = "assets/icons/presence_record_ic.svg";
|
||||
static const String helpDescriptionIcon = "assets/icons/help_description_ic.svg";
|
||||
|
||||
static const String lightPulp = "assets/icons/light_pulb.svg";
|
||||
static const String acDevice = "assets/icons/ac_device.svg";
|
||||
@ -159,12 +140,10 @@ class Assets {
|
||||
static const String unit = 'assets/icons/unit_icon.svg';
|
||||
static const String villa = 'assets/icons/villa_icon.svg';
|
||||
static const String iconEdit = 'assets/icons/icon_edit_icon.svg';
|
||||
static const String textFieldSearch =
|
||||
'assets/icons/textfield_search_icon.svg';
|
||||
static const String textFieldSearch = 'assets/icons/textfield_search_icon.svg';
|
||||
static const String roundedAddIcon = 'assets/icons/rounded_add_icon.svg';
|
||||
static const String addIcon = 'assets/icons/add_icon.svg';
|
||||
static const String smartThermostatIcon =
|
||||
'assets/icons/smart_thermostat_icon.svg';
|
||||
static const String smartThermostatIcon = 'assets/icons/smart_thermostat_icon.svg';
|
||||
static const String smartLightIcon = 'assets/icons/smart_light_icon.svg';
|
||||
static const String presenceSensor = 'assets/icons/presence_sensor.svg';
|
||||
static const String Gang3SwitchIcon = 'assets/icons/3_Gang_switch_icon.svg';
|
||||
@ -212,8 +191,7 @@ class Assets {
|
||||
//assets/icons/water_leak_normal.svg
|
||||
static const String waterLeakNormal = 'assets/icons/water_leak_normal.svg';
|
||||
//assets/icons/water_leak_detected.svg
|
||||
static const String waterLeakDetected =
|
||||
'assets/icons/water_leak_detected.svg';
|
||||
static const String waterLeakDetected = 'assets/icons/water_leak_detected.svg';
|
||||
|
||||
//assets/icons/automation_records.svg
|
||||
static const String automationRecords = 'assets/icons/automation_records.svg';
|
||||
@ -280,64 +258,40 @@ class Assets {
|
||||
static const String delay = 'assets/icons/routine/delay.svg';
|
||||
|
||||
// Assets for functions_icons
|
||||
static const String assetsSensitivityFunction =
|
||||
"assets/icons/functions_icons/sensitivity.svg";
|
||||
static const String assetsSensitivityFunction = "assets/icons/functions_icons/sensitivity.svg";
|
||||
static const String assetsSensitivityOperationIcon =
|
||||
"assets/icons/functions_icons/sesitivity_operation_icon.svg";
|
||||
static const String assetsAcPower =
|
||||
"assets/icons/functions_icons/ac_power.svg";
|
||||
static const String assetsAcPowerOFF =
|
||||
"assets/icons/functions_icons/ac_power_off.svg";
|
||||
static const String assetsChildLock =
|
||||
"assets/icons/functions_icons/child_lock.svg";
|
||||
static const String assetsFreezing =
|
||||
"assets/icons/functions_icons/freezing.svg";
|
||||
static const String assetsFanSpeed =
|
||||
"assets/icons/functions_icons/fan_speed.svg";
|
||||
static const String assetsAcCooling =
|
||||
"assets/icons/functions_icons/ac_cooling.svg";
|
||||
static const String assetsAcHeating =
|
||||
"assets/icons/functions_icons/ac_heating.svg";
|
||||
static const String assetsCelsiusDegrees =
|
||||
"assets/icons/functions_icons/celsius_degrees.svg";
|
||||
static const String assetsTempreture =
|
||||
"assets/icons/functions_icons/tempreture.svg";
|
||||
static const String assetsAcFanLow =
|
||||
"assets/icons/functions_icons/ac_fan_low.svg";
|
||||
static const String assetsAcFanMiddle =
|
||||
"assets/icons/functions_icons/ac_fan_middle.svg";
|
||||
static const String assetsAcFanHigh =
|
||||
"assets/icons/functions_icons/ac_fan_high.svg";
|
||||
static const String assetsAcFanAuto =
|
||||
"assets/icons/functions_icons/ac_fan_auto.svg";
|
||||
static const String assetsSceneChildLock =
|
||||
"assets/icons/functions_icons/scene_child_lock.svg";
|
||||
static const String assetsAcPower = "assets/icons/functions_icons/ac_power.svg";
|
||||
static const String assetsAcPowerOFF = "assets/icons/functions_icons/ac_power_off.svg";
|
||||
static const String assetsChildLock = "assets/icons/functions_icons/child_lock.svg";
|
||||
static const String assetsFreezing = "assets/icons/functions_icons/freezing.svg";
|
||||
static const String assetsFanSpeed = "assets/icons/functions_icons/fan_speed.svg";
|
||||
static const String assetsAcCooling = "assets/icons/functions_icons/ac_cooling.svg";
|
||||
static const String assetsAcHeating = "assets/icons/functions_icons/ac_heating.svg";
|
||||
static const String assetsCelsiusDegrees = "assets/icons/functions_icons/celsius_degrees.svg";
|
||||
static const String assetsTempreture = "assets/icons/functions_icons/tempreture.svg";
|
||||
static const String assetsAcFanLow = "assets/icons/functions_icons/ac_fan_low.svg";
|
||||
static const String assetsAcFanMiddle = "assets/icons/functions_icons/ac_fan_middle.svg";
|
||||
static const String assetsAcFanHigh = "assets/icons/functions_icons/ac_fan_high.svg";
|
||||
static const String assetsAcFanAuto = "assets/icons/functions_icons/ac_fan_auto.svg";
|
||||
static const String assetsSceneChildLock = "assets/icons/functions_icons/scene_child_lock.svg";
|
||||
static const String assetsSceneChildUnlock =
|
||||
"assets/icons/functions_icons/scene_child_unlock.svg";
|
||||
static const String assetsSceneRefresh =
|
||||
"assets/icons/functions_icons/scene_refresh.svg";
|
||||
static const String assetsLightCountdown =
|
||||
"assets/icons/functions_icons/light_countdown.svg";
|
||||
static const String assetsFarDetection =
|
||||
"assets/icons/functions_icons/far_detection.svg";
|
||||
static const String assetsSceneRefresh = "assets/icons/functions_icons/scene_refresh.svg";
|
||||
static const String assetsLightCountdown = "assets/icons/functions_icons/light_countdown.svg";
|
||||
static const String assetsFarDetection = "assets/icons/functions_icons/far_detection.svg";
|
||||
static const String assetsFarDetectionFunction =
|
||||
"assets/icons/functions_icons/far_detection_function.svg";
|
||||
static const String assetsIndicator =
|
||||
"assets/icons/functions_icons/indicator.svg";
|
||||
static const String assetsMotionDetection =
|
||||
"assets/icons/functions_icons/motion_detection.svg";
|
||||
static const String assetsIndicator = "assets/icons/functions_icons/indicator.svg";
|
||||
static const String assetsMotionDetection = "assets/icons/functions_icons/motion_detection.svg";
|
||||
static const String assetsMotionlessDetection =
|
||||
"assets/icons/functions_icons/motionless_detection.svg";
|
||||
static const String assetsNobodyTime =
|
||||
"assets/icons/functions_icons/nobody_time.svg";
|
||||
static const String assetsFactoryReset =
|
||||
"assets/icons/functions_icons/factory_reset.svg";
|
||||
static const String assetsMasterState =
|
||||
"assets/icons/functions_icons/master_state.svg";
|
||||
static const String assetsNobodyTime = "assets/icons/functions_icons/nobody_time.svg";
|
||||
static const String assetsFactoryReset = "assets/icons/functions_icons/factory_reset.svg";
|
||||
static const String assetsMasterState = "assets/icons/functions_icons/master_state.svg";
|
||||
static const String assetsSwitchAlarmSound =
|
||||
"assets/icons/functions_icons/switch_alarm_sound.svg";
|
||||
static const String assetsResetOff =
|
||||
"assets/icons/functions_icons/reset_off.svg";
|
||||
static const String assetsResetOff = "assets/icons/functions_icons/reset_off.svg";
|
||||
|
||||
// Assets for automation_functions
|
||||
static const String assetsCardUnlock =
|
||||
@ -368,8 +322,7 @@ class Assets {
|
||||
"assets/icons/functions_icons/automation_functions/self_test_result.svg";
|
||||
static const String assetsPresence =
|
||||
"assets/icons/functions_icons/automation_functions/presence.svg";
|
||||
static const String assetsMotion =
|
||||
"assets/icons/functions_icons/automation_functions/motion.svg";
|
||||
static const String assetsMotion = "assets/icons/functions_icons/automation_functions/motion.svg";
|
||||
static const String assetsCurrentTemp =
|
||||
"assets/icons/functions_icons/automation_functions/current_temp.svg";
|
||||
static const String assetsPresenceState =
|
||||
@ -381,16 +334,12 @@ class Assets {
|
||||
static const String activeUser = 'assets/icons/active_user.svg';
|
||||
static const String deActiveUser = 'assets/icons/deactive_user.svg';
|
||||
static const String invitedIcon = 'assets/icons/invited_icon.svg';
|
||||
static const String rectangleCheckBox =
|
||||
'assets/icons/rectangle_check_box.png';
|
||||
static const String rectangleCheckBox = 'assets/icons/rectangle_check_box.png';
|
||||
static const String CheckBoxChecked = 'assets/icons/box_checked.png';
|
||||
static const String emptyBox = 'assets/icons/empty_box.png';
|
||||
static const String completeProcessIcon =
|
||||
'assets/icons/compleate_process_icon.svg';
|
||||
static const String currentProcessIcon =
|
||||
'assets/icons/current_process_icon.svg';
|
||||
static const String uncomplete_ProcessIcon =
|
||||
'assets/icons/uncompleate_process_icon.svg';
|
||||
static const String completeProcessIcon = 'assets/icons/compleate_process_icon.svg';
|
||||
static const String currentProcessIcon = 'assets/icons/current_process_icon.svg';
|
||||
static const String uncomplete_ProcessIcon = 'assets/icons/uncompleate_process_icon.svg';
|
||||
static const String wrongProcessIcon = 'assets/icons/wrong_process_icon.svg';
|
||||
static const String arrowForward = 'assets/icons/arrow_forward.svg';
|
||||
static const String arrowDown = 'assets/icons/arrow_down.svg';
|
||||
@ -403,17 +352,14 @@ class Assets {
|
||||
static const String duplicate = 'assets/icons/duplicate.svg';
|
||||
static const String spaceDelete = 'assets/icons/space_delete.svg';
|
||||
|
||||
static const String deleteSpaceLinkIcon =
|
||||
'assets/icons/delete_space_link_icon.svg';
|
||||
static const String deleteSpaceLinkIcon = 'assets/icons/delete_space_link_icon.svg';
|
||||
static const String spaceLinkIcon = 'assets/icons/space_link_icon.svg';
|
||||
static const String successIcon = 'assets/icons/success_icon.svg';
|
||||
static const String spaceLocationIcon = 'assets/icons/spaseLocationIcon.svg';
|
||||
static const String scenesPlayIcon = 'assets/icons/scenesPlayIcon.png';
|
||||
static const String scenesPlayIconCheck =
|
||||
'assets/icons/scenesPlayIconCheck.png';
|
||||
static const String scenesPlayIconCheck = 'assets/icons/scenesPlayIconCheck.png';
|
||||
static const String presenceStateIcon = 'assets/icons/presence_state.svg';
|
||||
static const String currentDistanceIcon =
|
||||
'assets/icons/current_distance_icon.svg';
|
||||
static const String currentDistanceIcon = 'assets/icons/current_distance_icon.svg';
|
||||
|
||||
static const String farDetectionIcon = 'assets/icons/far_detection_icon.svg';
|
||||
static const String motionDetectionSensitivityIcon =
|
||||
@ -423,11 +369,11 @@ class Assets {
|
||||
'assets/icons/motionless_detection_sensitivity_icon.svg';
|
||||
|
||||
static const String IndicatorIcon = 'assets/icons/Indicator_icon.svg';
|
||||
static const String motionDetectionSensitivityValueIcon = 'assets/icons/motion_detection_sensitivity_value_icon.svg';
|
||||
static const String presenceTimeIcon = 'assets/icons/presence_time_icon.svg';
|
||||
static const String IlluminanceIcon = 'assets/icons/Illuminance_icon.svg';
|
||||
static const String gear = 'assets/icons/gear.svg';
|
||||
static const String activeBell='assets/icons/active_bell.svg';
|
||||
|
||||
|
||||
static const String motionDetectionSensitivityValueIcon =
|
||||
'assets/icons/motion_detection_sensitivity_value_icon.svg';
|
||||
static const String presenceTimeIcon = 'assets/icons/presence_time_icon.svg';
|
||||
static const String IlluminanceIcon = 'assets/icons/Illuminance_icon.svg';
|
||||
static const String gear = 'assets/icons/gear.svg';
|
||||
static const String activeBell = 'assets/icons/active_bell.svg';
|
||||
static const String deviceTagIcon = 'assets/icons/device_tag_ic.svg';
|
||||
}
|
||||
|
Reference in New Issue
Block a user