feat(ui): tickets + plan day button, fallback list and prime action

This commit is contained in:
mika kuns
2026-10-01 08:44:21 +02:00
parent 9fc2e26edb
commit e35b054a2e
16 changed files with 242 additions and 12 deletions
@@ -1,10 +1,16 @@
using System.Collections.ObjectModel;
using ClaudeDo.Data;
using ClaudeDo.Ui.Localization;
using ClaudeDo.Ui.Services;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.EntityFrameworkCore;
namespace ClaudeDo.Ui.ViewModels.Modals.Settings;
/// <summary>One fallback-list choice; Id null = no fallback.</summary>
public sealed record FallbackListOption(string? Id, string Name);
public sealed partial class TicketSettingsTabViewModel : ViewModelBase
{
/// <summary>
@@ -21,6 +27,7 @@ public sealed partial class TicketSettingsTabViewModel : ViewModelBase
public const bool FeatureEnabled = true;
private readonly IWorkerClient _worker;
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
[ObservableProperty] private string _apiBaseUrl = "";
[ObservableProperty] private string _token = "";
@@ -33,7 +40,17 @@ public sealed partial class TicketSettingsTabViewModel : ViewModelBase
// Never shows the stored token — TicketSettingsDto only ever carries the bool.
public string TokenPlaceholder => TokenSet ? Loc.T("settings.tickets.tokenSet") : "";
public TicketSettingsTabViewModel(IWorkerClient worker) => _worker = worker;
public ObservableCollection<FallbackListOption> FallbackLists { get; } = new();
[ObservableProperty] private FallbackListOption? _selectedFallbackList;
// Only a successful load may write the fallback back — otherwise an offline load would clear it.
private bool _fallbackLoaded;
public TicketSettingsTabViewModel(IWorkerClient worker, IDbContextFactory<ClaudeDoDbContext> dbFactory)
{
_worker = worker;
_dbFactory = dbFactory;
}
public async Task LoadAsync()
{
@@ -45,6 +62,17 @@ public sealed partial class TicketSettingsTabViewModel : ViewModelBase
}
ApiBaseUrl = dto.ApiBaseUrl ?? "";
TokenSet = dto.TokenSet;
await using var ctx = await _dbFactory.CreateDbContextAsync();
var lists = await ctx.Lists.AsNoTracking()
.OrderBy(l => l.SortOrder).ThenBy(l => l.Name)
.Select(l => new FallbackListOption(l.Id, l.Name))
.ToListAsync();
FallbackLists.Clear();
FallbackLists.Add(new FallbackListOption(null, Loc.T("settings.tickets.fallbackNone")));
foreach (var option in lists) FallbackLists.Add(option);
SelectedFallbackList = FallbackLists.FirstOrDefault(o => o.Id == dto.FallbackListId) ?? FallbackLists[0];
_fallbackLoaded = true;
}
public async Task SaveAsync()
@@ -56,6 +84,8 @@ public sealed partial class TicketSettingsTabViewModel : ViewModelBase
Token = "";
TokenSet = true;
}
if (_fallbackLoaded)
await _worker.SetTicketFallbackListAsync(SelectedFallbackList?.Id);
}
[RelayCommand]