Files
tm_app/lib/view_models/auth_view_model.dart
T
2026-04-16 16:36:55 +03:30

171 lines
4.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:tm_app/data/services/model/customer/customer.dart';
import '../core/utils/logger.dart';
import '../core/utils/result.dart';
import '../data/repositories/auth_repository.dart';
import '../data/services/model/login_response/login_response_model.dart';
class AuthViewModel with ChangeNotifier {
final AuthRepository _authRepository;
AuthViewModel({required AuthRepository authRepository})
: _authRepository = authRepository {
usernameController.addListener(_onTextChanged);
passwordController.addListener(_onTextChanged);
}
final TextEditingController usernameController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final FocusNode usernameFocus = FocusNode();
final FocusNode passwordFocus = FocusNode();
bool _obscurePassword = true;
bool get obscurePassword => _obscurePassword;
// bool get isLoginEnabled =>
// usernameController.text.isNotEmpty && passwordController.text.isNotEmpty;
// Auth state
bool _isLoading = false;
bool _isLoggedIn = false;
String? _errorMessage;
Customer? _loggedInUser;
String? successMessage;
Role? _userRole;
bool get isLoading => _isLoading;
bool get isLoggedIn => _isLoggedIn;
String? get errorMessage => _errorMessage;
Customer? get loggedInUser => _loggedInUser;
Role? get userRole => _userRole;
void togglePasswordVisibility() {
_obscurePassword = !_obscurePassword;
notifyListeners();
}
Future<void> hydrateFromStorage() async {
try {
final customer = await _authRepository.getStoredCustomer();
if (customer != null) {
_loggedInUser = customer;
_userRole = customer.role == 'admin' ? Role.admin : Role.analyst;
notifyListeners();
}
} catch (e) {
AppLogger().error('❌ Failed to hydrate auth state: $e');
}
}
// void _onTextChanged() {
// notifyListeners();
// }
bool _isLoginEnabled = false;
bool get isLoginEnabled => _isLoginEnabled;
void _onTextChanged() {
final newValue =
usernameController.text.isNotEmpty &&
passwordController.text.isNotEmpty;
if (newValue != _isLoginEnabled) {
_isLoginEnabled = newValue;
notifyListeners();
}
}
Future<void> login() async {
_isLoading = true;
_errorMessage = null;
notifyListeners();
await localLogout();
final result = await _authRepository.login(
username: usernameController.text.trim(),
password: passwordController.text.trim(),
);
switch (result) {
case Ok<LoginResponseModel>():
_loggedInUser = result.value.data.customer;
_userRole = _loggedInUser?.role == 'admin' ? Role.admin : Role.analyst;
usernameController.clear();
passwordController.clear();
break;
case Error<LoginResponseModel>():
_errorMessage = result.error.toString();
notifyListeners();
break;
}
_isLoading = false;
_errorMessage = null;
notifyListeners();
}
Future<void> localLogout() async {
try {
await _authRepository.localLogout();
} catch (e) {
// Handle local logout exceptions gracefully
AppLogger().error('❌ Failed to local logout: $e');
}
_loggedInUser = null;
_isLoggedIn = false;
notifyListeners();
}
Future<void> checkIsLoggedIn() async {
final result = await _authRepository.checkIsLoggedIn();
if (result is Ok<bool>) {
if (result.value) {
_isLoggedIn = result.value;
// Restore customer data from SharedPreferences
final customer = await _authRepository.getStoredCustomer();
if (customer != null) {
_loggedInUser = customer;
_userRole = customer.role == 'admin' ? Role.admin : Role.analyst;
}
} else {
_isLoggedIn = false;
_loggedInUser = null;
_userRole = null;
}
} else {
_isLoggedIn = false;
_loggedInUser = null;
_userRole = null;
}
notifyListeners();
}
void clearAuthFlow() {
_errorMessage = null;
successMessage = null;
usernameController.clear();
passwordController.clear();
_isLoggedIn = false;
_loggedInUser = null;
_userRole = null;
notifyListeners();
}
@override
void dispose() {
usernameController.dispose();
passwordController.dispose();
usernameFocus.dispose();
passwordFocus.dispose();
super.dispose();
}
}
enum Role { admin, analyst }