188 lines
5.6 KiB
C#
188 lines
5.6 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
||
using CommunityToolkit.Mvvm.Input;
|
||
using UtopiaCanteenSystem.Services;
|
||
|
||
namespace UtopiaCanteenSystem.ViewModels;
|
||
|
||
/// <summary>
|
||
/// ViewModel for SettingsView: editable API endpoint (UIND sync URL), save, load from config.
|
||
/// </summary>
|
||
public partial class SettingsViewModel : ObservableObject
|
||
{
|
||
private readonly IConfigService _configService;
|
||
private readonly INavigationService _navigation;
|
||
private readonly IAdminAuditService _adminAudit;
|
||
private readonly ISyncService _syncService;
|
||
|
||
[ObservableProperty]
|
||
private string _syncApiEndpoint = string.Empty;
|
||
|
||
[ObservableProperty]
|
||
private string _scanIntervalDays = "0";
|
||
|
||
[ObservableProperty]
|
||
private string _scanIntervalHours = "0";
|
||
|
||
[ObservableProperty]
|
||
private string _scanIntervalMinutes = "1";
|
||
|
||
[ObservableProperty]
|
||
private string _scanIntervalSeconds = "0";
|
||
|
||
[ObservableProperty]
|
||
private string _adminCardId = "ADMIN";
|
||
|
||
[ObservableProperty]
|
||
private string _saveMessage = string.Empty;
|
||
|
||
[ObservableProperty]
|
||
private bool _isError;
|
||
|
||
[ObservableProperty]
|
||
private bool _isSaving;
|
||
|
||
[ObservableProperty]
|
||
private bool _isPosting;
|
||
|
||
|
||
public bool CanPostNow => !IsPosting;
|
||
public string PostButtonText => IsPosting ? "Posting..." : "Post Data";
|
||
|
||
partial void OnIsPostingChanged(bool value)
|
||
{
|
||
OnPropertyChanged(nameof(PostButtonText));
|
||
OnPropertyChanged(nameof(CanPostNow));
|
||
}
|
||
|
||
public SettingsViewModel(
|
||
IConfigService configService,
|
||
INavigationService navigation,
|
||
IAdminAuditService adminAudit,
|
||
ISyncService syncService)
|
||
{
|
||
_configService = configService;
|
||
_navigation = navigation;
|
||
_adminAudit = adminAudit;
|
||
_syncService = syncService;
|
||
LoadFromConfig();
|
||
}
|
||
|
||
/// <summary>Loads config from service.</summary>
|
||
public void LoadFromConfig()
|
||
{
|
||
SyncApiEndpoint = _configService.GetSyncApiEndpoint();
|
||
ScanIntervalDays = _configService.GetScanIntervalDays().ToString();
|
||
ScanIntervalHours = _configService.GetScanIntervalHours().ToString();
|
||
ScanIntervalMinutes = _configService.GetScanIntervalMinutes().ToString();
|
||
ScanIntervalSeconds = _configService.GetScanIntervalSeconds().ToString();
|
||
|
||
// Always prefer the latest admin login from the database.
|
||
var last = _adminAudit.GetLastLogin();
|
||
if (last != null && !string.IsNullOrWhiteSpace(last.EmployeeId))
|
||
AdminCardId = last.EmployeeId;
|
||
else
|
||
AdminCardId = "ADMIN";
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void Save()
|
||
{
|
||
IsSaving = true;
|
||
if (!int.TryParse(ScanIntervalDays, out var days) || days < 0 || days > 365)
|
||
{
|
||
SaveMessage = "Scan interval Days must be 0–365.";
|
||
IsError = true;
|
||
IsSaving = false;
|
||
return;
|
||
}
|
||
if (!int.TryParse(ScanIntervalHours, out var hours) || hours < 0 || hours > 23)
|
||
{
|
||
SaveMessage = "Scan interval Hours must be 0–23.";
|
||
IsError = true;
|
||
IsSaving = false;
|
||
return;
|
||
}
|
||
if (!int.TryParse(ScanIntervalMinutes, out var minutes) || minutes < 0 || minutes > 59)
|
||
{
|
||
SaveMessage = "Scan interval Minutes must be 0–59.";
|
||
IsError = true;
|
||
IsSaving = false;
|
||
return;
|
||
}
|
||
if (!int.TryParse(ScanIntervalSeconds, out var seconds) || seconds < 0 || seconds > 59)
|
||
{
|
||
SaveMessage = "Scan interval Seconds must be 0–59.";
|
||
IsError = true;
|
||
IsSaving = false;
|
||
return;
|
||
}
|
||
if (days == 0 && hours == 0 && minutes == 0 && seconds == 0)
|
||
{
|
||
SaveMessage = "Scan interval cannot be zero. Use at least 1 second.";
|
||
IsError = true;
|
||
IsSaving = false;
|
||
return;
|
||
}
|
||
|
||
_configService.SetSyncApiEndpoint(SyncApiEndpoint?.Trim() ?? string.Empty);
|
||
_configService.SetScanIntervalDays(days);
|
||
_configService.SetScanIntervalHours(hours);
|
||
_configService.SetScanIntervalMinutes(minutes);
|
||
_configService.SetScanIntervalSeconds(seconds);
|
||
_configService.SetAdminCardId(AdminCardId?.Trim() ?? string.Empty);
|
||
SaveMessage = "Settings saved.";
|
||
IsError = false;
|
||
IsSaving = false;
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void Back()
|
||
{
|
||
_navigation.NavigateBackFromSettings(GetDashboardTimeout());
|
||
}
|
||
|
||
/// <summary>Opens Meal Schedules admin screen (Phase 2.5).</summary>
|
||
[RelayCommand]
|
||
private void OpenMealSchedules()
|
||
{
|
||
_navigation.NavigateToMealSchedules();
|
||
}
|
||
|
||
[RelayCommand]
|
||
private async Task PostDataNow()
|
||
{
|
||
if (IsPosting)
|
||
return;
|
||
|
||
SaveMessage = string.Empty;
|
||
IsError = false;
|
||
IsPosting = true;
|
||
|
||
try
|
||
{
|
||
// If not configured, do not attempt sync.
|
||
if (string.IsNullOrWhiteSpace(_configService.GetMySqlConnectionString()))
|
||
{
|
||
SaveMessage = "MySQL connection string not configured.";
|
||
IsError = true;
|
||
return;
|
||
}
|
||
|
||
await _syncService.SyncNowAsync().ConfigureAwait(false);
|
||
SaveMessage = "Posted data to production.";
|
||
IsError = false;
|
||
}
|
||
catch
|
||
{
|
||
SaveMessage = "Failed to post data to production.";
|
||
IsError = true;
|
||
}
|
||
finally
|
||
{
|
||
IsPosting = false;
|
||
}
|
||
}
|
||
|
||
private TimeSpan GetDashboardTimeout() => _configService.GetScanInterval();
|
||
}
|