feat: implement centralized human-readable error messaging for Dio exceptions and improve API response parsing

This commit is contained in:
pradeepkumar
2026-04-10 17:35:59 +05:30
parent fe521d64f5
commit cdb918fae8
2 changed files with 59 additions and 19 deletions

View File

@@ -10,6 +10,31 @@ import 'package:real_estate_mobile/features/auth/data/models/user_model.dart';
class AuthRepository {
final Dio _dio = ApiClient.instance.dio;
/// Extract a user-friendly message from a DioException.
/// NEVER returns Dio's raw technical text — always a short human sentence.
static String _friendlyError(DioException e, String fallback) {
// If our interceptor already wrapped it, use that message
if (e.error is ApiException) return (e.error as ApiException).message;
// Status-code based fallback
switch (e.response?.statusCode) {
case 400: return 'The request was invalid. Please check your input.';
case 401: return 'Invalid email or password.';
case 403: return 'You don\'t have permission to perform this action.';
case 404: return 'Not found.';
case 409: return 'This action conflicts with existing data.';
case 429: return 'Too many attempts. Please wait and try again.';
}
if (e.type == DioExceptionType.connectionTimeout ||
e.type == DioExceptionType.receiveTimeout ||
e.type == DioExceptionType.sendTimeout) {
return 'Request timed out. Please check your connection.';
}
if (e.type == DioExceptionType.connectionError) {
return 'Unable to reach the server. Check your internet connection.';
}
return fallback;
}
Future<Map<String, dynamic>> login({
required String email,
required String password,
@@ -42,11 +67,9 @@ class AuthRepository {
'user': authResponse.user,
};
} on DioException catch (e) {
if (e.error is ApiException) {
throw e.error as ApiException;
}
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? 'Login failed',
message: _friendlyError(e, 'Login failed'),
statusCode: e.response?.statusCode,
);
}
@@ -72,7 +95,7 @@ class AuthRepository {
} on DioException catch (e) {
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? '2FA verification failed',
message: _friendlyError(e, '2FA verification failed'),
statusCode: e.response?.statusCode,
);
}
@@ -98,7 +121,7 @@ class AuthRepository {
} on DioException catch (e) {
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? 'Backup code verification failed',
message: _friendlyError(e, 'Backup code verification failed'),
statusCode: e.response?.statusCode,
);
}
@@ -110,11 +133,9 @@ class AuthRepository {
final data = response.data['data'] as Map<String, dynamic>;
return UserModel.fromJson(data);
} on DioException catch (e) {
if (e.error is ApiException) {
throw e.error as ApiException;
}
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? 'Failed to fetch user',
message: _friendlyError(e, 'Failed to fetch user'),
statusCode: e.response?.statusCode,
);
}
@@ -168,7 +189,7 @@ class AuthRepository {
} on DioException catch (e) {
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? 'Social login failed',
message: _friendlyError(e, 'Social login failed'),
statusCode: e.response?.statusCode,
);
}
@@ -186,11 +207,9 @@ class AuthRepository {
final data = response.data['data'] as Map<String, dynamic>;
return data;
} on DioException catch (e) {
if (e.error is ApiException) {
throw e.error as ApiException;
}
if (e.error is ApiException) throw e.error as ApiException;
throw ApiException(
message: e.message ?? 'Registration failed',
message: _friendlyError(e, 'Registration failed'),
statusCode: e.response?.statusCode,
);
}