feat(ui): split SettingsModalViewModel into per-tab VMs + add PrimeClaudeTabViewModel

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mika Kuns
2026-04-28 09:18:39 +02:00
parent f890fa85b9
commit 8b02b63d3d
10 changed files with 389 additions and 175 deletions

View File

@@ -0,0 +1,81 @@
using System.Collections.ObjectModel;
using ClaudeDo.Ui.Services;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace ClaudeDo.Ui.ViewModels.Modals.Settings;
public sealed partial class PrimeClaudeTabViewModel : ViewModelBase
{
private readonly IPrimeScheduleApi _api;
private readonly HashSet<Guid> _initialIds = new();
public ObservableCollection<PrimeScheduleRowViewModel> Rows { get; } = new();
public PrimeClaudeTabViewModel(IPrimeScheduleApi api) => _api = api;
public async Task LoadAsync()
{
Rows.Clear();
_initialIds.Clear();
var list = await _api.ListAsync();
foreach (var dto in list)
{
Rows.Add(new PrimeScheduleRowViewModel(dto, isExisting: true));
_initialIds.Add(dto.Id);
}
}
public string? Validate()
{
foreach (var r in Rows)
{
if (r.StartDate > r.EndDate)
return $"Schedule {r.TimeOfDay:hh\\:mm}: start date is after end date.";
if (r.TimeOfDay < TimeSpan.Zero || r.TimeOfDay >= TimeSpan.FromDays(1))
return "Time must be between 00:00 and 23:59.";
}
return null;
}
public async Task SaveAsync()
{
var keepIds = Rows.Select(r => r.Id).ToHashSet();
foreach (var removed in _initialIds.Where(id => !keepIds.Contains(id)).ToList())
await _api.DeleteAsync(removed);
foreach (var r in Rows)
await _api.UpsertAsync(r.ToDto());
_initialIds.Clear();
foreach (var id in keepIds) _initialIds.Add(id);
}
[RelayCommand]
private void AddSchedule()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var dto = new PrimeScheduleDto(
Id: Guid.NewGuid(),
StartDate: today,
EndDate: today.AddDays(30),
TimeOfDay: new TimeSpan(7, 0, 0),
WorkdaysOnly: true,
Enabled: true,
LastRunAt: null,
PromptOverride: null);
Rows.Add(new PrimeScheduleRowViewModel(dto, isExisting: false));
}
[RelayCommand]
private void RemoveSchedule(PrimeScheduleRowViewModel? row)
{
if (row is null) return;
Rows.Remove(row);
}
public void ApplyFiredEvent(PrimeFiredEvent evt)
{
var row = Rows.FirstOrDefault(r => r.Id == evt.ScheduleId);
if (row is null) return;
if (evt.Success) row.LastRunAt = evt.FiredAt;
}
}