using Elternbeirat.Contracts; using Elternbeirat.PocketBase; using Elternbeirat.Web.Shared; using Microsoft.AspNetCore.Components; namespace Elternbeirat.Web.Features.Posts; public partial class PostDetail { [LoggerMessage( Level = LogLevel.Error, Message = "Could not load post '{Slug}' from PocketBase; content source is unavailable.")] private static partial void LogSourceUnavailable( ILogger logger, string slug, Exception exception); [Parameter] public string Slug { get; set; } = string.Empty; [Inject] private PocketBaseClient PocketBase { get; set; } = null!; [Inject] private ILogger Logger { get; set; } = null!; [Inject] private NavigationManager Navigation { get; set; } = null!; [CascadingParameter] private HttpContext? HttpContext { get; set; } private Post? _post; // Set when the content source could not be reached or read. The markup then // shows a "temporarily unavailable" note instead of a not-found page, matching // the 503 this sets on the response. private bool _unavailable; // The post body rendered from Markdown to HTML, ready to emit as a // MarkupString in the markup. private MarkupString Body => (MarkupString)Markdown.ToHtml(_post?.Body); protected override async Task OnParametersSetAsync() { try { var posts = await PocketBase.GetPostsAsync(HttpContext?.RequestAborted ?? CancellationToken.None); _post = posts.FirstOrDefault( post => string.Equals(post.Slug, Slug, StringComparison.OrdinalIgnoreCase)); } catch (PocketBaseUnavailableException exception) { // The site works, its data store is down: 503, not 404. LogSourceUnavailable(Logger, Slug, exception); _unavailable = true; SourceUnavailable.SetStatus(HttpContext); return; } if (_post is null) { // The source answered, but there is no post with this slug: a genuine 404. Navigation.NotFound(); } } }