cee5e6c6d6
- Implemented `ForgotPasswordViewModel`, `ResetPasswordViewModel`, and `VerifyOtpViewModel` for handling respective functionalities. - Created provider functions for lazy loading of these view models in the app. - Updated routing to utilize the new providers for managing state in the forgot password flow. - Refactored UI components to integrate with the new view models, ensuring proper state management and user feedback during operations.
126 lines
3.1 KiB
Dart
126 lines
3.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;
|
|
|
|
bool get isLoading => _isLoading;
|
|
bool get isLoggedIn => _isLoggedIn;
|
|
String? get errorMessage => _errorMessage;
|
|
Customer? get loggedInUser => _loggedInUser;
|
|
|
|
void togglePasswordVisibility() {
|
|
_obscurePassword = !_obscurePassword;
|
|
notifyListeners();
|
|
}
|
|
|
|
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;
|
|
usernameController.clear();
|
|
passwordController.clear();
|
|
break;
|
|
case Error<LoginResponseModel>():
|
|
_errorMessage = result.error.toString();
|
|
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;
|
|
} else {
|
|
_isLoggedIn = false;
|
|
}
|
|
} else {
|
|
_isLoggedIn = false;
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
void clearAuthFlow() {
|
|
_errorMessage = null;
|
|
successMessage = null;
|
|
usernameController.clear();
|
|
passwordController.clear();
|
|
_isLoggedIn = false;
|
|
_loggedInUser = null;
|
|
notifyListeners();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
usernameController.dispose();
|
|
passwordController.dispose();
|
|
usernameFocus.dispose();
|
|
passwordFocus.dispose();
|
|
|
|
super.dispose();
|
|
}
|
|
}
|