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 _initialIds = new(); [ObservableProperty] private int _dailyPrepMaxTasks = 5; public ObservableCollection 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.DaysMask() == 0) return $"Schedule {r.TimeOfDay:hh\\:mm}: select at least one day."; 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 dto = new PrimeScheduleDto( Id: Guid.NewGuid(), Days: 31, // Mon–Fri TimeOfDay: new TimeSpan(7, 0, 0), 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; } }