189 lines
5.8 KiB
Dart
189 lines
5.8 KiB
Dart
import 'dart:convert';
|
|
import '../constants/api_constants.dart';
|
|
import 'http_service.dart';
|
|
import 'auth_service.dart';
|
|
import 'cache_service.dart';
|
|
|
|
class UserService {
|
|
static bool _pollingStarted = false;
|
|
/// Get current user with caching - returns cached data if available and fresh
|
|
static Future<Map<String, dynamic>> getCurrentUser({bool forceRefresh = false}) async {
|
|
// Return cached data if available and not forcing refresh
|
|
if (!forceRefresh) {
|
|
final cached = CacheService.getCached<Map<String, dynamic>>(CacheService.userProfileKey);
|
|
if (cached != null && !CacheService.isCacheExpired(CacheService.userProfileKey, CacheService.userCacheDuration)) {
|
|
return {
|
|
'success': true,
|
|
'message': 'Loaded from cache',
|
|
'data': cached,
|
|
};
|
|
}
|
|
|
|
// Return stale data while fetching fresh data in background
|
|
final stale = CacheService.getCachedStale<Map<String, dynamic>>(CacheService.userProfileKey);
|
|
if (stale != null && !forceRefresh) {
|
|
// Trigger background refresh
|
|
_fetchAndCacheUser();
|
|
return {
|
|
'success': true,
|
|
'message': 'Loaded from cache (refreshing in background)',
|
|
'data': stale,
|
|
};
|
|
}
|
|
|
|
// Also check AuthService cache for backward compatibility
|
|
final authCachedData = await AuthService.getCachedUserData();
|
|
if (authCachedData != null) {
|
|
// Update our cache with auth service data
|
|
CacheService.setCached(CacheService.userProfileKey, authCachedData);
|
|
return {'success': true, 'data': authCachedData};
|
|
}
|
|
}
|
|
|
|
// Fetch fresh data
|
|
return await _fetchAndCacheUser();
|
|
}
|
|
|
|
static Future<Map<String, dynamic>> _fetchAndCacheUser([bool fromPolling = false]) async {
|
|
try {
|
|
final response = await HttpService.get(ApiConstants.getUserEndpoint);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = jsonDecode(response.body);
|
|
|
|
// Only cache when not called from polling to prevent conflicts
|
|
if (!fromPolling) {
|
|
CacheService.setCached(CacheService.userProfileKey, data);
|
|
}
|
|
|
|
// Also save to AuthService for backward compatibility
|
|
await AuthService.saveUserData(data);
|
|
|
|
return {
|
|
'success': true,
|
|
'data': data,
|
|
'message': '',
|
|
};
|
|
} else if (response.statusCode == 401 || response.statusCode == 403) {
|
|
await AuthService.handleAuthenticationError();
|
|
return {
|
|
'success': false,
|
|
'message': 'Session expired. Please login again.',
|
|
'data': null,
|
|
};
|
|
} else {
|
|
return {
|
|
'success': false,
|
|
'message': 'Server error (${response.statusCode})',
|
|
'data': null,
|
|
};
|
|
}
|
|
} catch (e) {
|
|
print('Error fetching user: $e');
|
|
return {
|
|
'success': false,
|
|
'message': 'Network error. Please check your connection.',
|
|
'data': null,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// Start background polling for user profile
|
|
static void startPolling() {
|
|
_pollingStarted = true;
|
|
CacheService.startPolling(
|
|
CacheService.userProfileKey,
|
|
() => _fetchAndCacheUser(true), // Mark as from polling
|
|
CacheService.userPollingInterval,
|
|
CacheService.userCacheDuration,
|
|
);
|
|
}
|
|
|
|
/// Stop background polling for user profile
|
|
static void stopPolling() {
|
|
CacheService.stopPolling(CacheService.userProfileKey);
|
|
_pollingStarted = false;
|
|
}
|
|
|
|
/// Get user profile stream for real-time updates
|
|
static Stream<Map<String, dynamic>> getUserStream() {
|
|
return CacheService.getStream<Map<String, dynamic>>(CacheService.userProfileKey);
|
|
}
|
|
|
|
/// Check if polling is active
|
|
static bool get isPollingActive => _pollingStarted;
|
|
|
|
/// Invalidate user cache (useful after updating profile)
|
|
static void invalidateCache() {
|
|
CacheService.clearCache(CacheService.userProfileKey);
|
|
}
|
|
|
|
static Future<Map<String, dynamic>> updateFCMToken(String fcmToken) async {
|
|
try {
|
|
final response = await HttpService.post(ApiConstants.updateUserEndpoint, {
|
|
'fcmToken': fcmToken,
|
|
});
|
|
|
|
if (response.statusCode == 200) {
|
|
return {'success': true};
|
|
} else if (response.statusCode == 401) {
|
|
return {
|
|
'success': false,
|
|
'message': 'Session expired. Please login again.',
|
|
};
|
|
} else if (response.statusCode == 403) {
|
|
return {
|
|
'success': false,
|
|
'message': 'Access denied. Invalid credentials.',
|
|
};
|
|
} else {
|
|
return {
|
|
'success': false,
|
|
'message': 'Server error (${response.statusCode})',
|
|
};
|
|
}
|
|
} catch (e) {
|
|
print('Error updating FCM token: $e');
|
|
return {
|
|
'success': false,
|
|
'message': 'Network error. Please check your connection.',
|
|
};
|
|
}
|
|
}
|
|
|
|
static Future<Map<String, dynamic>> createUser({
|
|
required String email,
|
|
required String password,
|
|
required String displayName,
|
|
}) async {
|
|
try {
|
|
final response = await HttpService.post('/admin/createUser', {
|
|
'email': email,
|
|
'password': password,
|
|
'displayName': displayName,
|
|
});
|
|
|
|
final responseData = jsonDecode(response.body);
|
|
|
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
|
return {
|
|
'success': responseData['status'] ?? false,
|
|
'message': responseData['message'] ?? 'User created successfully',
|
|
'data': responseData['data'],
|
|
};
|
|
} else {
|
|
return {
|
|
'success': false,
|
|
'message': responseData['message'] ?? 'Failed to create user',
|
|
};
|
|
}
|
|
} catch (e) {
|
|
print('Error creating user: $e');
|
|
return {
|
|
'success': false,
|
|
'message': 'Network error. Please check your connection.',
|
|
};
|
|
}
|
|
}
|
|
}
|