import 'dart:io'; import 'package:english_learning/core/services/repositories/user_repository.dart'; import 'package:flutter/material.dart'; import 'package:jwt_decoder/jwt_decoder.dart'; class UserProvider with ChangeNotifier { final UserRepository _userRepository = UserRepository(); bool _isLoggedIn = false; String? _jwtToken; Map? _userData; File? _selectedImage; bool _isLoading = false; int? _errorCode; bool get isLoading => _isLoading; bool get isLoggedIn => _isLoggedIn; String? get jwtToken => _jwtToken; Map? get userData => _userData; File? get selectedImage => _selectedImage; int? get errorCode => _errorCode; UserProvider() { _loadLoginStatus(); } void setLoading(bool value) { _isLoading = value; notifyListeners(); } Future _loadLoginStatus() async { _jwtToken = await _userRepository.getToken(); if (_jwtToken != null) { if (JwtDecoder.isExpired(_jwtToken!)) { await logout(); } else { _isLoggedIn = true; await _loadUserData(); } } notifyListeners(); } Future _loadUserData() async { _userData = await _userRepository.getUserData(); if (_userData == null) { await refreshUserData(); } } Future refreshUserData() async { if (_jwtToken != null) { final response = await _userRepository.getMe(_jwtToken!); if (response.statusCode == 200) { _userData = response.data['payload']; // Save all user data securely await _userRepository.saveUserData(_userData!); notifyListeners(); } } } // In the login method of UserProvider Future login({ required String credential, required String password, }) async { setLoading(true); _errorCode = null; try { final loginData = {'IDENTIFIER': credential, 'PASSWORD': password}; final response = await _userRepository.loginUser(loginData); _errorCode = response.statusCode; if (response.statusCode == 200 && response.data['payload']['TOKEN'] != null) { String token = response.data['payload']['TOKEN']; String refreshToken = response.data['payload']['REFRESH_TOKEN']; if (token.startsWith('Bearer ')) { token = token.substring(7); } _jwtToken = token; await _userRepository.saveToken(_jwtToken!); await _userRepository.saveRefreshToken(refreshToken); _isLoggedIn = true; await refreshUserData(); return true; } else if (response.statusCode == 403) { return false; } return false; } catch (e) { return false; } finally { setLoading(false); } } Future register({ required String name, required String email, required String nisn, required String password, required String confirmPassword, }) async { try { final response = await _userRepository.registerUser({ "NAME_USERS": name, "EMAIL": email, "NISN": nisn, "PASSWORD": password, "CONFIRM_PASSWORD": confirmPassword, }); if (response.statusCode == 200) { return true; } return false; } catch (e) { return false; } } Future logout() async { try { final response = await _userRepository.logoutUser(); if (response.statusCode == 200) { _isLoggedIn = false; _jwtToken = null; _userData = null; await _userRepository.deleteToken(); await _userRepository.deleteRefreshToken(); await _userRepository.deleteUserData(); notifyListeners(); return true; } return false; } catch (e) { _isLoggedIn = false; _jwtToken = null; _userData = null; await _userRepository.deleteToken(); await _userRepository.deleteRefreshToken(); await _userRepository.deleteUserData(); notifyListeners(); return false; } } Future forgotPassword({required String email}) async { try { final response = await _userRepository.forgotPassword(email); if (response.statusCode == 200) { return true; } else if (response.statusCode == 404) { return false; } return false; } catch (e) { return false; } } Future refreshToken() async { try { final refreshToken = await _userRepository.getRefreshToken(); if (refreshToken == null) return false; final response = await _userRepository.dioClient.refreshAccessToken(refreshToken); if (response.statusCode == 200) { String newToken = response.data['payload']['TOKEN']; String newRefreshToken = response.data['payload']['REFRESH_TOKEN']; if (newToken.startsWith('Bearer ')) { newToken = newToken.substring(7); } _jwtToken = newToken; await _userRepository.saveToken(_jwtToken!); await _userRepository.saveRefreshToken(newRefreshToken); return true; } return false; } catch (e) { return false; } } Future isTokenValid() async { if (_jwtToken == null) return false; if (JwtDecoder.isExpired(_jwtToken!)) { return await refreshToken(); } return true; } Future getValidToken() async { try { if (await isTokenValid()) { return _jwtToken; } return null; } catch (e) { return null; } } Future updateUserProfile(Map updatedData) async { try { final token = await getValidToken(); final userId = _userData?['ID']; if (token != null && userId != null) { final response = await _userRepository.updateUserProfile( userId, updatedData, token, imageFile: _selectedImage, ); if (response.statusCode == 200) { _userData = response.data['payload']; // Save updated user data securely await _userRepository.saveUserData(_userData!); _selectedImage = null; // Reset the selected image after successful update notifyListeners(); } } } catch (e) { rethrow; } } Future updatePassword({ required String oldPassword, required String newPassword, required String confirmPassword, }) async { try { final token = await getValidToken(); final userId = _userData?['ID']; if (token != null && userId != null) { final response = await _userRepository.updatePassword( userId, oldPassword, newPassword, confirmPassword, token, ); if (response.statusCode == 200) { return true; } } return false; } catch (e) { return false; } } Future reportIssue(String report) async { try { final token = await getValidToken(); if (token != null) { final response = await _userRepository.reportIssue(report, token); if (response.statusCode == 201) { return true; } } return false; } catch (e) { return false; } } String? getUserName() { return _userData?['NAME_USERS']; } void setSelectedImage(File? image) { _selectedImage = image; notifyListeners(); } }