Serve FAQs from PocketBase on a grouped /faqs page

This commit is contained in:
tleininger committed 2026-09-23 14:15:16 +02:00
1 parent 4136af6417
commit 6b5d9dda55
7 files changed
+127 -7

No files matched your search

@@ -0,0 +1,28 @@
@page "/faqs"
<PageTitle>Häufige Fragen</PageTitle>
<h1>Häufige Fragen</h1>
@if (_groups.Count == 0)
{
<p>Zurzeit gibt es keine Fragen.</p>
}
else
{
@foreach (var group in _groups)
{
<section class="faq-topic">
<h2>@TopicLabel(group.Key)</h2>
@foreach (var faq in group)
{
<details class="faq-item">
<summary>@faq.Question</summary>
<div class="faq-answer">
@((MarkupString)Markdown.ToHtml(faq.Answer))
</div>
</details>
}
</section>
}
}
@@ -0,0 +1,48 @@
using Elternbeirat.Contracts;
using Elternbeirat.PocketBase;
using Microsoft.AspNetCore.Components;
namespace Elternbeirat.Web.Features.Faqs;
public partial class FaqList
{
[LoggerMessage(Level = LogLevel.Warning, Message = "Could not load FAQs from PocketBase.")]
private static partial void LogLoadFailed(ILogger logger, Exception exception);
// German heading per topic. Unknown topics fall back to the raw key so a new
// topic in PocketBase still shows up rather than being silently dropped.
private static readonly Dictionary<string, string> TopicLabels =
new(StringComparer.Ordinal)
{
["mensa"] = "Mensa und Mittagessen",
["schliessfach"] = "Schließfächer",
["elterneuro"] = "Eltern-Euro",
["elternarbeit"] = "Elternarbeit und Mitmachen",
};
[Inject]
private PocketBaseClient PocketBase { get; set; } = default!;
[Inject]
private ILogger<FaqList> Logger { get; set; } = default!;
private IReadOnlyList<IGrouping<string, Faq>> _groups = [];
protected override async Task OnInitializedAsync()
{
try
{
var faqs = await PocketBase.GetFaqsAsync();
_groups = [.. faqs.GroupBy(faq => faq.Topic)];
}
catch (HttpRequestException ex)
{
// Source unreachable -> show an empty page instead of a 500. The page
// stays up; the "keine Fragen" note is rendered.
LogLoadFailed(Logger, ex);
}
}
private static string TopicLabel(string topic) =>
TopicLabels.TryGetValue(topic, out var label) ? label : topic;
}
@@ -0,0 +1,22 @@
.faq-topic {
margin-bottom: 2rem;
}
.faq-topic h2 {
margin-bottom: 0.5rem;
}
.faq-item {
border-bottom: 1px solid #eee;
padding: 0.5rem 0;
}
.faq-item summary {
cursor: pointer;
font-weight: 600;
}
.faq-answer {
padding: 0.5rem 0 0.25rem;
color: #333;
}