login
This commit is contained in:
@@ -31,19 +31,33 @@ class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
|
||||
@override
|
||||
Future<AuthResponseModel> login(LoginDto loginDto) async {
|
||||
try {
|
||||
print('📡 DataSource: Calling login API...');
|
||||
final response = await dioClient.post(
|
||||
ApiConstants.login,
|
||||
data: loginDto.toJson(),
|
||||
);
|
||||
|
||||
print('📡 DataSource: Status=${response.statusCode}');
|
||||
print('📡 DataSource: Response data keys=${response.data.keys.toList()}');
|
||||
|
||||
if (response.statusCode == ApiConstants.statusOk) {
|
||||
return AuthResponseModel.fromJson(response.data);
|
||||
// API returns nested structure: {success, data: {access_token, user}, message}
|
||||
// Extract the 'data' object
|
||||
final responseData = response.data['data'] as Map<String, dynamic>;
|
||||
print('📡 DataSource: Extracted data object with keys=${responseData.keys.toList()}');
|
||||
|
||||
final authResponseModel = AuthResponseModel.fromJson(responseData);
|
||||
print('📡 DataSource: Parsed successfully, token length=${authResponseModel.accessToken.length}');
|
||||
return authResponseModel;
|
||||
} else {
|
||||
throw ServerException('Login failed with status: ${response.statusCode}');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
print('❌ DataSource: DioException - ${e.message}');
|
||||
throw _handleDioError(e);
|
||||
} catch (e) {
|
||||
} catch (e, stackTrace) {
|
||||
print('❌ DataSource: Unexpected error - $e');
|
||||
print('Stack trace: $stackTrace');
|
||||
throw ServerException('Unexpected error during login: $e');
|
||||
}
|
||||
}
|
||||
@@ -56,8 +70,12 @@ class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
|
||||
data: registerDto.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == ApiConstants.statusCreated) {
|
||||
return AuthResponseModel.fromJson(response.data);
|
||||
if (response.statusCode == ApiConstants.statusCreated ||
|
||||
response.statusCode == ApiConstants.statusOk) {
|
||||
// API returns nested structure: {success, data: {access_token, user}, message}
|
||||
// Extract the 'data' object
|
||||
final responseData = response.data['data'] as Map<String, dynamic>;
|
||||
return AuthResponseModel.fromJson(responseData);
|
||||
} else {
|
||||
throw ServerException('Registration failed with status: ${response.statusCode}');
|
||||
}
|
||||
@@ -74,7 +92,12 @@ class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
|
||||
final response = await dioClient.get(ApiConstants.profile);
|
||||
|
||||
if (response.statusCode == ApiConstants.statusOk) {
|
||||
return UserModel.fromJson(response.data);
|
||||
// API might return nested structure: {success, data: user, message}
|
||||
// Check if response has 'data' key
|
||||
final userData = response.data['data'] != null
|
||||
? response.data['data'] as Map<String, dynamic>
|
||||
: response.data as Map<String, dynamic>;
|
||||
return UserModel.fromJson(userData);
|
||||
} else {
|
||||
throw ServerException('Get profile failed with status: ${response.statusCode}');
|
||||
}
|
||||
@@ -91,7 +114,10 @@ class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
|
||||
final response = await dioClient.post(ApiConstants.refreshToken);
|
||||
|
||||
if (response.statusCode == ApiConstants.statusOk) {
|
||||
return AuthResponseModel.fromJson(response.data);
|
||||
// API returns nested structure: {success, data: {access_token, user}, message}
|
||||
// Extract the 'data' object
|
||||
final responseData = response.data['data'] as Map<String, dynamic>;
|
||||
return AuthResponseModel.fromJson(responseData);
|
||||
} else {
|
||||
throw ServerException('Token refresh failed with status: ${response.statusCode}');
|
||||
}
|
||||
|
||||
@@ -14,14 +14,18 @@ class UserModel extends User {
|
||||
|
||||
/// Create UserModel from JSON
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||
final createdAt = DateTime.parse(json['createdAt'] as String);
|
||||
return UserModel(
|
||||
id: json['id'] as String,
|
||||
name: json['name'] as String,
|
||||
email: json['email'] as String,
|
||||
roles: (json['roles'] as List<dynamic>).cast<String>(),
|
||||
isActive: json['isActive'] as bool? ?? true,
|
||||
createdAt: DateTime.parse(json['createdAt'] as String),
|
||||
updatedAt: DateTime.parse(json['updatedAt'] as String),
|
||||
createdAt: createdAt,
|
||||
// updatedAt might not be in response, default to createdAt
|
||||
updatedAt: json['updatedAt'] != null
|
||||
? DateTime.parse(json['updatedAt'] as String)
|
||||
: createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,27 +28,39 @@ class AuthRepositoryImpl implements AuthRepository {
|
||||
required String password,
|
||||
}) async {
|
||||
try {
|
||||
print('🔐 Repository: Starting login...');
|
||||
final loginDto = LoginDto(email: email, password: password);
|
||||
final authResponse = await remoteDataSource.login(loginDto);
|
||||
|
||||
print('🔐 Repository: Got response, token length=${authResponse.accessToken.length}');
|
||||
|
||||
// Save token to secure storage
|
||||
await secureStorage.saveAccessToken(authResponse.accessToken);
|
||||
print('🔐 Repository: Token saved to secure storage');
|
||||
|
||||
// Set token in Dio client for subsequent requests
|
||||
dioClient.setAuthToken(authResponse.accessToken);
|
||||
print('🔐 Repository: Token set in DioClient');
|
||||
|
||||
return Right(authResponse);
|
||||
} on InvalidCredentialsException catch (e) {
|
||||
print('❌ Repository: InvalidCredentialsException - ${e.message}');
|
||||
return Left(InvalidCredentialsFailure(e.message));
|
||||
} on UnauthorizedException catch (e) {
|
||||
print('❌ Repository: UnauthorizedException - ${e.message}');
|
||||
return Left(UnauthorizedFailure(e.message));
|
||||
} on ValidationException catch (e) {
|
||||
print('❌ Repository: ValidationException - ${e.message}');
|
||||
return Left(ValidationFailure(e.message));
|
||||
} on NetworkException catch (e) {
|
||||
print('❌ Repository: NetworkException - ${e.message}');
|
||||
return Left(NetworkFailure(e.message));
|
||||
} on ServerException catch (e) {
|
||||
print('❌ Repository: ServerException - ${e.message}');
|
||||
return Left(ServerFailure(e.message));
|
||||
} catch (e) {
|
||||
} catch (e, stackTrace) {
|
||||
print('❌ Repository: Unexpected error - $e');
|
||||
print('Stack trace: $stackTrace');
|
||||
return Left(ServerFailure('Unexpected error: $e'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ class Auth extends _$Auth {
|
||||
|
||||
return result.fold(
|
||||
(failure) {
|
||||
print('❌ Login FAILED: ${failure.message}');
|
||||
state = state.copyWith(
|
||||
isAuthenticated: false,
|
||||
isLoading: false,
|
||||
@@ -135,12 +136,14 @@ class Auth extends _$Auth {
|
||||
return false;
|
||||
},
|
||||
(authResponse) {
|
||||
print('✅ Login SUCCESS: user=${authResponse.user.name}, token length=${authResponse.accessToken.length}');
|
||||
state = AuthState(
|
||||
user: authResponse.user,
|
||||
isAuthenticated: true,
|
||||
isLoading: false,
|
||||
errorMessage: null,
|
||||
);
|
||||
print('✅ State updated: isAuthenticated=${state.isAuthenticated}');
|
||||
return true;
|
||||
},
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@ class AuthWrapper extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final authState = ref.watch(authProvider);
|
||||
|
||||
print('AuthWrapper build: isAuthenticated=${authState.isAuthenticated}, isLoading=${authState.isLoading}');
|
||||
// Show loading indicator while checking auth status
|
||||
if (authState.isLoading && authState.user == null) {
|
||||
return const Scaffold(
|
||||
|
||||
Reference in New Issue
Block a user