base_project
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
class AppExceptions implements Exception {
|
||||
final String? _message;
|
||||
final String? _prefix;
|
||||
|
||||
AppExceptions([this._message, this._prefix]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "${_prefix ?? ''}${_message ?? 'An unknown error occurred'}";
|
||||
}
|
||||
}
|
||||
|
||||
// Network error when data fetch fails
|
||||
class FetchDataException extends AppExceptions {
|
||||
FetchDataException([String? message])
|
||||
: super(message ?? "Network Error: Failed to communicate with the server. Please check your internet connection and try again.",
|
||||
"Error During Communication: ");
|
||||
}
|
||||
|
||||
// Error for invalid or malformed requests
|
||||
class BadRequestException extends AppExceptions {
|
||||
BadRequestException([String? message])
|
||||
: super(message ?? "Client Error: The request sent to the server was malformed or contained invalid parameters.",
|
||||
"Invalid Request: ");
|
||||
}
|
||||
|
||||
// Error for unauthorized access
|
||||
class UnauthorizedException extends AppExceptions {
|
||||
UnauthorizedException([String? message])
|
||||
: super(message ?? "Authorization Error: You are not authorized to perform this action. Please log in with appropriate credentials.",
|
||||
"Unauthorized: ");
|
||||
}
|
||||
|
||||
// Error when a resource is not found
|
||||
class NotFoundException extends AppExceptions {
|
||||
NotFoundException([String? message])
|
||||
: super(message ?? "Resource Not Found: The requested resource could not be found on the server. It may have been moved or deleted.",
|
||||
"Not Found: ");
|
||||
}
|
||||
|
||||
// Error for server-side issues
|
||||
class InternalServerErrorException extends AppExceptions {
|
||||
InternalServerErrorException([String? message])
|
||||
: super(message ?? "Server Error: An unexpected error occurred on the server. Please try again later or contact support.",
|
||||
"Internal Server Error: ");
|
||||
}
|
||||
|
||||
// Error when user input is invalid
|
||||
class InvalidInputException extends AppExceptions {
|
||||
InvalidInputException([String? message])
|
||||
: super(message ?? "Validation Error: The provided input does not match the required format. Please correct the errors and try again.",
|
||||
"Invalid Input: ");
|
||||
}
|
||||
|
||||
// Error when a request times out
|
||||
class TimeoutException extends AppExceptions {
|
||||
TimeoutException([String? message])
|
||||
: super(message ?? "Request Timeout: The server took too long to respond. Please check your connection and try again.",
|
||||
"Timeout: ");
|
||||
}
|
||||
|
||||
// Error when a request conflicts with the current state
|
||||
class ConflictException extends AppExceptions {
|
||||
ConflictException([String? message])
|
||||
: super(message ?? "Conflict Error: The request could not be processed because of a conflict with the current state of the resource.",
|
||||
"Conflict: ");
|
||||
}
|
||||
|
||||
// Error when the service is unavailable
|
||||
class ServiceUnavailableException extends AppExceptions {
|
||||
ServiceUnavailableException([String? message])
|
||||
: super(message ?? "Service Unavailable: The server is currently unable to handle the request. Please try again later.",
|
||||
"Service Unavailable: ");
|
||||
}
|
||||
|
||||
// Error when access to a resource is forbidden
|
||||
class ForbiddenException extends AppExceptions {
|
||||
ForbiddenException([String? message])
|
||||
: super(message ?? "Forbidden: You do not have the necessary permissions to access this resource.",
|
||||
"Forbidden: ");
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
abstract class BaseNetworkService {
|
||||
Future<dynamic> getGetApiResponse(String? url);
|
||||
Future<dynamic> getPostApiResponse(String? url, dynamic body);
|
||||
Future<dynamic> getPutApiResponse(String? url, dynamic body);
|
||||
|
||||
Future<dynamic> getDeleteApiResponse(String? url);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
import 'dart:io';
|
||||
import 'package:base_project/utils/managers/user_manager.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import '../exceptions/app_exceptions.dart';
|
||||
import 'base_network_service.dart';
|
||||
|
||||
class NetworkApiService extends BaseNetworkService {
|
||||
final Dio _dio = Dio();
|
||||
|
||||
NetworkApiService() {
|
||||
// Optionally configure Dio, e.g. add interceptors
|
||||
_dio.options.connectTimeout = const Duration(seconds: 30); // 30 seconds
|
||||
_dio.options.receiveTimeout = const Duration(seconds: 30);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> getGetApiResponse(String? url) async {
|
||||
try {
|
||||
final token = UserManager().token;
|
||||
|
||||
// print("token..$token");
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json', // Add other headers if needed
|
||||
};
|
||||
final response = await _dio.get(
|
||||
url!,
|
||||
options: Options(headers: headers),
|
||||
);
|
||||
return _handleResponse(response);
|
||||
} on DioException catch (e) {
|
||||
return _handleDioError(e);
|
||||
} on SocketException {
|
||||
throw FetchDataException('No Internet Connection');
|
||||
} catch (e) {
|
||||
throw FetchDataException('An unexpected error occurred: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> getPostApiResponse(String? url, dynamic body) async {
|
||||
try {
|
||||
final token = UserManager().token;
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json', // Add other headers if needed
|
||||
};
|
||||
final response = await _dio.post(
|
||||
url!,
|
||||
data: body,
|
||||
options: Options(headers: headers),
|
||||
);
|
||||
return _handleResponse(response);
|
||||
} on DioException catch (e) {
|
||||
return _handleDioError(e);
|
||||
} on SocketException {
|
||||
throw FetchDataException('No Internet Connection');
|
||||
} catch (e) {
|
||||
throw FetchDataException('An unexpected error occurred: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> getPutApiResponse(String? url, dynamic body) async {
|
||||
try {
|
||||
final token = UserManager().token;
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json', // Add other headers if needed
|
||||
};
|
||||
final response = await _dio.put(
|
||||
url!,
|
||||
data: body,
|
||||
options: Options(headers: headers),
|
||||
);
|
||||
return _handleResponse(response);
|
||||
} on DioException catch (e) {
|
||||
return _handleDioError(e);
|
||||
} on SocketException {
|
||||
throw FetchDataException('No Internet Connection');
|
||||
} catch (e) {
|
||||
throw FetchDataException('An unexpected error occurred: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> getDeleteApiResponse(String? url) async {
|
||||
try {
|
||||
final token = UserManager().token;
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json', // Add other headers if needed
|
||||
};
|
||||
final response = await _dio.delete(
|
||||
url!,
|
||||
options: Options(headers: headers),
|
||||
);
|
||||
return _handleResponse(response);
|
||||
} on DioException catch (e) {
|
||||
return _handleDioError(e);
|
||||
} on SocketException {
|
||||
throw FetchDataException('No Internet Connection');
|
||||
} catch (e) {
|
||||
throw FetchDataException('An unexpected error occurred: $e');
|
||||
}
|
||||
}
|
||||
|
||||
dynamic _handleResponse(Response response) {
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
case 201:
|
||||
try {
|
||||
// Handle empty body
|
||||
if (response.data == null || response.data.toString().isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw FetchDataException('Error parsing response: $e');
|
||||
}
|
||||
case 400:
|
||||
throw BadRequestException('Bad request: ${response.data}');
|
||||
case 401:
|
||||
throw UnauthorizedException('Unauthorized request: ${response.data}');
|
||||
case 403:
|
||||
throw ForbiddenException('Forbidden request: ${response.data}');
|
||||
case 404:
|
||||
throw NotFoundException('Not found: ${response.data}');
|
||||
case 500:
|
||||
throw InternalServerErrorException('Server error: ${response.data}');
|
||||
default:
|
||||
throw FetchDataException(
|
||||
'Error while communicating with server: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
|
||||
dynamic _handleDioError(DioException error) {
|
||||
switch (error.type) {
|
||||
case DioExceptionType.connectionTimeout:
|
||||
case DioExceptionType.sendTimeout:
|
||||
case DioExceptionType.receiveTimeout:
|
||||
throw FetchDataException("Request timed out.");
|
||||
case DioExceptionType.badResponse:
|
||||
return _handleResponse(error.response!);
|
||||
case DioExceptionType.cancel:
|
||||
throw FetchDataException("Request was cancelled.");
|
||||
case DioExceptionType.connectionError:
|
||||
throw FetchDataException("Connection failed due to internet issue.");
|
||||
default:
|
||||
throw FetchDataException("Unexpected error occurred.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
import '../exceptions/app_exceptions.dart';
|
||||
import 'no_token_base_network_service.dart';
|
||||
|
||||
class NoTokenNetworkApiService extends NoTokenBaseNetworkService {
|
||||
final Dio _dio = Dio();
|
||||
|
||||
NetworkApiService() {
|
||||
// Optionally configure Dio, e.g. add interceptors
|
||||
_dio.options.connectTimeout = const Duration(seconds: 30); // 30 seconds
|
||||
_dio.options.receiveTimeout = const Duration(seconds: 30);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> getGetApiResponse(String? url) async {
|
||||
try {
|
||||
final headers = {
|
||||
'Content-Type': 'application/json', // Add other headers if needed
|
||||
};
|
||||
final response = await _dio.get(
|
||||
url!,
|
||||
options: Options(headers: headers),
|
||||
);
|
||||
return _handleResponse(response);
|
||||
} on DioException catch (e) {
|
||||
return _handleDioError(e);
|
||||
} on SocketException {
|
||||
throw FetchDataException('No Internet Connection');
|
||||
} catch (e) {
|
||||
throw FetchDataException('An unexpected error occurred: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> getPostApiResponse(String? url, dynamic body) async {
|
||||
try {
|
||||
final headers = {
|
||||
'Content-Type': 'application/json', // Add other headers if needed
|
||||
};
|
||||
final response = await _dio.post(
|
||||
url!,
|
||||
data: body,
|
||||
options: Options(headers: headers),
|
||||
);
|
||||
return _handleResponse(response);
|
||||
} on DioException catch (e) {
|
||||
return _handleDioError(e);
|
||||
} on SocketException {
|
||||
throw FetchDataException('No Internet Connection');
|
||||
} catch (e) {
|
||||
throw FetchDataException('An unexpected error occurred: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> getPutApiResponse(String? url, dynamic body) async {
|
||||
try {
|
||||
final headers = {
|
||||
'Content-Type': 'application/json', // Add other headers if needed
|
||||
};
|
||||
final response = await _dio.put(
|
||||
url!,
|
||||
data: body,
|
||||
options: Options(headers: headers),
|
||||
);
|
||||
return _handleResponse(response);
|
||||
} on DioException catch (e) {
|
||||
return _handleDioError(e);
|
||||
} on SocketException {
|
||||
throw FetchDataException('No Internet Connection');
|
||||
} catch (e) {
|
||||
throw FetchDataException('An unexpected error occurred: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> getDeleteApiResponse(String? url) async {
|
||||
try {
|
||||
final headers = {
|
||||
'Content-Type': 'application/json', // Add other headers if needed
|
||||
};
|
||||
final response = await _dio.delete(
|
||||
url!,
|
||||
options: Options(headers: headers),
|
||||
);
|
||||
return _handleResponse(response);
|
||||
} on DioException catch (e) {
|
||||
return _handleDioError(e);
|
||||
} on SocketException {
|
||||
throw FetchDataException('No Internet Connection');
|
||||
} catch (e) {
|
||||
throw FetchDataException('An unexpected error occurred: $e');
|
||||
}
|
||||
}
|
||||
|
||||
dynamic _handleResponse(Response response) {
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
case 201:
|
||||
try {
|
||||
// Handle empty body
|
||||
if (response.data == null || response.data.toString().isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw FetchDataException('Error parsing response: $e');
|
||||
}
|
||||
case 400:
|
||||
throw BadRequestException('Bad request: ${response.data}');
|
||||
case 401:
|
||||
throw UnauthorizedException('Unauthorized request: ${response.data}');
|
||||
case 403:
|
||||
throw ForbiddenException('Forbidden request: ${response.data}');
|
||||
case 404:
|
||||
throw NotFoundException('Not found: ${response.data}');
|
||||
case 500:
|
||||
throw InternalServerErrorException('Server error: ${response.data}');
|
||||
default:
|
||||
throw FetchDataException(
|
||||
'Error while communicating with server: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
|
||||
dynamic _handleDioError(DioException error) {
|
||||
switch (error.type) {
|
||||
case DioExceptionType.connectionTimeout:
|
||||
case DioExceptionType.sendTimeout:
|
||||
case DioExceptionType.receiveTimeout:
|
||||
throw FetchDataException("Request timed out.");
|
||||
case DioExceptionType.badResponse:
|
||||
return _handleResponse(error.response!);
|
||||
case DioExceptionType.cancel:
|
||||
throw FetchDataException("Request was cancelled.");
|
||||
case DioExceptionType.connectionError:
|
||||
throw FetchDataException("Connection failed due to internet issue.");
|
||||
default:
|
||||
throw FetchDataException("Unexpected error occurred.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
abstract class NoTokenBaseNetworkService {
|
||||
Future<dynamic> getGetApiResponse(String? url);
|
||||
Future<dynamic> getPostApiResponse(String? url, dynamic body);
|
||||
Future<dynamic> getPutApiResponse(String? url, dynamic body);
|
||||
|
||||
Future<dynamic> getDeleteApiResponse(String? url);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
// class NotificationService {
|
||||
// final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
|
||||
// Future<void> initialize() async {
|
||||
// const AndroidInitializationSettings initializationSettingsAndroid =
|
||||
// AndroidInitializationSettings('@mipmap/ic_launcher');
|
||||
|
||||
// const InitializationSettings initializationSettings =
|
||||
// InitializationSettings(android: initializationSettingsAndroid);
|
||||
|
||||
// await flutterLocalNotificationsPlugin.initialize(initializationSettings);
|
||||
// }
|
||||
|
||||
// Future<void> showNotification(int id, String title, String body) async {
|
||||
// const AndroidNotificationDetails androidPlatformChannelSpecifics =
|
||||
// AndroidNotificationDetails(
|
||||
// 'channel_id',
|
||||
// 'channel_name',
|
||||
// channelDescription: 'channel_description',
|
||||
// importance: Importance.max,
|
||||
// priority: Priority.high,
|
||||
// );
|
||||
|
||||
// const NotificationDetails platformChannelSpecifics =
|
||||
// NotificationDetails(android: androidPlatformChannelSpecifics);
|
||||
|
||||
// await flutterLocalNotificationsPlugin.show(
|
||||
// id,
|
||||
// title,
|
||||
// body,
|
||||
// platformChannelSpecifics,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:base_project/data/response/status.dart';
|
||||
|
||||
class ApiResponse<T> {
|
||||
Status? status;
|
||||
T? data;
|
||||
String? message;
|
||||
|
||||
ApiResponse(this.status, this.data, this.message);
|
||||
|
||||
// Named constructor for loading state
|
||||
ApiResponse.loading() : status = Status.LOADING;
|
||||
|
||||
// Named constructor for completed state
|
||||
ApiResponse.success(this.data) : status = Status.SUCCESS;
|
||||
|
||||
// Named constructor for error state
|
||||
ApiResponse.error(this.message) : status = Status.ERROR;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "Status: $status \n Message: $message \n Data: $data";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
enum Status {LOADING,SUCCESS,ERROR}
|
||||
Reference in New Issue
Block a user