aaa
This commit is contained in:
@@ -21,8 +21,10 @@ class _RetailAppState extends ConsumerState<RetailApp> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
print('📱 RetailApp: initState called');
|
||||
// Initialize auth state on app start
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
print('📱 RetailApp: Calling initialize()...');
|
||||
ref.read(authProvider.notifier).initialize();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -13,12 +13,21 @@ class SecureStorage {
|
||||
|
||||
/// Save access token
|
||||
Future<void> saveAccessToken(String token) async {
|
||||
print('💾 SecureStorage: Saving token (length: ${token.length})...');
|
||||
await _storage.write(key: _accessTokenKey, value: token);
|
||||
print('💾 SecureStorage: Token saved successfully');
|
||||
|
||||
// Verify it was saved
|
||||
final saved = await _storage.read(key: _accessTokenKey);
|
||||
print('💾 SecureStorage: Verification - token exists: ${saved != null}, length: ${saved?.length ?? 0}');
|
||||
}
|
||||
|
||||
/// Get access token
|
||||
Future<String?> getAccessToken() async {
|
||||
return await _storage.read(key: _accessTokenKey);
|
||||
print('💾 SecureStorage: Reading token...');
|
||||
final token = await _storage.read(key: _accessTokenKey);
|
||||
print('💾 SecureStorage: Token read result - exists: ${token != null}, length: ${token?.length ?? 0}');
|
||||
return token;
|
||||
}
|
||||
|
||||
/// Save refresh token (for future use)
|
||||
@@ -49,8 +58,11 @@ class SecureStorage {
|
||||
|
||||
/// Check if access token exists
|
||||
Future<bool> hasAccessToken() async {
|
||||
print('💾 SecureStorage: Checking if token exists...');
|
||||
final token = await getAccessToken();
|
||||
return token != null && token.isNotEmpty;
|
||||
final exists = token != null && token.isNotEmpty;
|
||||
print('💾 SecureStorage: Token exists: $exists');
|
||||
return exists;
|
||||
}
|
||||
|
||||
/// Clear all secure storage
|
||||
|
||||
@@ -89,21 +89,31 @@ class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
|
||||
@override
|
||||
Future<UserModel> getProfile() async {
|
||||
try {
|
||||
print('📡 DataSource: Calling getProfile API...');
|
||||
final response = await dioClient.get(ApiConstants.profile);
|
||||
|
||||
print('📡 DataSource: Profile status=${response.statusCode}');
|
||||
print('📡 DataSource: Profile response keys=${response.data?.keys?.toList()}');
|
||||
print('📡 DataSource: Profile response=$response.data}');
|
||||
|
||||
if (response.statusCode == ApiConstants.statusOk) {
|
||||
// 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);
|
||||
// API returns nested structure: {success, data: user, message}
|
||||
// Extract the 'data' object
|
||||
final userData = response.data['data'] as Map<String, dynamic>;
|
||||
print('📡 DataSource: Extracted user data with keys=${userData.keys.toList()}');
|
||||
|
||||
final userModel = UserModel.fromJson(userData);
|
||||
print('📡 DataSource: User parsed successfully: ${userModel.name}');
|
||||
return userModel;
|
||||
} else {
|
||||
throw ServerException('Get profile failed with status: ${response.statusCode}');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
print('❌ DataSource: Profile DioException - ${e.message}');
|
||||
throw _handleDioError(e);
|
||||
} catch (e) {
|
||||
} catch (e, stackTrace) {
|
||||
print('❌ DataSource: Profile unexpected error - $e');
|
||||
print('Stack trace: $stackTrace');
|
||||
throw ServerException('Unexpected error getting profile: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,11 @@ class UserModel extends User {
|
||||
|
||||
/// Create UserModel from JSON
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||
final createdAt = DateTime.parse(json['createdAt'] as String);
|
||||
// createdAt might not be in response, default to now
|
||||
final createdAt = json['createdAt'] != null
|
||||
? DateTime.parse(json['createdAt'] as String)
|
||||
: DateTime.now();
|
||||
|
||||
return UserModel(
|
||||
id: json['id'] as String,
|
||||
name: json['name'] as String,
|
||||
|
||||
@@ -26,19 +26,24 @@ class AuthRepositoryImpl implements AuthRepository {
|
||||
Future<Either<Failure, AuthResponse>> login({
|
||||
required String email,
|
||||
required String password,
|
||||
bool rememberMe = false,
|
||||
}) async {
|
||||
try {
|
||||
print('🔐 Repository: Starting login...');
|
||||
print('🔐 Repository: Starting login (rememberMe: $rememberMe)...');
|
||||
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');
|
||||
// Save token to secure storage only if rememberMe is true
|
||||
if (rememberMe) {
|
||||
await secureStorage.saveAccessToken(authResponse.accessToken);
|
||||
print('🔐 Repository: Token saved to secure storage (persistent)');
|
||||
} else {
|
||||
print('🔐 Repository: Token NOT saved (session only - rememberMe is false)');
|
||||
}
|
||||
|
||||
// Set token in Dio client for subsequent requests
|
||||
// Set token in Dio client for subsequent requests (always for current session)
|
||||
dioClient.setAuthToken(authResponse.accessToken);
|
||||
print('🔐 Repository: Token set in DioClient');
|
||||
|
||||
@@ -162,16 +167,25 @@ class AuthRepositoryImpl implements AuthRepository {
|
||||
@override
|
||||
Future<bool> isAuthenticated() async {
|
||||
try {
|
||||
print('🔍 Checking authentication...');
|
||||
final hasToken = await secureStorage.hasAccessToken();
|
||||
print('🔍 Has token in storage: $hasToken');
|
||||
|
||||
if (hasToken) {
|
||||
final token = await secureStorage.getAccessToken();
|
||||
print('🔍 Token retrieved, length: ${token?.length ?? 0}');
|
||||
|
||||
if (token != null) {
|
||||
dioClient.setAuthToken(token);
|
||||
print('✅ Token loaded from storage and set in DioClient');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
print('❌ No token found in storage');
|
||||
return false;
|
||||
} catch (e) {
|
||||
print('❌ Error checking authentication: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ abstract class AuthRepository {
|
||||
Future<Either<Failure, AuthResponse>> login({
|
||||
required String email,
|
||||
required String password,
|
||||
bool rememberMe = false,
|
||||
});
|
||||
|
||||
/// Register new user
|
||||
|
||||
@@ -39,6 +39,7 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
||||
final success = await ref.read(authProvider.notifier).login(
|
||||
email: _emailController.text.trim(),
|
||||
password: _passwordController.text,
|
||||
rememberMe: _rememberMe,
|
||||
);
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
@@ -86,29 +86,36 @@ class Auth extends _$Auth {
|
||||
|
||||
/// Initialize auth state - call this on app start
|
||||
Future<void> initialize() async {
|
||||
print('🚀 Initializing auth state...');
|
||||
state = state.copyWith(isLoading: true);
|
||||
|
||||
final isAuthenticated = await _repository.isAuthenticated();
|
||||
print('🚀 isAuthenticated result: $isAuthenticated');
|
||||
|
||||
if (isAuthenticated) {
|
||||
print('🚀 Token found, fetching user profile...');
|
||||
// Get user profile
|
||||
final result = await _repository.getProfile();
|
||||
result.fold(
|
||||
(failure) {
|
||||
print('❌ Failed to get profile: ${failure.message}');
|
||||
state = const AuthState(
|
||||
isAuthenticated: false,
|
||||
isLoading: false,
|
||||
);
|
||||
},
|
||||
(user) {
|
||||
print('✅ Profile loaded: ${user.name}');
|
||||
state = AuthState(
|
||||
user: user,
|
||||
isAuthenticated: true,
|
||||
isLoading: false,
|
||||
);
|
||||
print('✅ Initialize complete: isAuthenticated=${state.isAuthenticated}');
|
||||
},
|
||||
);
|
||||
} else {
|
||||
print('❌ No token found, user needs to login');
|
||||
state = const AuthState(
|
||||
isAuthenticated: false,
|
||||
isLoading: false,
|
||||
@@ -120,10 +127,15 @@ class Auth extends _$Auth {
|
||||
Future<bool> login({
|
||||
required String email,
|
||||
required String password,
|
||||
bool rememberMe = false,
|
||||
}) async {
|
||||
state = state.copyWith(isLoading: true, clearError: true);
|
||||
|
||||
final result = await _repository.login(email: email, password: password);
|
||||
final result = await _repository.login(
|
||||
email: email,
|
||||
password: password,
|
||||
rememberMe: rememberMe,
|
||||
);
|
||||
|
||||
return result.fold(
|
||||
(failure) {
|
||||
|
||||
Reference in New Issue
Block a user