Utopia-Canteen-System/ViewModels/AdminLoginViewModel.cs

129 lines
4.0 KiB
C#

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using UtopiaCanteenSystem.Services;
using UtopiaCanteenSystem.Services.Logging;
namespace UtopiaCanteenSystem.ViewModels;
public partial class AdminLoginViewModel : ObservableObject
{
private readonly IAuthService _authService;
private readonly AppSession _session;
private readonly INavigationService _navigation;
private readonly IConfigService _config;
private readonly IAdminAuditService _adminAudit;
private readonly IEmployeeLookupService _employeeLookup;
private readonly ICanteenBackendApiClient? _backendApi;
[ObservableProperty]
private string _username = string.Empty;
// Updated from code-behind (PasswordBox doesn't support binding cleanly).
[ObservableProperty]
private string _password = string.Empty;
[ObservableProperty]
private string _errorMessage = string.Empty;
[ObservableProperty]
private bool _isBusy;
[ObservableProperty]
private bool _rememberCredentials;
public AdminLoginViewModel(
IAuthService authService,
AppSession session,
INavigationService navigation,
IConfigService config,
IAdminAuditService adminAudit,
IEmployeeLookupService employeeLookup,
ICanteenBackendApiClient? backendApi = null)
{
_authService = authService;
_session = session;
_navigation = navigation;
_config = config;
_adminAudit = adminAudit;
_employeeLookup = employeeLookup;
_backendApi = backendApi;
RememberCredentials = _config.GetRememberAdminCredentials();
if (RememberCredentials)
{
Username = _config.GetSavedAdminUsername();
Password = _config.GetSavedAdminPassword();
}
}
[RelayCommand]
private async Task AdminLoginAsync()
{
if (IsBusy)
return;
ErrorMessage = string.Empty;
var user = Username?.Trim() ?? string.Empty;
var pass = Password ?? string.Empty;
// Requirement: always clear fields after clicking LOGIN (success or failure).
// Keep local copies for the ongoing request.
Username = string.Empty;
Password = string.Empty;
if (string.IsNullOrWhiteSpace(user) || string.IsNullOrEmpty(pass))
{
ErrorMessage = "Username and password are required.";
return;
}
IsBusy = true;
try
{
var result = await _authService.LoginAsync(user, pass).ConfigureAwait(true);
if (!result.Success)
{
ErrorMessage = "Invalid username or password.";
FileLogger.Warn("ClientLogin", $"Admin login failed for user '{user}'.");
return;
}
_session.SetAdminAuthenticated(user, result.EmployeeId);
await AdminLoginHelper.ApplyAdminLoginDefaultsAsync(
result.EmployeeId,
_config,
_employeeLookup,
_backendApi).ConfigureAwait(true);
FileLogger.Info(
"ClientLogin",
$"Admin login succeeded. EmployeeId={result.EmployeeId}, AdminCardId saved, SiteId={_config.GetSiteId()}");
// Persist who logged in (for audit / reporting).
await _adminAudit.RecordLoginAsync(user, result.EmployeeId).ConfigureAwait(false);
// Persist credentials only if user opted in.
_config.SetRememberAdminCredentials(RememberCredentials);
if (RememberCredentials)
{
_config.SetSavedAdminUsername(user);
_config.SetSavedAdminPassword(pass);
}
else
{
_config.SetSavedAdminUsername(string.Empty);
_config.SetSavedAdminPassword(string.Empty);
}
_navigation.NavigateToScanner();
}
finally
{
IsBusy = false;
}
}
}