mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-15 17:47:53 +00:00
Merge branch 'dev' of https://github.com/SyncrowIOT/web into feature/space-management
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||
|
||||
@ -14,6 +14,10 @@ class DeviceManagementBloc
|
||||
int _offlineCount = 0;
|
||||
int _lowBatteryCount = 0;
|
||||
List<AllDevicesModel> _selectedDevices = [];
|
||||
List<AllDevicesModel> _filteredDevices = [];
|
||||
String currentProductName = '';
|
||||
String? currentCommunity;
|
||||
String? currentUnitName;
|
||||
|
||||
DeviceManagementBloc() : super(DeviceManagementInitial()) {
|
||||
on<FetchDevices>(_onFetchDevices);
|
||||
@ -21,6 +25,9 @@ class DeviceManagementBloc
|
||||
on<SelectedFilterChanged>(_onSelectedFilterChanged);
|
||||
on<SearchDevices>(_onSearchDevices);
|
||||
on<SelectDevice>(_onSelectDevice);
|
||||
on<ResetFilters>(_onResetFilters);
|
||||
on<ResetSelectedDevices>(_onResetSelectedDevices);
|
||||
on<UpdateSelection>(_onUpdateSelection);
|
||||
}
|
||||
|
||||
Future<void> _onFetchDevices(
|
||||
@ -28,14 +35,18 @@ class DeviceManagementBloc
|
||||
emit(DeviceManagementLoading());
|
||||
try {
|
||||
final devices = await DevicesManagementApi().fetchDevices();
|
||||
_selectedDevices.clear();
|
||||
_devices = devices;
|
||||
_filteredDevices = devices;
|
||||
_calculateDeviceCounts();
|
||||
emit(DeviceManagementLoaded(
|
||||
devices: devices,
|
||||
selectedIndex: _selectedIndex,
|
||||
selectedIndex: 0,
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
selectedDevice: null,
|
||||
isControlButtonEnabled: false,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(DeviceManagementInitial());
|
||||
@ -43,9 +54,9 @@ class DeviceManagementBloc
|
||||
}
|
||||
|
||||
void _onFilterDevices(
|
||||
FilterDevices event, Emitter<DeviceManagementState> emit) {
|
||||
FilterDevices event, Emitter<DeviceManagementState> emit) async {
|
||||
if (_devices.isNotEmpty) {
|
||||
final filteredDevices = _devices.where((device) {
|
||||
_filteredDevices = List.from(_devices.where((device) {
|
||||
switch (event.filter) {
|
||||
case 'Online':
|
||||
return device.online == true;
|
||||
@ -56,13 +67,64 @@ class DeviceManagementBloc
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}).toList();
|
||||
}).toList());
|
||||
|
||||
emit(DeviceManagementFiltered(
|
||||
filteredDevices: filteredDevices,
|
||||
filteredDevices: _filteredDevices,
|
||||
selectedIndex: _selectedIndex,
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
selectedDevice: _selectedDevices.isNotEmpty ? _selectedDevices : null,
|
||||
isControlButtonEnabled: _selectedDevices.isNotEmpty,
|
||||
));
|
||||
|
||||
if (currentProductName.isNotEmpty) {
|
||||
add(SearchDevices(productName: currentProductName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onResetFilters(
|
||||
ResetFilters event, Emitter<DeviceManagementState> emit) async {
|
||||
currentProductName = '';
|
||||
_selectedDevices.clear();
|
||||
_filteredDevices = List.from(_devices);
|
||||
_selectedIndex = 0;
|
||||
emit(DeviceManagementLoaded(
|
||||
devices: _devices,
|
||||
selectedIndex: 0,
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
selectedDevice: null,
|
||||
isControlButtonEnabled: false,
|
||||
));
|
||||
}
|
||||
|
||||
void _onResetSelectedDevices(
|
||||
ResetSelectedDevices event, Emitter<DeviceManagementState> emit) {
|
||||
_selectedDevices.clear();
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
emit(DeviceManagementLoaded(
|
||||
devices: _devices,
|
||||
selectedIndex: _selectedIndex,
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
selectedDevice: null,
|
||||
isControlButtonEnabled: false,
|
||||
));
|
||||
} else if (state is DeviceManagementFiltered) {
|
||||
emit(DeviceManagementFiltered(
|
||||
filteredDevices: (state as DeviceManagementFiltered).filteredDevices,
|
||||
selectedIndex: _selectedIndex,
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
selectedDevice: null,
|
||||
isControlButtonEnabled: false,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -75,13 +137,18 @@ class DeviceManagementBloc
|
||||
|
||||
void _onSelectDevice(
|
||||
SelectDevice event, Emitter<DeviceManagementState> emit) {
|
||||
if (_selectedDevices.contains(event.selectedDevice)) {
|
||||
_selectedDevices.remove(event.selectedDevice);
|
||||
final selectedUuid = event.selectedDevice.uuid;
|
||||
|
||||
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
|
||||
_selectedDevices.removeWhere((device) => device.uuid == selectedUuid);
|
||||
} else {
|
||||
_selectedDevices.add(event.selectedDevice);
|
||||
}
|
||||
|
||||
bool isControlButtonEnabled = _selectedDevices.length == 1;
|
||||
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
|
||||
|
||||
bool isControlButtonEnabled =
|
||||
_checkIfControlButtonEnabled(clonedSelectedDevices);
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
emit(DeviceManagementLoaded(
|
||||
@ -90,7 +157,9 @@ class DeviceManagementBloc
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
selectedDevice: isControlButtonEnabled ? _selectedDevices.first : null,
|
||||
selectedDevice:
|
||||
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
||||
isControlButtonEnabled: isControlButtonEnabled,
|
||||
));
|
||||
} else if (state is DeviceManagementFiltered) {
|
||||
emit(DeviceManagementFiltered(
|
||||
@ -99,11 +168,66 @@ class DeviceManagementBloc
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
selectedDevice: isControlButtonEnabled ? _selectedDevices.first : null,
|
||||
selectedDevice:
|
||||
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
||||
isControlButtonEnabled: isControlButtonEnabled,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void _onUpdateSelection(
|
||||
UpdateSelection event, Emitter<DeviceManagementState> emit) {
|
||||
List<AllDevicesModel> selectedDevices = [];
|
||||
List<AllDevicesModel> devicesToSelectFrom = [];
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
devicesToSelectFrom = (state as DeviceManagementLoaded).devices;
|
||||
} else if (state is DeviceManagementFiltered) {
|
||||
devicesToSelectFrom = (state as DeviceManagementFiltered).filteredDevices;
|
||||
}
|
||||
|
||||
for (int i = 0; i < event.selectedRows.length; i++) {
|
||||
if (event.selectedRows[i]) {
|
||||
selectedDevices.add(devicesToSelectFrom[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
final loadedState = state as DeviceManagementLoaded;
|
||||
emit(DeviceManagementLoaded(
|
||||
devices: loadedState.devices,
|
||||
selectedIndex: loadedState.selectedIndex,
|
||||
onlineCount: loadedState.onlineCount,
|
||||
offlineCount: loadedState.offlineCount,
|
||||
lowBatteryCount: loadedState.lowBatteryCount,
|
||||
selectedDevice: selectedDevices,
|
||||
isControlButtonEnabled: _checkIfControlButtonEnabled(selectedDevices),
|
||||
));
|
||||
} else if (state is DeviceManagementFiltered) {
|
||||
final filteredState = state as DeviceManagementFiltered;
|
||||
emit(DeviceManagementFiltered(
|
||||
filteredDevices: filteredState.filteredDevices,
|
||||
selectedIndex: filteredState.selectedIndex,
|
||||
onlineCount: filteredState.onlineCount,
|
||||
offlineCount: filteredState.offlineCount,
|
||||
lowBatteryCount: filteredState.lowBatteryCount,
|
||||
selectedDevice: selectedDevices,
|
||||
isControlButtonEnabled: _checkIfControlButtonEnabled(selectedDevices),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
|
||||
if (selectedDevices.length > 1) {
|
||||
final productTypes =
|
||||
selectedDevices.map((device) => device.productType).toSet();
|
||||
return productTypes.length == 1;
|
||||
} else if (selectedDevices.length == 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void _calculateDeviceCounts() {
|
||||
_onlineCount = _devices.where((device) => device.online == true).length;
|
||||
_offlineCount = _devices.where((device) => device.online == false).length;
|
||||
@ -128,27 +252,61 @@ class DeviceManagementBloc
|
||||
|
||||
void _onSearchDevices(
|
||||
SearchDevices event, Emitter<DeviceManagementState> emit) {
|
||||
if (_devices.isNotEmpty) {
|
||||
final filteredDevices = _devices.where((device) {
|
||||
if ((event.community == null || event.community!.isEmpty) &&
|
||||
(event.unitName == null || event.unitName!.isEmpty) &&
|
||||
(event.productName == null || event.productName!.isEmpty)) {
|
||||
currentProductName = '';
|
||||
if (state is DeviceManagementFiltered) {
|
||||
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.productName == currentProductName &&
|
||||
event.community == currentCommunity &&
|
||||
event.unitName == currentUnitName &&
|
||||
event.searchField) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentProductName = event.productName ?? '';
|
||||
currentCommunity = event.community;
|
||||
currentUnitName = event.unitName;
|
||||
|
||||
List<AllDevicesModel> devicesToSearch = _filteredDevices;
|
||||
|
||||
if (devicesToSearch.isNotEmpty) {
|
||||
final filteredDevices = devicesToSearch.where((device) {
|
||||
final matchesCommunity = event.community == null ||
|
||||
event.community!.isEmpty ||
|
||||
(device.room?.name
|
||||
(device.community?.name
|
||||
?.toLowerCase()
|
||||
.contains(event.community!.toLowerCase()) ??
|
||||
false);
|
||||
final matchesUnit = event.unitName == null ||
|
||||
event.unitName!.isEmpty ||
|
||||
(device.unit?.name
|
||||
?.toLowerCase()
|
||||
.contains(event.unitName!.toLowerCase()) ??
|
||||
false);
|
||||
(device.spaces != null &&
|
||||
device.spaces!.isNotEmpty &&
|
||||
device.spaces![0].spaceName
|
||||
!.toLowerCase()
|
||||
.contains(event.unitName!.toLowerCase()));
|
||||
final matchesProductName = event.productName == null ||
|
||||
event.productName!.isEmpty ||
|
||||
(device.name
|
||||
?.toLowerCase()
|
||||
.contains(event.productName!.toLowerCase()) ??
|
||||
false);
|
||||
return matchesCommunity && matchesUnit && matchesProductName;
|
||||
final matchesDeviceName = event.productName == null ||
|
||||
event.productName!.isEmpty ||
|
||||
(device.categoryName
|
||||
?.toLowerCase()
|
||||
.contains(event.productName!.toLowerCase()) ??
|
||||
false);
|
||||
|
||||
return matchesCommunity &&
|
||||
matchesUnit &&
|
||||
(matchesProductName || matchesDeviceName);
|
||||
}).toList();
|
||||
|
||||
emit(DeviceManagementFiltered(
|
||||
@ -157,6 +315,8 @@ class DeviceManagementBloc
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
selectedDevice: null,
|
||||
isControlButtonEnabled: false,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -31,11 +31,13 @@ class SearchDevices extends DeviceManagementEvent {
|
||||
final String? community;
|
||||
final String? unitName;
|
||||
final String? productName;
|
||||
final bool searchField;
|
||||
|
||||
const SearchDevices({
|
||||
this.community,
|
||||
this.unitName,
|
||||
this.productName,
|
||||
this.searchField = false,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -50,3 +52,13 @@ class SelectDevice extends DeviceManagementEvent {
|
||||
@override
|
||||
List<Object?> get props => [selectedDevice];
|
||||
}
|
||||
|
||||
class ResetFilters extends DeviceManagementEvent {}
|
||||
|
||||
class ResetSelectedDevices extends DeviceManagementEvent {}
|
||||
|
||||
class UpdateSelection extends DeviceManagementEvent {
|
||||
final List<bool> selectedRows;
|
||||
|
||||
const UpdateSelection(this.selectedRows);
|
||||
}
|
||||
|
@ -17,7 +17,8 @@ class DeviceManagementLoaded extends DeviceManagementState {
|
||||
final int onlineCount;
|
||||
final int offlineCount;
|
||||
final int lowBatteryCount;
|
||||
final AllDevicesModel? selectedDevice;
|
||||
final List<AllDevicesModel>? selectedDevice;
|
||||
final bool isControlButtonEnabled;
|
||||
|
||||
const DeviceManagementLoaded({
|
||||
required this.devices,
|
||||
@ -26,6 +27,7 @@ class DeviceManagementLoaded extends DeviceManagementState {
|
||||
required this.offlineCount,
|
||||
required this.lowBatteryCount,
|
||||
this.selectedDevice,
|
||||
required this.isControlButtonEnabled,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -35,7 +37,8 @@ class DeviceManagementLoaded extends DeviceManagementState {
|
||||
onlineCount,
|
||||
offlineCount,
|
||||
lowBatteryCount,
|
||||
selectedDevice
|
||||
selectedDevice,
|
||||
isControlButtonEnabled
|
||||
];
|
||||
}
|
||||
|
||||
@ -45,7 +48,8 @@ class DeviceManagementFiltered extends DeviceManagementState {
|
||||
final int onlineCount;
|
||||
final int offlineCount;
|
||||
final int lowBatteryCount;
|
||||
final AllDevicesModel? selectedDevice;
|
||||
final List<AllDevicesModel>? selectedDevice;
|
||||
final bool isControlButtonEnabled;
|
||||
|
||||
const DeviceManagementFiltered({
|
||||
required this.filteredDevices,
|
||||
@ -54,6 +58,7 @@ class DeviceManagementFiltered extends DeviceManagementState {
|
||||
required this.offlineCount,
|
||||
required this.lowBatteryCount,
|
||||
this.selectedDevice,
|
||||
required this.isControlButtonEnabled,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -63,7 +68,8 @@ class DeviceManagementFiltered extends DeviceManagementState {
|
||||
onlineCount,
|
||||
offlineCount,
|
||||
lowBatteryCount,
|
||||
selectedDevice
|
||||
selectedDevice,
|
||||
isControlButtonEnabled
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -1,34 +1,199 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/view/ac_device_batch_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/view/ac_device_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/view/ceiling_sensor_batch_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/view/ceiling_sensor_controls.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/door_lock/view/door_lock_status_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain/view/curtain_batch_status_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/curtain/view/curtain_status_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/door_lock/view/door_lock_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/door_lock/view/door_lock_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/garage_door/view/garage_door_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/garage_door/view/garage_door_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/gateway/view/gateway_batch_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/gateway/view/gateway_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/view/living_room_device_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/main_door_sensor/view/main_door_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/main_door_sensor/view/main_door_sensor_batch_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/one_g_glass_switch/view/one_gang_glass_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/one_gang_switch/view/wall_light_batch_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/one_gang_switch/view/wall_light_device_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/power_clamp/view/power_clamp_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/power_clamp/view/smart_power_device_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/sos/view/sos_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/sos/view/sos_device_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/view/three_gang_glass_switch_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/view/three_gang_glass_switch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/three_gang_switch/view/living_room_batch_controls.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/three_gang_switch/view/living_room_device_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/two_gang_switch/view/wall_light_batch_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/two_gang_switch/view/wall_light_device_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/view/wall_sensor_batch_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/view/wall_sensor_conrtols.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/water_heater/view/water_heater_batch_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/water_heater/view/water_heater_device_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/water_leak/view/water_leak_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/water_leak/view/water_leak_control_view.dart';
|
||||
|
||||
import '../../one_g_glass_switch/view/one_gang_glass_switch_control_view.dart';
|
||||
|
||||
mixin RouteControlsBasedCode {
|
||||
Widget routeControlsWidgets({required AllDevicesModel device}) {
|
||||
switch (device.productType) {
|
||||
case '1G':
|
||||
return WallLightDeviceControl(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case '2G':
|
||||
return TwoGangDeviceControlView(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case '3G':
|
||||
return LivingRoomDeviceControl(
|
||||
return LivingRoomDeviceControlsView(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case '1GT':
|
||||
return OneGangGlassSwitchControlView(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case '2GT':
|
||||
return TwoGangGlassSwitchControlView(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case '3GT':
|
||||
return ThreeGangGlassSwitchControlView(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case 'GW':
|
||||
return GateWayControls(
|
||||
return GateWayControlsView(
|
||||
gatewayId: device.uuid!,
|
||||
);
|
||||
case 'DL':
|
||||
return DoorLockView(device: device);
|
||||
return DoorLockControlsView(device: device);
|
||||
case 'WPS':
|
||||
return WallSensorControls(device: device);
|
||||
return WallSensorControlsView(device: device);
|
||||
case 'CPS':
|
||||
return CeilingSensorControls(
|
||||
return CeilingSensorControlsView(
|
||||
device: device,
|
||||
);
|
||||
case 'CUR':
|
||||
return CurtainStatusControlsView(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case 'AC':
|
||||
return AcDeviceControl(device: device);
|
||||
return AcDeviceControlsView(device: device);
|
||||
case 'WH':
|
||||
return WaterHeaterDeviceControlView(
|
||||
device: device,
|
||||
);
|
||||
case 'DS':
|
||||
return MainDoorSensorControlView(device: device);
|
||||
case 'GD':
|
||||
return GarageDoorControlView(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case 'WL':
|
||||
return WaterLeakView(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case 'PC':
|
||||
return SmartPowerDeviceControl(
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case 'SOS':
|
||||
return SosDeviceControlsView(device: device);
|
||||
default:
|
||||
return const SizedBox();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
3G:
|
||||
1G:
|
||||
2G:
|
||||
GW:
|
||||
DL:
|
||||
WPS:
|
||||
CPS:
|
||||
AC:
|
||||
CUR:
|
||||
WH:
|
||||
DS:
|
||||
*/
|
||||
|
||||
Widget routeBatchControlsWidgets({required List<AllDevicesModel> devices}) {
|
||||
switch (devices.first.productType) {
|
||||
case '1G':
|
||||
return WallLightBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == '1G')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case '2G':
|
||||
return TwoGangBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == '2G')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case '3G':
|
||||
return LivingRoomBatchControlsView(
|
||||
deviceIds: devices.where((e) => (e.productType == '3G')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case '1GT':
|
||||
return OneGangGlassSwitchBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == '1GT')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case '2GT':
|
||||
return TwoGangGlassSwitchBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == '2GT')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case '3GT':
|
||||
return ThreeGangGlassSwitchBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == '3GT')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case 'GW':
|
||||
return GatewayBatchControlView(
|
||||
gatewayIds: devices.where((e) => (e.productType == 'GW')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case 'DL':
|
||||
return DoorLockBatchControlView(
|
||||
devicesIds: devices.where((e) => (e.productType == 'DL')).map((e) => e.uuid!).toList());
|
||||
case 'WPS':
|
||||
return WallSensorBatchControlView(
|
||||
devicesIds: devices.where((e) => (e.productType == 'WPS')).map((e) => e.uuid!).toList());
|
||||
case 'CPS':
|
||||
return CeilingSensorBatchControlView(
|
||||
devicesIds: devices.where((e) => (e.productType == 'CPS')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case 'CUR':
|
||||
return CurtainBatchStatusView(
|
||||
devicesIds: devices.where((e) => (e.productType == 'CUR')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case 'AC':
|
||||
return AcDeviceBatchControlView(
|
||||
devicesIds: devices.where((e) => (e.productType == 'AC')).map((e) => e.uuid!).toList());
|
||||
case 'WH':
|
||||
return WaterHEaterBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == 'WH')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case 'DS':
|
||||
return MainDoorSensorBatchView(
|
||||
devicesIds: devices.where((e) => (e.productType == 'DS')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case 'GD':
|
||||
return GarageDoorBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == 'GD')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case 'WL':
|
||||
return WaterLeakBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == 'WL')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case 'PC':
|
||||
return PowerClampBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == 'PC')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
case 'SOS':
|
||||
return SOSBatchControlView(
|
||||
deviceIds: devices.where((e) => (e.productType == 'SOS')).map((e) => e.uuid!).toList(),
|
||||
);
|
||||
default:
|
||||
return const SizedBox();
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
class DeviceCommunityModel {
|
||||
String? uuid;
|
||||
String? name;
|
||||
|
||||
DeviceCommunityModel({this.uuid, this.name});
|
||||
|
||||
DeviceCommunityModel.fromJson(Map<String, dynamic> json) {
|
||||
uuid = json['uuid']?.toString();
|
||||
name = json['name']?.toString();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = <String, dynamic>{};
|
||||
data['uuid'] = uuid;
|
||||
data['name'] = name;
|
||||
return data;
|
||||
}
|
||||
}
|
@ -13,11 +13,15 @@ class DeviceReport {
|
||||
|
||||
DeviceReport.fromJson(Map<String, dynamic> json)
|
||||
: deviceUuid = json['deviceUuid'] as String?,
|
||||
startTime = json['startTime'] as int?,
|
||||
endTime = json['endTime'] as int?,
|
||||
data = (json['data'] as List<dynamic>?)
|
||||
?.map((e) => DeviceEvent.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
startTime = int.tryParse(json['startTime'].toString()) ??
|
||||
json['startTime'] as int?,
|
||||
endTime =
|
||||
int.tryParse(json['endTime'].toString()) ?? json['endTime'] as int?,
|
||||
data = json['data'] != null
|
||||
? (json['data'] as List<dynamic>?)
|
||||
?.map((e) => DeviceEvent.fromJson(e as Map<String, dynamic>))
|
||||
.toList()
|
||||
: [];
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'deviceUuid': deviceUuid,
|
||||
|
@ -0,0 +1,18 @@
|
||||
class DeviceSpaceModel {
|
||||
String? uuid;
|
||||
String? spaceName;
|
||||
|
||||
DeviceSpaceModel({this.uuid, this.spaceName});
|
||||
|
||||
DeviceSpaceModel.fromJson(Map<String, dynamic> json) {
|
||||
uuid = json['uuid']?.toString();
|
||||
spaceName = json['spaceName']?.toString();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = <String, dynamic>{};
|
||||
data['uuid'] = uuid;
|
||||
data['spaceName'] = spaceName;
|
||||
return data;
|
||||
}
|
||||
}
|
@ -1,5 +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/room.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class AllDevicesModel {
|
||||
/*
|
||||
@ -39,6 +42,7 @@ class AllDevicesModel {
|
||||
|
||||
DevicesModelRoom? room;
|
||||
DevicesModelUnit? unit;
|
||||
DeviceCommunityModel? community;
|
||||
String? productUuid;
|
||||
String? productType;
|
||||
String? permissionType;
|
||||
@ -62,10 +66,13 @@ class AllDevicesModel {
|
||||
int? updateTime;
|
||||
String? uuid;
|
||||
int? batteryLevel;
|
||||
String? productName;
|
||||
List<DeviceSpaceModel>? spaces;
|
||||
|
||||
AllDevicesModel({
|
||||
this.room,
|
||||
this.unit,
|
||||
this.community,
|
||||
this.productUuid,
|
||||
this.productType,
|
||||
this.permissionType,
|
||||
@ -89,6 +96,8 @@ class AllDevicesModel {
|
||||
this.updateTime,
|
||||
this.uuid,
|
||||
this.batteryLevel,
|
||||
this.productName,
|
||||
this.spaces,
|
||||
});
|
||||
AllDevicesModel.fromJson(Map<String, dynamic> json) {
|
||||
room = (json['room'] != null && (json['room'] is Map))
|
||||
@ -97,6 +106,9 @@ class AllDevicesModel {
|
||||
unit = (json['unit'] != null && (json['unit'] is Map))
|
||||
? DevicesModelUnit.fromJson(json['unit'])
|
||||
: null;
|
||||
community = (json['community'] != null && (json['community'] is Map))
|
||||
? DeviceCommunityModel.fromJson(json['community'])
|
||||
: null;
|
||||
productUuid = json['productUuid']?.toString();
|
||||
productType = json['productType']?.toString();
|
||||
permissionType = json['permissionType']?.toString();
|
||||
@ -105,7 +117,7 @@ class AllDevicesModel {
|
||||
categoryName = json['categoryName']?.toString();
|
||||
createTime = int.tryParse(json['createTime']?.toString() ?? '');
|
||||
gatewayId = json['gatewayId']?.toString();
|
||||
icon = json['icon']?.toString();
|
||||
icon = json['icon'] ?? _getDefaultIcon(productType);
|
||||
ip = json['ip']?.toString();
|
||||
lat = json['lat']?.toString();
|
||||
localKey = json['localKey']?.toString();
|
||||
@ -119,8 +131,43 @@ class AllDevicesModel {
|
||||
timeZone = json['timeZone']?.toString();
|
||||
updateTime = int.tryParse(json['updateTime']?.toString() ?? '');
|
||||
uuid = json['uuid']?.toString();
|
||||
batteryLevel = int.tryParse(json['batteryLevel']?.toString() ?? '');
|
||||
batteryLevel = int.tryParse(json['battery']?.toString() ?? '');
|
||||
productName = json['productName']?.toString();
|
||||
if (json['spaces'] != null && json['spaces'] is List) {
|
||||
spaces = (json['spaces'] as List)
|
||||
.map((space) => DeviceSpaceModel.fromJson(space))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
String _getDefaultIcon(String? productType) {
|
||||
switch (productType) {
|
||||
case 'LightBulb':
|
||||
return Assets.lightBulb;
|
||||
case 'CeilingSensor':
|
||||
case 'WallSensor':
|
||||
return Assets.sensors;
|
||||
case 'AC':
|
||||
return Assets.ac;
|
||||
case 'DoorLock':
|
||||
return Assets.doorLock;
|
||||
case 'Curtain':
|
||||
return Assets.curtain;
|
||||
case '3G':
|
||||
case '2G':
|
||||
case '1G':
|
||||
return Assets.gangSwitch;
|
||||
case 'Gateway':
|
||||
return Assets.gateway;
|
||||
case 'WH':
|
||||
return Assets.blackLogo;
|
||||
case 'DS':
|
||||
return Assets.sensors;
|
||||
default:
|
||||
return Assets.logo;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = <String, dynamic>{};
|
||||
if (room != null) {
|
||||
@ -129,6 +176,9 @@ class AllDevicesModel {
|
||||
if (unit != null) {
|
||||
data['unit'] = unit!.toJson();
|
||||
}
|
||||
if (community != null) {
|
||||
data['community'] = community!.toJson();
|
||||
}
|
||||
data['productUuid'] = productUuid;
|
||||
data['productType'] = productType;
|
||||
data['permissionType'] = permissionType;
|
||||
@ -151,7 +201,74 @@ class AllDevicesModel {
|
||||
data['timeZone'] = timeZone;
|
||||
data['updateTime'] = updateTime;
|
||||
data['uuid'] = uuid;
|
||||
data['batteryLevel'] = batteryLevel;
|
||||
data['battery'] = batteryLevel;
|
||||
data['productName'] = productName;
|
||||
if (spaces != null) {
|
||||
data['spaces'] = spaces!.map((space) => space.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is AllDevicesModel &&
|
||||
other.room == room &&
|
||||
other.unit == unit &&
|
||||
other.productUuid == productUuid &&
|
||||
other.productType == productType &&
|
||||
other.permissionType == permissionType &&
|
||||
other.activeTime == activeTime &&
|
||||
other.category == category &&
|
||||
other.categoryName == categoryName &&
|
||||
other.createTime == createTime &&
|
||||
other.gatewayId == gatewayId &&
|
||||
other.icon == icon &&
|
||||
other.ip == ip &&
|
||||
other.lat == lat &&
|
||||
other.localKey == localKey &&
|
||||
other.lon == lon &&
|
||||
other.model == model &&
|
||||
other.name == name &&
|
||||
other.nodeId == nodeId &&
|
||||
other.online == online &&
|
||||
other.ownerId == ownerId &&
|
||||
other.sub == sub &&
|
||||
other.timeZone == timeZone &&
|
||||
other.updateTime == updateTime &&
|
||||
other.uuid == uuid &&
|
||||
other.productName == productName &&
|
||||
other.batteryLevel == batteryLevel;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return room.hashCode ^
|
||||
unit.hashCode ^
|
||||
productUuid.hashCode ^
|
||||
productType.hashCode ^
|
||||
permissionType.hashCode ^
|
||||
activeTime.hashCode ^
|
||||
category.hashCode ^
|
||||
categoryName.hashCode ^
|
||||
createTime.hashCode ^
|
||||
gatewayId.hashCode ^
|
||||
icon.hashCode ^
|
||||
ip.hashCode ^
|
||||
lat.hashCode ^
|
||||
localKey.hashCode ^
|
||||
lon.hashCode ^
|
||||
model.hashCode ^
|
||||
name.hashCode ^
|
||||
nodeId.hashCode ^
|
||||
online.hashCode ^
|
||||
ownerId.hashCode ^
|
||||
sub.hashCode ^
|
||||
timeZone.hashCode ^
|
||||
updateTime.hashCode ^
|
||||
uuid.hashCode ^
|
||||
productName.hashCode ^
|
||||
batteryLevel.hashCode;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class FactoryResetModel {
|
||||
final List<String> devicesUuid;
|
||||
|
||||
FactoryResetModel({
|
||||
required this.devicesUuid,
|
||||
});
|
||||
|
||||
factory FactoryResetModel.fromJson(Map<String, dynamic> json) {
|
||||
return FactoryResetModel(
|
||||
devicesUuid: List<String>.from(json['devicesUuid']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'devicesUuid': devicesUuid,
|
||||
};
|
||||
}
|
||||
|
||||
FactoryResetModel copyWith({
|
||||
List<String>? devicesUuid,
|
||||
}) {
|
||||
return FactoryResetModel(
|
||||
devicesUuid: devicesUuid ?? this.devicesUuid,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'devicesUuid': devicesUuid,
|
||||
};
|
||||
}
|
||||
|
||||
factory FactoryResetModel.fromMap(Map<String, dynamic> map) {
|
||||
return FactoryResetModel(
|
||||
devicesUuid: List<String>.from(map['devicesUuid']),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'FactoryReset(devicesUuid: $devicesUuid)';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is FactoryResetModel &&
|
||||
listEquals(other.devicesUuid, devicesUuid);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => devicesUuid.hashCode;
|
||||
}
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_managment_body.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
@ -13,24 +14,25 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
||||
return BlocProvider(
|
||||
create: (context) => DeviceManagementBloc()..add(FetchDevices()),
|
||||
child: WebScaffold(
|
||||
appBarTitle: Text(
|
||||
'Device Management',
|
||||
style: Theme.of(context).textTheme.headlineLarge,
|
||||
appBarTitle: FittedBox(
|
||||
child: Text(
|
||||
'Device Management',
|
||||
style: Theme.of(context).textTheme.headlineLarge,
|
||||
),
|
||||
),
|
||||
enableMenuSideba: isLargeScreenSize(context),
|
||||
rightBody: const NavigateHomeGridView(),
|
||||
scaffoldBody: BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
|
||||
builder: (context, state) {
|
||||
if (state is DeviceManagementLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state is DeviceManagementLoaded ||
|
||||
state is DeviceManagementFiltered) {
|
||||
} else if (state is DeviceManagementLoaded || state is DeviceManagementFiltered) {
|
||||
final devices = state is DeviceManagementLoaded
|
||||
? state.devices
|
||||
: (state as DeviceManagementFiltered).filteredDevices;
|
||||
|
||||
return DeviceManagementBody(devices: devices);
|
||||
} else {
|
||||
return const Center(child: Text('No Devices Found'));
|
||||
return const Center(child: Text('Error fetching Devices'));
|
||||
}
|
||||
},
|
||||
),
|
||||
@ -38,3 +40,6 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/core/extension/build_context_x.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||
import 'package:syncrow_web/pages/common/custom_table.dart';
|
||||
import 'package:syncrow_web/pages/common/filter/filter_widget.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart';
|
||||
import 'package:syncrow_web/utils/format_date_time.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
@ -27,6 +27,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
int offlineCount = 0;
|
||||
int lowBatteryCount = 0;
|
||||
bool isControlButtonEnabled = false;
|
||||
List<AllDevicesModel> selectedDevices = [];
|
||||
|
||||
if (state is DeviceManagementLoaded) {
|
||||
devicesToShow = state.devices;
|
||||
@ -34,87 +35,108 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
onlineCount = state.onlineCount;
|
||||
offlineCount = state.offlineCount;
|
||||
lowBatteryCount = state.lowBatteryCount;
|
||||
isControlButtonEnabled = state.selectedDevice != null;
|
||||
isControlButtonEnabled = state.isControlButtonEnabled;
|
||||
selectedDevices = state.selectedDevice ?? [];
|
||||
} else if (state is DeviceManagementFiltered) {
|
||||
devicesToShow = state.filteredDevices;
|
||||
selectedIndex = state.selectedIndex;
|
||||
onlineCount = state.onlineCount;
|
||||
offlineCount = state.offlineCount;
|
||||
lowBatteryCount = state.lowBatteryCount;
|
||||
isControlButtonEnabled = state.selectedDevice != null;
|
||||
isControlButtonEnabled = state.isControlButtonEnabled;
|
||||
selectedDevices = state.selectedDevice ?? [];
|
||||
} else if (state is DeviceManagementInitial) {
|
||||
devicesToShow = [];
|
||||
selectedIndex = 0;
|
||||
isControlButtonEnabled = false;
|
||||
}
|
||||
|
||||
final tabs = [
|
||||
'All (${devices.length})',
|
||||
'All',
|
||||
'Online ($onlineCount)',
|
||||
'Offline ($offlineCount)',
|
||||
'Low Battery ($lowBatteryCount)',
|
||||
];
|
||||
|
||||
return CustomScrollView(
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
padding: isLargeScreenSize(context)
|
||||
? const EdgeInsets.all(30)
|
||||
: const EdgeInsets.all(15),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
FilterWidget(
|
||||
size: MediaQuery.of(context).size,
|
||||
tabs: tabs,
|
||||
selectedIndex: selectedIndex,
|
||||
onTabChanged: (index) {
|
||||
context
|
||||
.read<DeviceManagementBloc>()
|
||||
.add(SelectedFilterChanged(index));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const DeviceSearchFilters(),
|
||||
const SizedBox(height: 12),
|
||||
Container(
|
||||
height: 43,
|
||||
width: isSmallScreenSize(context) ? double.infinity : 100,
|
||||
decoration: containerDecoration,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
onPressed: isControlButtonEnabled
|
||||
? () {
|
||||
final selectedDevice = context
|
||||
.read<DeviceManagementBloc>()
|
||||
.selectedDevices
|
||||
.first;
|
||||
final buttonLabel =
|
||||
(selectedDevices.length > 1) ? 'Batch Control' : 'Control';
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: isLargeScreenSize(context)
|
||||
? const EdgeInsets.all(30)
|
||||
: const EdgeInsets.all(15),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
FilterWidget(
|
||||
size: MediaQuery.of(context).size,
|
||||
tabs: tabs,
|
||||
selectedIndex: selectedIndex,
|
||||
onTabChanged: (index) {
|
||||
context
|
||||
.read<DeviceManagementBloc>()
|
||||
.add(SelectedFilterChanged(index));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const DeviceSearchFilters(),
|
||||
const SizedBox(height: 12),
|
||||
Container(
|
||||
height: 45,
|
||||
width: 125,
|
||||
decoration: containerDecoration,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
onPressed: isControlButtonEnabled
|
||||
? () {
|
||||
if (selectedDevices.length == 1) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => DeviceControlDialog(
|
||||
device: selectedDevice),
|
||||
device: selectedDevices.first,
|
||||
),
|
||||
);
|
||||
} else if (selectedDevices.length > 1) {
|
||||
final productTypes = selectedDevices
|
||||
.map((device) => device.productType)
|
||||
.toSet();
|
||||
if (productTypes.length == 1) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
DeviceBatchControlDialog(
|
||||
devices: selectedDevices,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
: null,
|
||||
borderRadius: 9,
|
||||
child: Text(
|
||||
'Control',
|
||||
style: TextStyle(
|
||||
color: isControlButtonEnabled
|
||||
? Colors.white
|
||||
: Colors.grey,
|
||||
),
|
||||
}
|
||||
: null,
|
||||
borderRadius: 9,
|
||||
child: Text(
|
||||
buttonLabel,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: isControlButtonEnabled
|
||||
? Colors.white
|
||||
: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SliverFillRemaining(
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: isLargeScreenSize(context)
|
||||
? const EdgeInsets.all(30)
|
||||
: const EdgeInsets.all(15),
|
||||
child: DynamicTable(
|
||||
withSelectAll: true,
|
||||
cellDecoration: containerDecoration,
|
||||
onRowSelected: (index, isSelected, row) {
|
||||
final selectedDevice = devicesToShow[index];
|
||||
@ -123,28 +145,42 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
.add(SelectDevice(selectedDevice));
|
||||
},
|
||||
withCheckBox: true,
|
||||
size: context.screenSize,
|
||||
size: MediaQuery.of(context).size,
|
||||
uuidIndex: 2,
|
||||
headers: const [
|
||||
'Device Name',
|
||||
'Product Name',
|
||||
'Device ID',
|
||||
'Unit Name',
|
||||
'Room',
|
||||
'Space Name',
|
||||
'location',
|
||||
'Battery Level',
|
||||
'Installation Date and Time',
|
||||
'Status',
|
||||
'Last Offline Date and Time',
|
||||
],
|
||||
data: devicesToShow.map((device) {
|
||||
final combinedSpaceNames = device.spaces != null
|
||||
? device.spaces!
|
||||
.map((space) => space.spaceName)
|
||||
.join(' > ') +
|
||||
(device.community != null
|
||||
? ' > ${device.community!.name}'
|
||||
: '')
|
||||
: (device.community != null
|
||||
? device.community!.name
|
||||
: '');
|
||||
|
||||
return [
|
||||
device.categoryName ?? '',
|
||||
device.name ?? '',
|
||||
device.productName ?? '',
|
||||
device.uuid ?? '',
|
||||
device.unit?.name ?? '',
|
||||
device.room?.name ?? '',
|
||||
(device.spaces != null && device.spaces!.isNotEmpty)
|
||||
? device.spaces![0].spaceName
|
||||
: '',
|
||||
combinedSpaceNames,
|
||||
device.batteryLevel != null
|
||||
? '${device.batteryLevel}%'
|
||||
: '',
|
||||
: '-',
|
||||
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
|
||||
(device.createTime ?? 0) * 1000)),
|
||||
device.online == true ? 'Online' : 'Offline',
|
||||
@ -152,10 +188,20 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
(device.updateTime ?? 0) * 1000)),
|
||||
];
|
||||
}).toList(),
|
||||
onSelectionChanged: (selectedRows) {
|
||||
context
|
||||
.read<DeviceManagementBloc>()
|
||||
.add(UpdateSelection(selectedRows));
|
||||
},
|
||||
initialSelectedIds: context
|
||||
.read<DeviceManagementBloc>()
|
||||
.selectedDevices
|
||||
.map((device) => device.uuid!)
|
||||
.toList(),
|
||||
isEmpty: devicesToShow.isEmpty,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
|
@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/common/text_field/custom_text_field.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/search_reset_buttons.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
class DeviceSearchFilters extends StatefulWidget {
|
||||
const DeviceSearchFilters({super.key});
|
||||
@ -28,12 +29,12 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return isLargeScreenSize(context)
|
||||
return isExtraLargeScreenSize(context)
|
||||
? Row(
|
||||
children: [
|
||||
_buildSearchField("Community", communityController, 200),
|
||||
const SizedBox(width: 20),
|
||||
_buildSearchField("Unit Name", unitNameController, 200),
|
||||
_buildSearchField("Space Name", unitNameController, 200),
|
||||
const SizedBox(width: 20),
|
||||
_buildSearchField(
|
||||
"Device Name / Product Name", productNameController, 300),
|
||||
@ -45,10 +46,17 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
||||
spacing: 20,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
_buildSearchField("Community", communityController, 200),
|
||||
_buildSearchField("Unit Name", unitNameController, 200),
|
||||
_buildSearchField(
|
||||
"Device Name / Product Name", productNameController, 300),
|
||||
"Community",
|
||||
communityController,
|
||||
200,
|
||||
),
|
||||
_buildSearchField("Space Name", unitNameController, 200),
|
||||
_buildSearchField(
|
||||
"Device Name / Product Name",
|
||||
productNameController,
|
||||
300,
|
||||
),
|
||||
_buildSearchResetButtons(),
|
||||
],
|
||||
);
|
||||
@ -56,11 +64,20 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
||||
|
||||
Widget _buildSearchField(
|
||||
String title, TextEditingController controller, double width) {
|
||||
return StatefulTextField(
|
||||
title: title,
|
||||
width: width,
|
||||
elevation: 2,
|
||||
controller: controller,
|
||||
return Container(
|
||||
child: StatefulTextField(
|
||||
title: title,
|
||||
width: width,
|
||||
elevation: 2,
|
||||
controller: controller,
|
||||
onSubmitted: () {
|
||||
context.read<DeviceManagementBloc>().add(SearchDevices(
|
||||
productName: productNameController.text,
|
||||
unitName: unitNameController.text,
|
||||
community: communityController.text,
|
||||
searchField: true));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -68,16 +85,18 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
||||
return SearchResetButtons(
|
||||
onSearch: () {
|
||||
context.read<DeviceManagementBloc>().add(SearchDevices(
|
||||
community: communityController.text,
|
||||
unitName: unitNameController.text,
|
||||
productName: productNameController.text,
|
||||
));
|
||||
community: communityController.text,
|
||||
unitName: unitNameController.text,
|
||||
productName: productNameController.text,
|
||||
searchField: true));
|
||||
},
|
||||
onReset: () {
|
||||
communityController.clear();
|
||||
unitNameController.clear();
|
||||
productNameController.clear();
|
||||
context.read<DeviceManagementBloc>().add(FetchDevices());
|
||||
context.read<DeviceManagementBloc>()
|
||||
..add(ResetFilters())
|
||||
..add(FetchDevices());
|
||||
},
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user