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_state.dart';
class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementState> {
class DeviceManagementBloc
extends Bloc<DeviceManagementEvent, DeviceManagementState> {
int _selectedIndex = 0;
List<AllDevicesModel> _devices = [];
int _onlineCount = 0;
@ -29,7 +30,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
on<UpdateSelection>(_onUpdateSelection);
}
Future<void> _onFetchDevices(FetchDevices event, Emitter<DeviceManagementState> emit) async {
Future<void> _onFetchDevices(
FetchDevices event, Emitter<DeviceManagementState> emit) async {
emit(DeviceManagementLoading());
try {
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) {
_filteredDevices = List.from(_devices.where((device) {
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 = '';
_selectedDevices.clear();
_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();
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;
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
}
void _onSelectDevice(SelectDevice event, Emitter<DeviceManagementState> emit) {
void _onSelectDevice(
SelectDevice event, Emitter<DeviceManagementState> emit) {
final selectedUuid = event.selectedDevice.uuid;
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
@ -140,7 +147,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
bool isControlButtonEnabled = _checkIfControlButtonEnabled(clonedSelectedDevices);
bool isControlButtonEnabled =
_checkIfControlButtonEnabled(clonedSelectedDevices);
if (state is DeviceManagementLoaded) {
emit(DeviceManagementLoaded(
@ -149,7 +157,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
onlineCount: _onlineCount,
offlineCount: _offlineCount,
lowBatteryCount: _lowBatteryCount,
selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
selectedDevice:
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
isControlButtonEnabled: isControlButtonEnabled,
));
} else if (state is DeviceManagementFiltered) {
@ -159,13 +168,15 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
onlineCount: _onlineCount,
offlineCount: _offlineCount,
lowBatteryCount: _lowBatteryCount,
selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
selectedDevice:
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
isControlButtonEnabled: isControlButtonEnabled,
));
}
}
void _onUpdateSelection(UpdateSelection event, Emitter<DeviceManagementState> emit) {
void _onUpdateSelection(
UpdateSelection event, Emitter<DeviceManagementState> emit) {
List<AllDevicesModel> selectedDevices = [];
List<AllDevicesModel> devicesToSelectFrom = [];
@ -208,7 +219,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
if (selectedDevices.length > 1) {
final productTypes = selectedDevices.map((device) => device.productType).toSet();
final productTypes =
selectedDevices.map((device) => device.productType).toSet();
return productTypes.length == 1;
} else if (selectedDevices.length == 1) {
return true;
@ -219,8 +231,10 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
void _calculateDeviceCounts() {
_onlineCount = _devices.where((device) => device.online == true).length;
_offlineCount = _devices.where((device) => device.online == false).length;
_lowBatteryCount =
_devices.where((device) => device.batteryLevel != null && device.batteryLevel! < 20).length;
_lowBatteryCount = _devices
.where((device) =>
device.batteryLevel != null && device.batteryLevel! < 20)
.length;
}
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) &&
(event.unitName == null || event.unitName!.isEmpty) &&
(event.productName == null || event.productName!.isEmpty)) {
@ -265,19 +280,33 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
final filteredDevices = devicesToSearch.where((device) {
final matchesCommunity = event.community == null ||
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 ||
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);
(device.name
?.toLowerCase()
.contains(event.productName!.toLowerCase()) ??
false);
final matchesDeviceName = event.productName == null ||
event.productName!.isEmpty ||
(device.categoryName?.toLowerCase().contains(event.productName!.toLowerCase()) ??
(device.categoryName
?.toLowerCase()
.contains(event.productName!.toLowerCase()) ??
false);
return matchesCommunity && matchesUnit && (matchesProductName || matchesDeviceName);
return matchesCommunity &&
matchesUnit &&
(matchesProductName || matchesDeviceName);
}).toList();
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/unit.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
@ -40,6 +42,7 @@ class AllDevicesModel {
DevicesModelRoom? room;
DevicesModelUnit? unit;
DeviceCommunityModel? community;
String? productUuid;
String? productType;
String? permissionType;
@ -64,10 +67,12 @@ class AllDevicesModel {
String? uuid;
int? batteryLevel;
String? productName;
List<DeviceSpaceModel>? spaces;
AllDevicesModel({
this.room,
this.unit,
this.community,
this.productUuid,
this.productType,
this.permissionType,
@ -92,6 +97,7 @@ class AllDevicesModel {
this.uuid,
this.batteryLevel,
this.productName,
this.spaces,
});
AllDevicesModel.fromJson(Map<String, dynamic> json) {
room = (json['room'] != null && (json['room'] is Map))
@ -100,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();
@ -124,6 +133,11 @@ class AllDevicesModel {
uuid = json['uuid']?.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) {
@ -162,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;
@ -186,6 +203,9 @@ class AllDevicesModel {
data['uuid'] = uuid;
data['battery'] = batteryLevel;
data['productName'] = productName;
if (spaces != null) {
data['spaces'] = spaces!.map((space) => space.toJson()).toList();
}
return data;
}

View File

@ -151,20 +151,33 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
'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.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}%'
: '-',

View File

@ -34,7 +34,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
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),
@ -51,7 +51,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
communityController,
200,
),
_buildSearchField("Unit Name", unitNameController, 200),
_buildSearchField("Space Name", unitNameController, 200),
_buildSearchField(
"Device Name / Product Name",
productNameController,

View File

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

View File

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

View File

@ -1,3 +1,4 @@
import 'dart:core';
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_status.dart';