Files
tm_app/lib/view_models/auth_view_model.dart
T
amirrezaghabeli 64a1c30e6c Add logo SVG asset and improve authentication error handling
- Added a new logo SVG asset to the AssetsManager for better branding.
- Updated the AuthViewModel to notify listeners on authentication error changes.
- Modified DesktopNavigationWidget to use the new logo SVG with specified dimensions for improved layout.
2025-11-16 14:54:45 +03:30

157 lines
4.1 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();
}
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 }