Implemented devices bloc, service, param and model.

This commit is contained in:
Faris Armoush
2025-06-16 15:39:40 +03:00
parent 2108622b5b
commit 3eb38d28f7
7 changed files with 225 additions and 0 deletions

View File

@ -0,0 +1,47 @@
import 'package:dio/dio.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/models/device_model.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/services/device_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart';
class RemoteDeviceService implements DeviceService {
final HTTPService _httpService;
RemoteDeviceService({
required HTTPService httpService,
}) : _httpService = httpService;
static const _defaultErrorMessage = 'Failed to load devices';
@override
Future<List<DeviceModel>> getDevices(LoadDevicesParam param) async {
try {
final response = await _httpService.get(
path: 'devices',
queryParameters: {
'spaceUuid': param.spaceUuid,
if (param.type != null) 'type': param.type,
if (param.status != null) 'status': param.status,
},
expectedResponseModel: (data) {
return (data as List)
.map((e) => DeviceModel.fromJson(e as Map<String, dynamic>))
.toList();
},
);
return response;
} on DioException catch (e) {
final message = e.response?.data as Map<String, dynamic>?;
final error = message?['error'] as Map<String, dynamic>?;
final errorMessage = error?['error'] as String? ?? '';
final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(
': ',
);
throw APIException(formattedErrorMessage);
} catch (e) {
final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': ');
throw APIException(formattedErrorMessage);
}
}
}

View File

@ -0,0 +1,82 @@
import 'package:equatable/equatable.dart';
class DeviceModel extends Equatable {
final String uuid;
final String name;
final String type;
final String status;
final String lastSeen;
final String spaceUuid;
final List<DeviceCapability> capabilities;
const DeviceModel({
required this.uuid,
required this.name,
required this.type,
required this.status,
required this.lastSeen,
required this.spaceUuid,
required this.capabilities,
});
factory DeviceModel.fromJson(Map<String, dynamic> json) {
return DeviceModel(
uuid: json['uuid'] as String,
name: json['name'] as String,
type: json['type'] as String,
status: json['status'] as String,
lastSeen: json['lastSeen'] as String,
spaceUuid: json['spaceUuid'] as String,
capabilities: (json['capabilities'] as List)
.map((e) => DeviceCapability.fromJson(e as Map<String, dynamic>))
.toList(),
);
}
Map<String, dynamic> toJson() {
return {
'uuid': uuid,
'name': name,
'type': type,
'status': status,
'lastSeen': lastSeen,
'spaceUuid': spaceUuid,
'capabilities': capabilities.map((e) => e.toJson()).toList(),
};
}
@override
List<Object?> get props =>
[uuid, name, type, status, lastSeen, spaceUuid, capabilities];
}
class DeviceCapability extends Equatable {
final String name;
final String type;
final Map<String, dynamic> config;
const DeviceCapability({
required this.name,
required this.type,
required this.config,
});
factory DeviceCapability.fromJson(Map<String, dynamic> json) {
return DeviceCapability(
name: json['name'] as String,
type: json['type'] as String,
config: json['config'] as Map<String, dynamic>,
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'type': type,
'config': config,
};
}
@override
List<Object?> get props => [name, type, config];
}

View File

@ -0,0 +1,11 @@
class LoadDevicesParam {
final String spaceUuid;
final String? type;
final String? status;
const LoadDevicesParam({
required this.spaceUuid,
this.type,
this.status,
});
}

View File

@ -0,0 +1,6 @@
import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/models/device_model.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart';
abstract class DeviceService {
Future<List<DeviceModel>> getDevices(LoadDevicesParam param);
}

View File

@ -0,0 +1,32 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/models/device_model.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/params/load_devices_param.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/devices/domain/services/device_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
part 'device_event.dart';
part 'device_state.dart';
class DeviceBloc extends Bloc<DeviceEvent, DeviceState> {
final DeviceService _deviceService;
DeviceBloc(this._deviceService) : super(DeviceInitial()) {
on<LoadDevices>(_onLoadDevices);
}
Future<void> _onLoadDevices(
LoadDevices event,
Emitter<DeviceState> emit,
) async {
emit(DeviceLoading());
try {
final devices = await _deviceService.getDevices(event.param);
emit(DeviceLoaded(devices));
} on APIException catch (e) {
emit(DeviceFailure(e.message));
} catch (e) {
emit(DeviceFailure(e.toString()));
}
}
}

View File

@ -0,0 +1,17 @@
part of 'device_bloc.dart';
sealed class DeviceEvent extends Equatable {
const DeviceEvent();
@override
List<Object> get props => [];
}
final class LoadDevices extends DeviceEvent {
const LoadDevices(this.param);
final LoadDevicesParam param;
@override
List<Object> get props => [param];
}

View File

@ -0,0 +1,30 @@
part of 'device_bloc.dart';
sealed class DeviceState extends Equatable {
const DeviceState();
@override
List<Object> get props => [];
}
final class DeviceInitial extends DeviceState {}
final class DeviceLoading extends DeviceState {}
final class DeviceLoaded extends DeviceState {
final List<DeviceModel> devices;
const DeviceLoaded(this.devices);
@override
List<Object> get props => [devices];
}
final class DeviceFailure extends DeviceState {
final String message;
const DeviceFailure(this.message);
@override
List<Object> get props => [message];
}