diff --git a/src/PostIt/PostIt/ViewModels/MainPageViewModel.cs b/src/PostIt/PostIt/ViewModels/MainPageViewModel.cs index d907606f..d1d16306 100644 --- a/src/PostIt/PostIt/ViewModels/MainPageViewModel.cs +++ b/src/PostIt/PostIt/ViewModels/MainPageViewModel.cs @@ -35,6 +35,18 @@ public partial class MainPageViewModel : ViewModelBase [ObservableProperty] public partial string DraftArticle { get; set; } + /// Editor buffer for the post's publication state. + /// Reflects the server-side IsPublished flag (the + /// existence of a row in BlogSpotPublication) and + /// is pushed to the server via + /// on explicit + /// toggle — it is NOT included in the regular Save + /// payload, mirroring the wire contract where + /// BlogPostDto doesn't carry Publish as a + /// mutable field. Toggling is its own action. + [ObservableProperty] + public partial bool DraftIsPublished { get; set; } + [ObservableProperty] public partial ViewModelBase? CurrentViewModel { get; set; } @@ -102,6 +114,7 @@ public partial class MainPageViewModel : ViewModelBase WindowTitle = "PostIt"; DraftTitle = string.Empty; DraftArticle = string.Empty; + DraftIsPublished = false; CurrentViewModel = this; } @@ -131,6 +144,9 @@ public partial class MainPageViewModel : ViewModelBase // doesn't show stale content. DraftTitle = value?.Title ?? string.Empty; DraftArticle = value?.Article ?? string.Empty; + // Mirror publication state too. Defaults to false on + // null selection so a fresh draft starts unpublished. + DraftIsPublished = value?.IsPublished ?? false; UpdateCommandStates(); } @@ -241,6 +257,46 @@ public partial class MainPageViewModel : ViewModelBase }); } + /// + /// Toggle the publication state of the currently selected + /// post. Pushes the new state to + /// PUT /api/BlogApi/{id}/publish and reflects it + /// locally in + the + /// selected post so the UI updates without a full + /// refresh. + /// + /// The toggle is its own action — separate from Save + /// — because Publish is not part of the + /// BlogPostDto payload. Bundling it into Save + /// would require a wire-shape change and a second server + /// overload; the dedicated endpoint keeps the wire + /// contract clean. + /// + [RelayCommand] + internal async Task TogglePublish() + { + if (SelectedPost is null || SelectedPost.Id == 0) + { + StatusMessage = "Sélectionnez un billet existant pour changer sa publication."; + return; + } + + await ExecuteAsync(async () => + { + var desired = !DraftIsPublished; + await BlogClient.SetPublishAsync(SelectedPost.Id, desired); + DraftIsPublished = desired; + // Mirror into the selected post so a subsequent + // RefreshPostsAsync() doesn't blow away the + // locally flipped state until the round-trip + // re-hydrates it. + SelectedPost.IsPublished = desired; + StatusMessage = desired + ? $"Billet {SelectedPost.Id} publié." + : $"Billet {SelectedPost.Id} remis en brouillon."; + }); + } + [RelayCommand] internal void OpenSettings() { diff --git a/src/PostIt/PostIt/Views/MainPage.axaml b/src/PostIt/PostIt/Views/MainPage.axaml index c6e7fb10..0246857e 100644 --- a/src/PostIt/PostIt/Views/MainPage.axaml +++ b/src/PostIt/PostIt/Views/MainPage.axaml @@ -35,6 +35,18 @@