Merge pull request #47 from SyncrowIOT/feat/refactoring

Feat/refactoring
This commit is contained in:
Abdullah
2024-11-06 10:57:30 +03:00
committed by GitHub
9 changed files with 128 additions and 29 deletions

View File

@ -6,7 +6,8 @@ import 'package:syncrow_web/services/devices_mang_api.dart';
part 'device_managment_event.dart'; part 'device_managment_event.dart';
part 'device_managment_state.dart'; part 'device_managment_state.dart';
class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementState> { class DeviceManagementBloc
extends Bloc<DeviceManagementEvent, DeviceManagementState> {
int _selectedIndex = 0; int _selectedIndex = 0;
List<AllDevicesModel> _devices = []; List<AllDevicesModel> _devices = [];
int _onlineCount = 0; int _onlineCount = 0;
@ -29,7 +30,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
on<UpdateSelection>(_onUpdateSelection); on<UpdateSelection>(_onUpdateSelection);
} }
Future<void> _onFetchDevices(FetchDevices event, Emitter<DeviceManagementState> emit) async { Future<void> _onFetchDevices(
FetchDevices event, Emitter<DeviceManagementState> emit) async {
emit(DeviceManagementLoading()); emit(DeviceManagementLoading());
try { try {
final devices = await DevicesManagementApi().fetchDevices(); final devices = await DevicesManagementApi().fetchDevices();
@ -51,7 +53,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
} }
} }
void _onFilterDevices(FilterDevices event, Emitter<DeviceManagementState> emit) async { void _onFilterDevices(
FilterDevices event, Emitter<DeviceManagementState> emit) async {
if (_devices.isNotEmpty) { if (_devices.isNotEmpty) {
_filteredDevices = List.from(_devices.where((device) { _filteredDevices = List.from(_devices.where((device) {
switch (event.filter) { switch (event.filter) {
@ -82,7 +85,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
} }
} }
Future<void> _onResetFilters(ResetFilters event, Emitter<DeviceManagementState> emit) async { Future<void> _onResetFilters(
ResetFilters event, Emitter<DeviceManagementState> emit) async {
currentProductName = ''; currentProductName = '';
_selectedDevices.clear(); _selectedDevices.clear();
_filteredDevices = List.from(_devices); _filteredDevices = List.from(_devices);
@ -98,7 +102,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
)); ));
} }
void _onResetSelectedDevices(ResetSelectedDevices event, Emitter<DeviceManagementState> emit) { void _onResetSelectedDevices(
ResetSelectedDevices event, Emitter<DeviceManagementState> emit) {
_selectedDevices.clear(); _selectedDevices.clear();
if (state is DeviceManagementLoaded) { if (state is DeviceManagementLoaded) {
@ -124,12 +129,14 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
} }
} }
void _onSelectedFilterChanged(SelectedFilterChanged event, Emitter<DeviceManagementState> emit) { void _onSelectedFilterChanged(
SelectedFilterChanged event, Emitter<DeviceManagementState> emit) {
_selectedIndex = event.selectedIndex; _selectedIndex = event.selectedIndex;
add(FilterDevices(_getFilterFromIndex(_selectedIndex))); add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
} }
void _onSelectDevice(SelectDevice event, Emitter<DeviceManagementState> emit) { void _onSelectDevice(
SelectDevice event, Emitter<DeviceManagementState> emit) {
final selectedUuid = event.selectedDevice.uuid; final selectedUuid = event.selectedDevice.uuid;
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) { if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
@ -140,7 +147,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices); List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
bool isControlButtonEnabled = _checkIfControlButtonEnabled(clonedSelectedDevices); bool isControlButtonEnabled =
_checkIfControlButtonEnabled(clonedSelectedDevices);
if (state is DeviceManagementLoaded) { if (state is DeviceManagementLoaded) {
emit(DeviceManagementLoaded( emit(DeviceManagementLoaded(
@ -149,7 +157,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
onlineCount: _onlineCount, onlineCount: _onlineCount,
offlineCount: _offlineCount, offlineCount: _offlineCount,
lowBatteryCount: _lowBatteryCount, lowBatteryCount: _lowBatteryCount,
selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null, selectedDevice:
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
isControlButtonEnabled: isControlButtonEnabled, isControlButtonEnabled: isControlButtonEnabled,
)); ));
} else if (state is DeviceManagementFiltered) { } else if (state is DeviceManagementFiltered) {
@ -159,13 +168,15 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
onlineCount: _onlineCount, onlineCount: _onlineCount,
offlineCount: _offlineCount, offlineCount: _offlineCount,
lowBatteryCount: _lowBatteryCount, lowBatteryCount: _lowBatteryCount,
selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null, selectedDevice:
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
isControlButtonEnabled: isControlButtonEnabled, isControlButtonEnabled: isControlButtonEnabled,
)); ));
} }
} }
void _onUpdateSelection(UpdateSelection event, Emitter<DeviceManagementState> emit) { void _onUpdateSelection(
UpdateSelection event, Emitter<DeviceManagementState> emit) {
List<AllDevicesModel> selectedDevices = []; List<AllDevicesModel> selectedDevices = [];
List<AllDevicesModel> devicesToSelectFrom = []; List<AllDevicesModel> devicesToSelectFrom = [];
@ -208,7 +219,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) { bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
if (selectedDevices.length > 1) { if (selectedDevices.length > 1) {
final productTypes = selectedDevices.map((device) => device.productType).toSet(); final productTypes =
selectedDevices.map((device) => device.productType).toSet();
return productTypes.length == 1; return productTypes.length == 1;
} else if (selectedDevices.length == 1) { } else if (selectedDevices.length == 1) {
return true; return true;
@ -219,8 +231,10 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
void _calculateDeviceCounts() { void _calculateDeviceCounts() {
_onlineCount = _devices.where((device) => device.online == true).length; _onlineCount = _devices.where((device) => device.online == true).length;
_offlineCount = _devices.where((device) => device.online == false).length; _offlineCount = _devices.where((device) => device.online == false).length;
_lowBatteryCount = _lowBatteryCount = _devices
_devices.where((device) => device.batteryLevel != null && device.batteryLevel! < 20).length; .where((device) =>
device.batteryLevel != null && device.batteryLevel! < 20)
.length;
} }
String _getFilterFromIndex(int index) { String _getFilterFromIndex(int index) {
@ -236,7 +250,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
} }
} }
void _onSearchDevices(SearchDevices event, Emitter<DeviceManagementState> emit) { void _onSearchDevices(
SearchDevices event, Emitter<DeviceManagementState> emit) {
if ((event.community == null || event.community!.isEmpty) && if ((event.community == null || event.community!.isEmpty) &&
(event.unitName == null || event.unitName!.isEmpty) && (event.unitName == null || event.unitName!.isEmpty) &&
(event.productName == null || event.productName!.isEmpty)) { (event.productName == null || event.productName!.isEmpty)) {
@ -265,19 +280,33 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
final filteredDevices = devicesToSearch.where((device) { final filteredDevices = devicesToSearch.where((device) {
final matchesCommunity = event.community == null || final matchesCommunity = event.community == null ||
event.community!.isEmpty || event.community!.isEmpty ||
(device.room?.name?.toLowerCase().contains(event.community!.toLowerCase()) ?? false); (device.community?.name
?.toLowerCase()
.contains(event.community!.toLowerCase()) ??
false);
final matchesUnit = event.unitName == null || final matchesUnit = event.unitName == null ||
event.unitName!.isEmpty || 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 || final matchesProductName = event.productName == null ||
event.productName!.isEmpty || event.productName!.isEmpty ||
(device.name?.toLowerCase().contains(event.productName!.toLowerCase()) ?? false); (device.name
?.toLowerCase()
.contains(event.productName!.toLowerCase()) ??
false);
final matchesDeviceName = event.productName == null || final matchesDeviceName = event.productName == null ||
event.productName!.isEmpty || event.productName!.isEmpty ||
(device.categoryName?.toLowerCase().contains(event.productName!.toLowerCase()) ?? (device.categoryName
?.toLowerCase()
.contains(event.productName!.toLowerCase()) ??
false); false);
return matchesCommunity && matchesUnit && (matchesProductName || matchesDeviceName); return matchesCommunity &&
matchesUnit &&
(matchesProductName || matchesDeviceName);
}).toList(); }).toList();
emit(DeviceManagementFiltered( emit(DeviceManagementFiltered(

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -1,3 +1,5 @@
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/room.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
@ -40,6 +42,7 @@ class AllDevicesModel {
DevicesModelRoom? room; DevicesModelRoom? room;
DevicesModelUnit? unit; DevicesModelUnit? unit;
DeviceCommunityModel? community;
String? productUuid; String? productUuid;
String? productType; String? productType;
String? permissionType; String? permissionType;
@ -64,10 +67,12 @@ class AllDevicesModel {
String? uuid; String? uuid;
int? batteryLevel; int? batteryLevel;
String? productName; String? productName;
List<DeviceSpaceModel>? spaces;
AllDevicesModel({ AllDevicesModel({
this.room, this.room,
this.unit, this.unit,
this.community,
this.productUuid, this.productUuid,
this.productType, this.productType,
this.permissionType, this.permissionType,
@ -92,6 +97,7 @@ class AllDevicesModel {
this.uuid, this.uuid,
this.batteryLevel, this.batteryLevel,
this.productName, this.productName,
this.spaces,
}); });
AllDevicesModel.fromJson(Map<String, dynamic> json) { AllDevicesModel.fromJson(Map<String, dynamic> json) {
room = (json['room'] != null && (json['room'] is Map)) room = (json['room'] != null && (json['room'] is Map))
@ -100,6 +106,9 @@ class AllDevicesModel {
unit = (json['unit'] != null && (json['unit'] is Map)) unit = (json['unit'] != null && (json['unit'] is Map))
? DevicesModelUnit.fromJson(json['unit']) ? DevicesModelUnit.fromJson(json['unit'])
: null; : null;
community = (json['community'] != null && (json['community'] is Map))
? DeviceCommunityModel.fromJson(json['community'])
: null;
productUuid = json['productUuid']?.toString(); productUuid = json['productUuid']?.toString();
productType = json['productType']?.toString(); productType = json['productType']?.toString();
permissionType = json['permissionType']?.toString(); permissionType = json['permissionType']?.toString();
@ -124,6 +133,11 @@ class AllDevicesModel {
uuid = json['uuid']?.toString(); uuid = json['uuid']?.toString();
batteryLevel = int.tryParse(json['battery']?.toString() ?? ''); batteryLevel = int.tryParse(json['battery']?.toString() ?? '');
productName = json['productName']?.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) { String _getDefaultIcon(String? productType) {
@ -162,6 +176,9 @@ class AllDevicesModel {
if (unit != null) { if (unit != null) {
data['unit'] = unit!.toJson(); data['unit'] = unit!.toJson();
} }
if (community != null) {
data['community'] = community!.toJson();
}
data['productUuid'] = productUuid; data['productUuid'] = productUuid;
data['productType'] = productType; data['productType'] = productType;
data['permissionType'] = permissionType; data['permissionType'] = permissionType;
@ -186,6 +203,9 @@ class AllDevicesModel {
data['uuid'] = uuid; data['uuid'] = uuid;
data['battery'] = batteryLevel; data['battery'] = batteryLevel;
data['productName'] = productName; data['productName'] = productName;
if (spaces != null) {
data['spaces'] = spaces!.map((space) => space.toJson()).toList();
}
return data; return data;
} }

View File

@ -151,20 +151,33 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
'Device Name', 'Device Name',
'Product Name', 'Product Name',
'Device ID', 'Device ID',
'Unit Name', 'Space Name',
'Room', 'location',
'Battery Level', 'Battery Level',
'Installation Date and Time', 'Installation Date and Time',
'Status', 'Status',
'Last Offline Date and Time', 'Last Offline Date and Time',
], ],
data: devicesToShow.map((device) { 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 [ return [
device.name ?? '', device.name ?? '',
device.productName ?? '', device.productName ?? '',
device.uuid ?? '', device.uuid ?? '',
device.unit?.name ?? '', (device.spaces != null && device.spaces!.isNotEmpty)
device.room?.name ?? '', ? device.spaces![0].spaceName
: '',
combinedSpaceNames,
device.batteryLevel != null device.batteryLevel != null
? '${device.batteryLevel}%' ? '${device.batteryLevel}%'
: '-', : '-',

View File

@ -34,7 +34,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
children: [ children: [
_buildSearchField("Community", communityController, 200), _buildSearchField("Community", communityController, 200),
const SizedBox(width: 20), const SizedBox(width: 20),
_buildSearchField("Unit Name", unitNameController, 200), _buildSearchField("Space Name", unitNameController, 200),
const SizedBox(width: 20), const SizedBox(width: 20),
_buildSearchField( _buildSearchField(
"Device Name / Product Name", productNameController, 300), "Device Name / Product Name", productNameController, 300),
@ -51,7 +51,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
communityController, communityController,
200, 200,
), ),
_buildSearchField("Unit Name", unitNameController, 200), _buildSearchField("Space Name", unitNameController, 200),
_buildSearchField( _buildSearchField(
"Device Name / Product Name", "Device Name / Product Name",
productNameController, productNameController,

View File

@ -95,7 +95,7 @@ class DeviceControlDialog extends StatelessWidget with RouteControlsBasedCode {
]), ]),
TableRow( TableRow(
children: [ children: [
_buildInfoRow('Unit Name:', device.unit?.name ?? 'N/A'), _buildInfoRow('Space Name:', device.unit?.name ?? 'N/A'),
_buildInfoRow('Room:', device.room?.name ?? 'N/A'), _buildInfoRow('Room:', device.room?.name ?? 'N/A'),
], ],
), ),

View File

@ -111,7 +111,7 @@ class AddDeviceDialog extends StatelessWidget {
child: CustomWebTextField( child: CustomWebTextField(
controller: visitorBloc.unitNameController, controller: visitorBloc.unitNameController,
isRequired: false, isRequired: false,
textFieldName: 'Unit Name', textFieldName: 'Space Name',
description: '', description: '',
), ),
), ),
@ -185,7 +185,7 @@ class AddDeviceDialog extends StatelessWidget {
'Device Name', 'Device Name',
'Device ID', 'Device ID',
'Access Type', 'Access Type',
'Unit Name', 'Space Name',
'Status' 'Status'
], ],
data: state.data.map((item) { data: state.data.map((item) {

View File

@ -1,3 +1,4 @@
import 'dart:core';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_reports.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/device_reports.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';