mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
build main structure and build data layer and space managment bloc
This commit is contained in:
16
lib/core/network/custom_exceptions.dart
Normal file
16
lib/core/network/custom_exceptions.dart
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
import 'enums.dart';
|
||||||
|
|
||||||
|
class GenericException implements Exception {
|
||||||
|
final ExceptionType type;
|
||||||
|
final String errorMessage;
|
||||||
|
const GenericException(
|
||||||
|
{required this.type, this.errorMessage = "Unknown Error"});
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object?> get props => [type, errorMessage];
|
||||||
|
}
|
36
lib/core/network/dio.dart
Normal file
36
lib/core/network/dio.dart
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
import '../../utils/constants/api_const.dart';
|
||||||
|
|
||||||
|
class DioInstance {
|
||||||
|
Dio? _dio;
|
||||||
|
|
||||||
|
Dio get dio => _dio ?? _instantiate();
|
||||||
|
|
||||||
|
String? baseUrl;
|
||||||
|
|
||||||
|
DioInstance({this.baseUrl});
|
||||||
|
|
||||||
|
Dio _instantiate() {
|
||||||
|
Dio dio = Dio(
|
||||||
|
BaseOptions(
|
||||||
|
baseUrl: baseUrl ?? '${ApiEndpoints.baseUrl}/',
|
||||||
|
receiveDataWhenStatusError: true,
|
||||||
|
headers: {
|
||||||
|
'content_Type': 'application/json',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
dio.interceptors.add(
|
||||||
|
LogInterceptor(
|
||||||
|
responseHeader: false,
|
||||||
|
requestHeader: false,
|
||||||
|
requestBody: true,
|
||||||
|
responseBody: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return dio;
|
||||||
|
}
|
||||||
|
}
|
3
lib/core/network/end_points.dart
Normal file
3
lib/core/network/end_points.dart
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class EndPoints {
|
||||||
|
static const String fetchCommunities = 'projects/{projectUuid}/communities';
|
||||||
|
}
|
50
lib/core/network/enums.dart
Normal file
50
lib/core/network/enums.dart
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
enum RequestType {
|
||||||
|
get,
|
||||||
|
post,
|
||||||
|
delete,
|
||||||
|
put,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ExceptionType {
|
||||||
|
notAuthenticated,
|
||||||
|
connectionError,
|
||||||
|
// related to http status code exceptions
|
||||||
|
notAuthorized,
|
||||||
|
notFound,
|
||||||
|
internalServerException,
|
||||||
|
serviceUnavailableException,
|
||||||
|
pageGone,
|
||||||
|
|
||||||
|
// related to bad request status code
|
||||||
|
// related to auth requests
|
||||||
|
invalidCredentials,
|
||||||
|
solutionAlreadySunmitted,
|
||||||
|
invalidValidation,
|
||||||
|
// other
|
||||||
|
other,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ExceptionMessage {
|
||||||
|
NOT_AUTHENTICATED,
|
||||||
|
INVALID_CREDENTIALS,
|
||||||
|
The_password_field_must_be_at_least_8_characters,
|
||||||
|
SOLUTION_ALREADY_SUBMITTED,
|
||||||
|
you_are_not_authorized,
|
||||||
|
page_not_found,
|
||||||
|
page_gone,
|
||||||
|
INTERNAL_SERVER_ERROR,
|
||||||
|
service_unavailable,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NotificationsType {
|
||||||
|
payment,
|
||||||
|
transporation,
|
||||||
|
product,
|
||||||
|
zero,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ImagesType {
|
||||||
|
assets,
|
||||||
|
svg,
|
||||||
|
network,
|
||||||
|
}
|
121
lib/core/network/request.dart
Normal file
121
lib/core/network/request.dart
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
|
|
||||||
|
import '../../pages/auth/model/token.dart';
|
||||||
|
import 'custom_exceptions.dart';
|
||||||
|
import 'dio.dart';
|
||||||
|
import 'enums.dart';
|
||||||
|
|
||||||
|
class Request {
|
||||||
|
String endPoint;
|
||||||
|
bool? autherized;
|
||||||
|
bool? isFormData;
|
||||||
|
RequestType? method;
|
||||||
|
Map<String, dynamic>? headers;
|
||||||
|
final Map<String, dynamic>? queryParams;
|
||||||
|
Map<String, dynamic>? body;
|
||||||
|
Duration? receiveTimeout;
|
||||||
|
Request(
|
||||||
|
this.endPoint, {
|
||||||
|
this.autherized,
|
||||||
|
this.isFormData,
|
||||||
|
this.method,
|
||||||
|
this.headers,
|
||||||
|
this.queryParams,
|
||||||
|
this.body,
|
||||||
|
this.receiveTimeout,
|
||||||
|
}) {
|
||||||
|
headers = {
|
||||||
|
'content_Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Future<Map<String, dynamic>> sendRequest() async {
|
||||||
|
Response? response;
|
||||||
|
if (autherized != null && autherized!) {
|
||||||
|
final storage = const FlutterSecureStorage();
|
||||||
|
final token = await storage.read(key: Token.loginAccessTokenKey);
|
||||||
|
if (token != null) {
|
||||||
|
headers!["authorization"] = "Bearer $token";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
response = await DioInstance().dio.request(
|
||||||
|
endPoint,
|
||||||
|
queryParameters: queryParams,
|
||||||
|
data: isFormData != null && isFormData == true
|
||||||
|
? FormData.fromMap(body!)
|
||||||
|
: body,
|
||||||
|
options: Options(
|
||||||
|
method: method!.name.toUpperCase(),
|
||||||
|
headers: headers,
|
||||||
|
contentType: 'application/json',
|
||||||
|
receiveTimeout: receiveTimeout,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (response.statusCode! >= 200 && response.statusCode! < 300) {
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
} on DioException catch (error) {
|
||||||
|
if (error.type == DioExceptionType.badResponse) {
|
||||||
|
throw badRequestException[error.response!.data["error"]] ??
|
||||||
|
const GenericException(
|
||||||
|
type: ExceptionType.other,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (error.type == DioExceptionType.connectionError ||
|
||||||
|
error.type == DioExceptionType.connectionTimeout ||
|
||||||
|
error.type == DioExceptionType.receiveTimeout ||
|
||||||
|
error.type == DioExceptionType.sendTimeout ||
|
||||||
|
error.type == DioExceptionType.unknown) {
|
||||||
|
throw const GenericException(
|
||||||
|
type: ExceptionType.connectionError,
|
||||||
|
errorMessage: 'no_internet_connection',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'endPoint': endPoint,
|
||||||
|
'method': method!.name.toUpperCase(),
|
||||||
|
'body': json.encode(body),
|
||||||
|
'headers': headers,
|
||||||
|
'queryParams': queryParams,
|
||||||
|
'autherized': autherized,
|
||||||
|
'isFormData': isFormData,
|
||||||
|
};
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return jsonEncode(toJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object?> get props => [
|
||||||
|
endPoint,
|
||||||
|
autherized,
|
||||||
|
isFormData,
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
queryParams,
|
||||||
|
body,
|
||||||
|
receiveTimeout,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, GenericException> badRequestException = {
|
||||||
|
ExceptionMessage.INVALID_CREDENTIALS.name: const GenericException(
|
||||||
|
type: ExceptionType.invalidCredentials,
|
||||||
|
errorMessage: "Invalid credentials ...",
|
||||||
|
),
|
||||||
|
"The password field must be at least 8 characters.": const GenericException(
|
||||||
|
type: ExceptionType.invalidValidation,
|
||||||
|
errorMessage: 'password must be 8 or more characters',
|
||||||
|
),
|
||||||
|
ExceptionMessage.NOT_AUTHENTICATED.name: const GenericException(
|
||||||
|
type: ExceptionType.notAuthenticated,
|
||||||
|
errorMessage: "not authenticated",
|
||||||
|
),
|
||||||
|
};
|
@ -0,0 +1,37 @@
|
|||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
|
|
||||||
|
import '../../data/models/community_model.dart';
|
||||||
|
import '../../data/sources/space_managment_remote_source.dart';
|
||||||
|
|
||||||
|
part 'communities_event.dart';
|
||||||
|
part 'communities_state.dart';
|
||||||
|
|
||||||
|
class CommunitiesBloc extends Bloc<CommunitiesEvent, CommunitiesState> {
|
||||||
|
SpaceManagementRemoteSource spaceManagementRemoteSource =
|
||||||
|
SpaceManagementRemoteSource();
|
||||||
|
CommunitiesBloc() : super(CommunitiesInitial()) {
|
||||||
|
on<CommunitiesEvent>((event, emit) {
|
||||||
|
if (event is FetchCommunitiesEvent) {
|
||||||
|
_fetchCommunities(emit);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchCommunities(Emitter<CommunitiesState> emit) async {
|
||||||
|
String? projectUuid = await ProjectManager.getProjectUUID();
|
||||||
|
if (projectUuid == null) {
|
||||||
|
emit(const CommunitiesError("Project UUID is null"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit(CommunitiesLoading());
|
||||||
|
try {
|
||||||
|
final communities =
|
||||||
|
await spaceManagementRemoteSource.fetchCommunities(projectUuid);
|
||||||
|
emit(CommunitiesLoaded(communities));
|
||||||
|
} catch (e) {
|
||||||
|
emit(CommunitiesError(e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
part of 'communities_bloc.dart';
|
||||||
|
|
||||||
|
sealed class CommunitiesEvent extends Equatable {
|
||||||
|
const CommunitiesEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class FetchCommunitiesEvent extends CommunitiesEvent {}
|
@ -0,0 +1,30 @@
|
|||||||
|
part of 'communities_bloc.dart';
|
||||||
|
|
||||||
|
sealed class CommunitiesState extends Equatable {
|
||||||
|
const CommunitiesState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
final class CommunitiesInitial extends CommunitiesState {}
|
||||||
|
|
||||||
|
final class CommunitiesLoading extends CommunitiesState {}
|
||||||
|
|
||||||
|
final class CommunitiesLoaded extends CommunitiesState {
|
||||||
|
final List<CommunityModel> communities;
|
||||||
|
|
||||||
|
const CommunitiesLoaded(this.communities);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [communities];
|
||||||
|
}
|
||||||
|
|
||||||
|
final class CommunitiesError extends CommunitiesState {
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
const CommunitiesError(this.message);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
import 'package:syncrow_web/pages/spaces_management/refactor/data/models/space_model.dart';
|
||||||
|
|
||||||
|
class CommunityModel {
|
||||||
|
String id, name;
|
||||||
|
List<SpaceModel>? spaces;
|
||||||
|
CommunityModel({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
this.spaces,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory CommunityModel.fromJson(Map<String, dynamic> json) => CommunityModel(
|
||||||
|
id: json['id'],
|
||||||
|
name: json['name'],
|
||||||
|
spaces: SpaceModel.fromJsonList(json['spaces']),
|
||||||
|
);
|
||||||
|
|
||||||
|
static List<CommunityModel> fromJsonList(List<dynamic> jsonList) {
|
||||||
|
return jsonList.map((json) => CommunityModel.fromJson(json)).toList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
class DeviceModel {
|
||||||
|
String id, name, tag;
|
||||||
|
String location;
|
||||||
|
DeviceModel({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.tag,
|
||||||
|
required this.location,
|
||||||
|
});
|
||||||
|
factory DeviceModel.fromJson(Map<String, dynamic> json) => DeviceModel(
|
||||||
|
id: json['id'],
|
||||||
|
name: json['name'],
|
||||||
|
tag: json['tag'],
|
||||||
|
location: json['location'],
|
||||||
|
);
|
||||||
|
|
||||||
|
static List<DeviceModel> fromJsonList(List<dynamic> jsonList) {
|
||||||
|
return jsonList.map((json) => DeviceModel.fromJson(json)).toList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
import 'device_model.dart';
|
||||||
|
|
||||||
|
class SpaceModel {
|
||||||
|
String id, parentId, name;
|
||||||
|
List<SpaceModel>? spaces;
|
||||||
|
List<DeviceModel>? devices;
|
||||||
|
|
||||||
|
SpaceModel({
|
||||||
|
required this.id,
|
||||||
|
required this.parentId,
|
||||||
|
required this.name,
|
||||||
|
this.spaces,
|
||||||
|
this.devices,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory SpaceModel.fromJson(Map<String, dynamic> json) => SpaceModel(
|
||||||
|
id: json['id'],
|
||||||
|
parentId: json['parentId'],
|
||||||
|
name: json['name'],
|
||||||
|
spaces: SpaceModel.fromJsonList(json['spaces']),
|
||||||
|
devices: DeviceModel.fromJsonList(json['devices']),
|
||||||
|
);
|
||||||
|
|
||||||
|
static List<SpaceModel> fromJsonList(List<dynamic> jsonList) {
|
||||||
|
return jsonList.map((json) => SpaceModel.fromJson(json)).toList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
import 'device_model.dart';
|
||||||
|
|
||||||
|
class SubSpaceModel {
|
||||||
|
String id, name;
|
||||||
|
List<DeviceModel>? devices;
|
||||||
|
SubSpaceModel({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
this.devices,
|
||||||
|
});
|
||||||
|
factory SubSpaceModel.fromJson(Map<String, dynamic> json) => SubSpaceModel(
|
||||||
|
id: json['id'],
|
||||||
|
name: json['name'],
|
||||||
|
devices: DeviceModel.fromJsonList(json['devices']),
|
||||||
|
);
|
||||||
|
static List<SubSpaceModel> fromJsonList(List<dynamic> jsonList) {
|
||||||
|
return jsonList.map((json) => SubSpaceModel.fromJson(json)).toList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import 'package:syncrow_web/core/network/end_points.dart';
|
||||||
|
import 'package:syncrow_web/core/network/enums.dart';
|
||||||
|
import 'package:syncrow_web/core/network/request.dart';
|
||||||
|
|
||||||
|
import '../models/community_model.dart';
|
||||||
|
|
||||||
|
class SpaceManagementRemoteSource {
|
||||||
|
Future<List<CommunityModel>> fetchCommunities(String projectUuid) async {
|
||||||
|
Request request = Request(
|
||||||
|
EndPoints.fetchCommunities.replaceFirst('{projectUuid}', projectUuid),
|
||||||
|
method: RequestType.get,
|
||||||
|
autherized: true,
|
||||||
|
);
|
||||||
|
final response = await request.sendRequest();
|
||||||
|
return CommunityModel.fromJsonList((response['data']));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user