feat(ui): planning sessions UI (Plan C) #5

Merged
mikakuns merged 9 commits from feat/planning-sessions-ui into main 2026-04-23 17:38:09 +00:00
2 changed files with 57 additions and 3 deletions
Showing only changes of commit 0e116bec7b - Show all commits

View File

@@ -139,6 +139,9 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
// Set by the view so DeleteTaskCommand can prompt yes/no before deleting // Set by the view so DeleteTaskCommand can prompt yes/no before deleting
public Func<string, System.Threading.Tasks.Task<bool>>? ConfirmAsync { get; set; } public Func<string, System.Threading.Tasks.Task<bool>>? ConfirmAsync { get; set; }
// Set by the view so DeleteTaskCommand can show an error message
public Func<string, System.Threading.Tasks.Task>? ShowErrorAsync { get; set; }
public DetailsIslandViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory, WorkerClient worker, IServiceProvider services) public DetailsIslandViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory, WorkerClient worker, IServiceProvider services)
{ {
_dbFactory = dbFactory; _dbFactory = dbFactory;
@@ -537,9 +540,20 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
var ok = await ConfirmAsync($"Delete \"{row.Title}\"? This cannot be undone."); var ok = await ConfirmAsync($"Delete \"{row.Title}\"? This cannot be undone.");
if (!ok) return; if (!ok) return;
} }
try
{
await using var ctx = _dbFactory.CreateDbContext(); await using var ctx = _dbFactory.CreateDbContext();
var repo = new TaskRepository(ctx); var repo = new TaskRepository(ctx);
await repo.DeleteAsync(row.Id); await repo.DeleteAsync(row.Id);
}
catch (DbUpdateException ex) when (
ex.Message.Contains("FOREIGN KEY", StringComparison.OrdinalIgnoreCase)
|| ex.InnerException?.Message.Contains("FOREIGN KEY", StringComparison.OrdinalIgnoreCase) == true)
{
if (ShowErrorAsync != null)
await ShowErrorAsync("This task has child tasks. Discard the planning session or delete child tasks first.");
return;
}
if (DeleteFromList != null) if (DeleteFromList != null)
await DeleteFromList(row); await DeleteFromList(row);
CloseDetail?.Invoke(); CloseDetail?.Invoke();

View File

@@ -45,9 +45,49 @@ public partial class DetailsIslandView : UserControl
}; };
vm.ConfirmAsync = ShowConfirmAsync; vm.ConfirmAsync = ShowConfirmAsync;
vm.ShowErrorAsync = ShowErrorDialogAsync;
} }
} }
private async System.Threading.Tasks.Task ShowErrorDialogAsync(string message)
{
var owner = TopLevel.GetTopLevel(this) as Window;
if (owner == null) return;
var ok = new Button { Content = "OK", MinWidth = 90 };
var dialog = new Window
{
Title = "Error",
Width = 360,
SizeToContent = SizeToContent.Height,
CanResize = false,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
ShowInTaskbar = false,
Background = this.FindResource("SurfaceBrush") as IBrush,
Content = new StackPanel
{
Spacing = 16,
Margin = new Thickness(20),
Children =
{
new TextBlock { Text = message, TextWrapping = TextWrapping.Wrap },
new StackPanel
{
Orientation = Orientation.Horizontal,
Spacing = 8,
HorizontalAlignment = HorizontalAlignment.Right,
Children = { ok }
}
}
}
};
ok.Click += (_, _) => dialog.Close();
await dialog.ShowDialog(owner);
}
private async System.Threading.Tasks.Task<bool> ShowConfirmAsync(string message) private async System.Threading.Tasks.Task<bool> ShowConfirmAsync(string message)
{ {
var owner = TopLevel.GetTopLevel(this) as Window; var owner = TopLevel.GetTopLevel(this) as Window;