enrollment-app/lib/service/token_storage_service.dart
2025-10-11 18:04:18 +05:30

157 lines
4.8 KiB
Dart

import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
class TokenStorageService {
static final TokenStorageService _instance = TokenStorageService._internal();
factory TokenStorageService() => _instance;
TokenStorageService._internal();
// Storage keys
static const String _preEnrollmentKey = 'pre_enrollment_data';
static const String _postEnrollmentKey = 'post_enrollment_data';
static const String _selectedBranchKey = 'selected_branch';
static const String _decodedTokenKey = 'decoded_token';
// In-memory cache
List<dynamic>? _preEnrollmentData;
List<dynamic>? _postEnrollmentData;
Map<String, dynamic>? _selectedBranch;
Map<String, dynamic>? _decodedToken;
// Initialize - Load data from storage
Future<void> initialize() async {
final prefs = await SharedPreferences.getInstance();
final preData = prefs.getString(_preEnrollmentKey);
if (preData != null) {
_preEnrollmentData = json.decode(preData);
}
final postData = prefs.getString(_postEnrollmentKey);
if (postData != null) {
_postEnrollmentData = json.decode(postData);
}
final branchData = prefs.getString(_selectedBranchKey);
if (branchData != null) {
_selectedBranch = json.decode(branchData);
}
final tokenData = prefs.getString(_decodedTokenKey);
if (tokenData != null) {
_decodedToken = json.decode(tokenData);
}
}
// Save enrollment data
Future<void> saveEnrollmentData(List<dynamic> preData, List<dynamic> postData) async {
_preEnrollmentData = preData;
_postEnrollmentData = postData;
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_preEnrollmentKey, json.encode(preData));
await prefs.setString(_postEnrollmentKey, json.encode(postData));
}
// Get combined unique branches
List<Map<String, dynamic>> getCombinedBranches() {
List<Map<String, dynamic>> combined = [];
Set<String> seenTokens = {};
Set<String> seenIds = {};
// Add pre-enrollment data
if (_preEnrollmentData != null) {
for (var item in _preEnrollmentData!) {
String token = item['token']?.toString() ?? '';
String uniqueId = '${item['id']}_${item['client_id']}_${item['client_branch_id']}';
if (seenIds.contains(uniqueId)) continue;
if (token.isNotEmpty && seenTokens.contains(token)) continue;
if (token.isNotEmpty) seenTokens.add(token);
seenIds.add(uniqueId);
combined.add({...item, 'enrollment_type': 'pre'});
}
}
// Add post-enrollment data
if (_postEnrollmentData != null) {
for (var item in _postEnrollmentData!) {
String token = item['token']?.toString() ?? '';
String uniqueId = '${item['id']}_${item['client_id']}_${item['client_branch_id']}';
if (seenIds.contains(uniqueId)) continue;
if (token.isNotEmpty && seenTokens.contains(token)) continue;
if (token.isNotEmpty) seenTokens.add(token);
seenIds.add(uniqueId);
combined.add({...item, 'enrollment_type': 'post'});
}
}
return combined;
}
// Save selected branch and decode token
Future<void> saveSelectedBranch(Map<String, dynamic> branch) async {
_selectedBranch = branch;
String token = branch['token']?.toString() ?? '';
if (token.isNotEmpty) {
_decodedToken = _decodeJWT(token);
} else {
_decodedToken = null;
}
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_selectedBranchKey, json.encode(branch));
if (_decodedToken != null) {
await prefs.setString(_decodedTokenKey, json.encode(_decodedToken));
}
}
// Decode JWT token
Map<String, dynamic>? _decodeJWT(String token) {
try {
final parts = token.split('.');
if (parts.length != 3) return null;
final payload = parts[1];
var normalized = base64Url.normalize(payload);
var decoded = utf8.decode(base64Url.decode(normalized));
return json.decode(decoded);
} catch (e) {
print('Error decoding token: $e');
return null;
}
}
// Getters
Map<String, dynamic>? getSelectedBranch() => _selectedBranch;
Map<String, dynamic>? getDecodedToken() => _decodedToken;
String? getCurrentToken() => _selectedBranch?['token'];
bool isLoggedIn() {
return _selectedBranch != null &&
_selectedBranch!['token'] != null &&
_selectedBranch!['token'].toString().isNotEmpty;
}
// Clear all data (logout)
Future<void> clearAll() async {
_preEnrollmentData = null;
_postEnrollmentData = null;
_selectedBranch = null;
_decodedToken = null;
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_preEnrollmentKey);
await prefs.remove(_postEnrollmentKey);
await prefs.remove(_selectedBranchKey);
await prefs.remove(_decodedTokenKey);
}
}