Files
retail/lib/features/auth/data/datasources/auth_remote_datasource.dart
Phuoc Nguyen 04f7042b8d update api
2025-10-10 17:15:40 +07:00

160 lines
5.2 KiB
Dart

import 'package:dio/dio.dart';
import '../../../../core/constants/api_constants.dart';
import '../../../../core/errors/exceptions.dart';
import '../../../../core/network/dio_client.dart';
import '../models/auth_response_model.dart';
import '../models/login_dto.dart';
import '../models/register_dto.dart';
import '../models/user_model.dart';
/// Remote data source for authentication operations
abstract class AuthRemoteDataSource {
/// Login user with email and password
Future<AuthResponseModel> login(LoginDto loginDto);
/// Register new user
Future<AuthResponseModel> register(RegisterDto registerDto);
/// Get current user profile
Future<UserModel> getProfile();
/// Refresh access token
Future<AuthResponseModel> refreshToken();
}
/// Implementation of AuthRemoteDataSource
class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
final DioClient dioClient;
AuthRemoteDataSourceImpl({required this.dioClient});
@override
Future<AuthResponseModel> login(LoginDto loginDto) async {
try {
final response = await dioClient.post(
ApiConstants.login,
data: loginDto.toJson(),
);
if (response.statusCode == ApiConstants.statusOk) {
return AuthResponseModel.fromJson(response.data);
} else {
throw ServerException('Login failed with status: ${response.statusCode}');
}
} on DioException catch (e) {
throw _handleDioError(e);
} catch (e) {
throw ServerException('Unexpected error during login: $e');
}
}
@override
Future<AuthResponseModel> register(RegisterDto registerDto) async {
try {
final response = await dioClient.post(
ApiConstants.register,
data: registerDto.toJson(),
);
if (response.statusCode == ApiConstants.statusCreated) {
return AuthResponseModel.fromJson(response.data);
} else {
throw ServerException('Registration failed with status: ${response.statusCode}');
}
} on DioException catch (e) {
throw _handleDioError(e);
} catch (e) {
throw ServerException('Unexpected error during registration: $e');
}
}
@override
Future<UserModel> getProfile() async {
try {
final response = await dioClient.get(ApiConstants.profile);
if (response.statusCode == ApiConstants.statusOk) {
return UserModel.fromJson(response.data);
} else {
throw ServerException('Get profile failed with status: ${response.statusCode}');
}
} on DioException catch (e) {
throw _handleDioError(e);
} catch (e) {
throw ServerException('Unexpected error getting profile: $e');
}
}
@override
Future<AuthResponseModel> refreshToken() async {
try {
final response = await dioClient.post(ApiConstants.refreshToken);
if (response.statusCode == ApiConstants.statusOk) {
return AuthResponseModel.fromJson(response.data);
} else {
throw ServerException('Token refresh failed with status: ${response.statusCode}');
}
} on DioException catch (e) {
throw _handleDioError(e);
} catch (e) {
throw ServerException('Unexpected error refreshing token: $e');
}
}
/// Handle Dio errors and convert to custom exceptions
Exception _handleDioError(DioException error) {
switch (error.type) {
case DioExceptionType.connectionTimeout:
case DioExceptionType.sendTimeout:
case DioExceptionType.receiveTimeout:
return NetworkException('Connection timeout. Please check your internet connection.');
case DioExceptionType.badResponse:
final statusCode = error.response?.statusCode;
final message = error.response?.data?['message'] ?? error.message;
switch (statusCode) {
case ApiConstants.statusUnauthorized:
return InvalidCredentialsException(message ?? 'Invalid email or password');
case ApiConstants.statusForbidden:
return UnauthorizedException(message ?? 'Access forbidden');
case ApiConstants.statusNotFound:
return NotFoundException(message ?? 'Resource not found');
case ApiConstants.statusUnprocessableEntity:
return ValidationException(message ?? 'Validation failed');
case 409: // Conflict
return ConflictException(message ?? 'Email already exists');
case ApiConstants.statusTooManyRequests:
return ServerException('Too many requests. Please try again later.');
case ApiConstants.statusInternalServerError:
case ApiConstants.statusBadGateway:
case ApiConstants.statusServiceUnavailable:
case ApiConstants.statusGatewayTimeout:
return ServerException(message ?? 'Server error. Please try again later.');
default:
return ServerException(message ?? 'Unknown error occurred');
}
case DioExceptionType.connectionError:
return NetworkException('No internet connection. Please check your network.');
case DioExceptionType.badCertificate:
return NetworkException('SSL certificate error');
case DioExceptionType.cancel:
return NetworkException('Request was cancelled');
default:
return ServerException(error.message ?? 'Unknown error occurred');
}
}
}