using System.Globalization; using ClaudeDo.Data.Models; using ClaudeDo.Ui.Localization; using ClaudeDo.Ui.Services; using CommunityToolkit.Mvvm.ComponentModel; namespace ClaudeDo.Ui.ViewModels.Modals.Settings; public sealed partial class PrimeScheduleRowViewModel : ViewModelBase { private const int Mon = 1, Tue = 2, Wed = 4, Thu = 8, Fri = 16, Sat = 32, Sun = 64; public Guid Id { get; } public bool IsExisting { get; } [ObservableProperty] private bool _enabled; [ObservableProperty] private bool _monday; [ObservableProperty] private bool _tuesday; [ObservableProperty] private bool _wednesday; [ObservableProperty] private bool _thursday; [ObservableProperty] private bool _friday; [ObservableProperty] private bool _saturday; [ObservableProperty] private bool _sunday; [ObservableProperty] private TimeSpan _timeOfDay; [ObservableProperty] private DateTimeOffset? _lastRunAt; [ObservableProperty] private string? _promptOverride; [ObservableProperty] private PrimeActionKind _kind; public string LastRunLabel => LastRunAt is { } v ? v.LocalDateTime.ToString("g") : "—"; private static readonly string[] TimeFormats = { @"h\:mm", @"hh\:mm" }; public string TimeText { get => TimeOfDay.ToString(@"hh\:mm", CultureInfo.InvariantCulture); set { if (TimeSpan.TryParseExact(value, TimeFormats, CultureInfo.InvariantCulture, out var t) && t >= TimeSpan.Zero && t < TimeSpan.FromDays(1)) { TimeOfDay = t; } OnPropertyChanged(nameof(TimeText)); } } /// Per-row group name. A shared GroupName would make every schedule in the /// ItemsControl share one selection. public string RadioGroup => $"prime-kind-{Id}"; // One boolean per kind rather than an enum-to-bool converter: RadioButton.IsChecked binds // TwoWay to a bool, and compiled bindings stay simple. public bool IsPing { get => Kind == PrimeActionKind.Ping; set { if (value) Kind = PrimeActionKind.Ping; } } public bool IsFillMyDay { get => Kind == PrimeActionKind.FillMyDay; set { if (value) Kind = PrimeActionKind.FillMyDay; } } public bool IsCustom { get => Kind == PrimeActionKind.Custom; set { if (value) Kind = PrimeActionKind.Custom; } } public bool IsImportTickets { get => Kind == PrimeActionKind.ImportTickets; set { if (value) Kind = PrimeActionKind.ImportTickets; } } public bool ShowPrompt => Kind != PrimeActionKind.Ping; public string PromptLabel => Kind == PrimeActionKind.Custom ? Loc.T("settings.prime.customPromptLabel") : Loc.T("settings.prime.promptOverrideLabel"); public string PromptPlaceholder => Kind == PrimeActionKind.Custom ? Loc.T("settings.prime.customPromptPlaceholder") : Loc.T("settings.prime.promptOverridePlaceholder"); partial void OnKindChanged(PrimeActionKind value) { OnPropertyChanged(nameof(IsPing)); OnPropertyChanged(nameof(IsFillMyDay)); OnPropertyChanged(nameof(IsCustom)); OnPropertyChanged(nameof(IsImportTickets)); OnPropertyChanged(nameof(ShowPrompt)); OnPropertyChanged(nameof(PromptLabel)); OnPropertyChanged(nameof(PromptPlaceholder)); } partial void OnLastRunAtChanged(DateTimeOffset? value) => OnPropertyChanged(nameof(LastRunLabel)); partial void OnTimeOfDayChanged(TimeSpan value) => OnPropertyChanged(nameof(TimeText)); public PrimeScheduleRowViewModel(PrimeScheduleDto dto, bool isExisting) { Id = dto.Id; IsExisting = isExisting; Enabled = dto.Enabled; Monday = (dto.Days & Mon) != 0; Tuesday = (dto.Days & Tue) != 0; Wednesday = (dto.Days & Wed) != 0; Thursday = (dto.Days & Thu) != 0; Friday = (dto.Days & Fri) != 0; Saturday = (dto.Days & Sat) != 0; Sunday = (dto.Days & Sun) != 0; TimeOfDay = dto.TimeOfDay; LastRunAt = dto.LastRunAt; PromptOverride = dto.PromptOverride; Kind = dto.Kind; } public int DaysMask() { int m = 0; if (Monday) m |= Mon; if (Tuesday) m |= Tue; if (Wednesday) m |= Wed; if (Thursday) m |= Thu; if (Friday) m |= Fri; if (Saturday) m |= Sat; if (Sunday) m |= Sun; return m; } public PrimeScheduleDto ToDto() => new(Id, DaysMask(), TimeOfDay, Enabled, LastRunAt, string.IsNullOrWhiteSpace(PromptOverride) ? null : PromptOverride, Kind); }