This commit is contained in:
2025-10-28 00:09:46 +07:00
parent 9ebe7c2919
commit de49f564b1
110 changed files with 15392 additions and 3996 deletions

View File

@@ -0,0 +1,147 @@
import '../../../../core/constants/api_endpoints.dart';
import '../../../../core/errors/exceptions.dart';
import '../../../../core/network/api_client.dart';
import '../../../../core/network/api_response.dart';
import '../models/login_request_model.dart';
import '../models/user_model.dart';
/// Abstract interface for authentication remote data source
///
/// Defines the contract for authentication-related API operations
abstract class AuthRemoteDataSource {
/// Login with username and password
///
/// Throws [ServerException] if the login fails
/// Returns [UserModel] on successful login
Future<UserModel> login(LoginRequestModel request);
/// Logout current user
///
/// Throws [ServerException] if logout fails
Future<void> logout();
/// Refresh access token using refresh token
///
/// Throws [ServerException] if refresh fails
/// Returns new [UserModel] with updated tokens
Future<UserModel> refreshToken(String refreshToken);
}
/// Implementation of AuthRemoteDataSource using ApiClient
///
/// Handles all authentication-related API calls
class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
final ApiClient apiClient;
AuthRemoteDataSourceImpl(this.apiClient);
@override
Future<UserModel> login(LoginRequestModel request) async {
try {
// Make POST request to login endpoint
final response = await apiClient.post(
ApiEndpoints.login,
data: request.toJson(),
);
// Parse API response with ApiResponse wrapper
final apiResponse = ApiResponse.fromJson(
response.data as Map<String, dynamic>,
(json) => UserModel.fromJson(
json as Map<String, dynamic>,
username: request.username, // Pass username since API doesn't return it
),
);
// Check if login was successful
if (apiResponse.isSuccess && apiResponse.value != null) {
return apiResponse.value!;
} else {
// Extract error message from API response
final errorMessage = apiResponse.errors.isNotEmpty
? apiResponse.errors.first
: 'Login failed';
throw ServerException(
errorMessage,
code: apiResponse.errorCodes.isNotEmpty
? apiResponse.errorCodes.first
: null,
);
}
} on ServerException {
rethrow;
} catch (e) {
throw ServerException('Failed to login: ${e.toString()}');
}
}
@override
Future<void> logout() async {
try {
// Make POST request to logout endpoint
final response = await apiClient.post(ApiEndpoints.logout);
// Parse API response
final apiResponse = ApiResponse.fromJson(
response.data as Map<String, dynamic>,
null,
);
// Check if logout was successful
if (!apiResponse.isSuccess) {
final errorMessage = apiResponse.errors.isNotEmpty
? apiResponse.errors.first
: 'Logout failed';
throw ServerException(
errorMessage,
code: apiResponse.errorCodes.isNotEmpty
? apiResponse.errorCodes.first
: null,
);
}
} on ServerException {
rethrow;
} catch (e) {
throw ServerException('Failed to logout: ${e.toString()}');
}
}
@override
Future<UserModel> refreshToken(String refreshToken) async {
try {
// Make POST request to refresh token endpoint
final response = await apiClient.post(
ApiEndpoints.refreshToken,
data: {'refreshToken': refreshToken},
);
// Parse API response
final apiResponse = ApiResponse.fromJson(
response.data as Map<String, dynamic>,
(json) => UserModel.fromJson(json as Map<String, dynamic>),
);
// Check if refresh was successful
if (apiResponse.isSuccess && apiResponse.value != null) {
return apiResponse.value!;
} else {
final errorMessage = apiResponse.errors.isNotEmpty
? apiResponse.errors.first
: 'Token refresh failed';
throw ServerException(
errorMessage,
code: apiResponse.errorCodes.isNotEmpty
? apiResponse.errorCodes.first
: null,
);
}
} on ServerException {
rethrow;
} catch (e) {
throw ServerException('Failed to refresh token: ${e.toString()}');
}
}
}