using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Text; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; namespace ClaudeDo.Ui.ViewModels.Islands.Detail; public partial class SubtaskRowSampleViewModel : ObservableObject { [ObservableProperty] string _title = ""; [ObservableProperty] bool _done; [ObservableProperty] bool _isEditing; [RelayCommand] void ToggleDone() => Done = !Done; [RelayCommand] void BeginEdit() => IsEditing = true; [RelayCommand] void CommitEdit() => IsEditing = false; } public partial class DescriptionStepsCardViewModel : ClaudeDo.Ui.ViewModels.ViewModelBase { [ObservableProperty] [NotifyPropertyChangedFor(nameof(IsDescriptionView))] bool _isStepsView; public bool IsDescriptionView => !IsStepsView; [ObservableProperty] [NotifyPropertyChangedFor(nameof(ComposedPreview))] string _title = ""; [ObservableProperty] [NotifyPropertyChangedFor(nameof(ComposedPreview))] string _editableDescription = ""; [ObservableProperty] bool _isEditingDescription; [ObservableProperty] string _newSubtaskTitle = ""; public ObservableCollection Subtasks { get; } = new(); public string ComposedPreview => BuildComposedPreview(); [RelayCommand] void ToggleCardView() => IsStepsView = !IsStepsView; [RelayCommand] void ToggleEditDescription() => IsEditingDescription = !IsEditingDescription; [RelayCommand] void AddSubtask() { if (string.IsNullOrWhiteSpace(NewSubtaskTitle)) return; var row = new SubtaskRowSampleViewModel { Title = NewSubtaskTitle.Trim() }; row.PropertyChanged += OnRowPropertyChanged; Subtasks.Add(row); NewSubtaskTitle = ""; OnPropertyChanged(nameof(ComposedPreview)); } [RelayCommand] void ToggleSubtaskDone(SubtaskRowSampleViewModel row) { row.Done = !row.Done; } [RelayCommand] void CommitSubtaskEdit(SubtaskRowSampleViewModel row) { row.IsEditing = false; } private void OnRowPropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName is nameof(SubtaskRowSampleViewModel.Done) or nameof(SubtaskRowSampleViewModel.Title)) OnPropertyChanged(nameof(ComposedPreview)); } private void OnSubtasksChanged(object? sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems is not null) foreach (SubtaskRowSampleViewModel row in e.NewItems) row.PropertyChanged += OnRowPropertyChanged; if (e.OldItems is not null) foreach (SubtaskRowSampleViewModel row in e.OldItems) row.PropertyChanged -= OnRowPropertyChanged; OnPropertyChanged(nameof(ComposedPreview)); } private string BuildComposedPreview() { var sb = new StringBuilder(); sb.AppendLine(Title); if (!string.IsNullOrWhiteSpace(EditableDescription)) { sb.AppendLine(); sb.AppendLine(EditableDescription.TrimEnd()); } var openSteps = Subtasks.Where(s => !s.Done).ToList(); if (openSteps.Count > 0) { sb.AppendLine(); sb.AppendLine("## Sub-Tasks"); foreach (var step in openSteps) sb.AppendLine($"- [ ] {step.Title}"); } return sb.ToString().TrimEnd(); } public DescriptionStepsCardViewModel() { Subtasks.CollectionChanged += OnSubtasksChanged; _title = "Refactor diff viewer"; _editableDescription = "Split the current monolithic diff renderer into smaller, testable components.\n\n" + "The goal is to improve readability and allow unit testing of each parsing stage independently."; var samples = new[] { new SubtaskRowSampleViewModel { Title = "Extract DiffParser into its own class", Done = true }, new SubtaskRowSampleViewModel { Title = "Add unit tests for DiffParser", Done = true }, new SubtaskRowSampleViewModel { Title = "Wire new parser into DiffViewerViewModel" }, new SubtaskRowSampleViewModel { Title = "Update snapshot tests" }, }; foreach (var row in samples) { row.PropertyChanged += OnRowPropertyChanged; Subtasks.Add(row); } } }