Render FAQ topics as cards, drop dead scoped CSS

This commit is contained in:
tleininger committed 2026-09-30 14:58:12 +02:00
1 parent 2ea8856d65
commit e38ebf078d
11 files changed
+260 -46

No files matched your search

+27
View File
@@ -43,6 +43,33 @@ public record Faq
[JsonPropertyName("answer")]
public required string Answer { get; init; }
/// <summary>
/// Gets the sort order of the question within its topic.
/// </summary>
/// <value>
/// The sort key; questions with smaller values appear first.
/// </value>
[JsonPropertyName("order")]
public double Order { get; init; }
/// <summary>
/// Gets whether this entry is published and may be shown to visitors.
/// </summary>
/// <value>
/// <see langword="true"/> when the entry is public, <see langword="false"/> for a
/// draft that must stay hidden.
/// </value>
/// <remarks>
/// Collection queries filter on <c>public=true</c> server-side, so entries loaded
/// that way are always public and never need this checked. It matters only for the
/// <c>faqs_via_topic</c> back-relation expand behind <see cref="FaqTopic.Faqs"/>:
/// PocketBase does not apply the topic query's <c>public</c> filter to expanded
/// child records, so a draft question would otherwise leak onto the topic page.
/// That getter filters on this to keep drafts hidden.
/// </remarks>
[JsonPropertyName("public")]
public bool Public { get; init; }
/// <summary>
/// Gets the expanded relations returned by PocketBase, or <see langword="null"/>
/// when the query did not expand any.
+46 -1
View File
@@ -38,7 +38,7 @@ public record FaqTopic
public required string Title { get; init; }
/// <summary>
/// Gets the URL slug of the topic, e.g. <c>"mensa"</c>.
/// Gets the URL slug of the topic, e.g. <c>"cafeteria"</c>.
/// </summary>
/// <value>
/// A URL path segment: lowercase letters, digits and single hyphens as
@@ -70,4 +70,49 @@ public record FaqTopic
/// </value>
[JsonPropertyName("order")]
public double Order { get; init; }
/// <summary>
/// Gets the expanded relations returned by PocketBase, or <see langword="null"/>
/// when the query did not expand any.
/// </summary>
[JsonPropertyName("expand")]
public FaqTopicExpand? Expand { get; init; }
/// <summary>
/// Gets the questions of this topic, ordered by <see cref="Faq.Order"/>, or an
/// empty list when none are linked or the relation was not expanded.
/// </summary>
/// <remarks>
/// Convenience over <see cref="Expand"/>: questions name their topic, so
/// PocketBase returns them under the back-relation key when the query expands it
/// (<c>faqs_via_topic</c>). The topic detail page reads them from here. They
/// arrive unsorted, so this orders them by <see cref="Faq.Order"/> for a stable
/// render. Drafts are dropped: PocketBase does not apply the topic query's
/// <c>public</c> filter to the expanded children, so this keeps
/// non-public questions (<see cref="Faq.Public"/>) off the page.
/// </remarks>
[JsonIgnore]
public IReadOnlyList<Faq> Faqs =>
Expand?.Faqs is { } faqs
? [.. faqs.Where(faq => faq.Public).OrderBy(faq => faq.Order)]
: [];
}
/// <summary>
/// The relations of a <see cref="FaqTopic"/> that PocketBase returns under
/// <c>expand</c> when the query asks for them.
/// </summary>
/// <remarks>
/// The questions point at their topic, so PocketBase exposes them as the
/// back-relation <c>faqs_via_topic</c>. <see cref="FaqTopic.Faqs"/> reads through
/// this.
/// </remarks>
public record FaqTopicExpand
{
/// <summary>
/// Gets the expanded questions of the <c>faqs_via_topic</c> back-relation, if it
/// was expanded.
/// </summary>
[JsonPropertyName("faqs_via_topic")]
public IReadOnlyList<Faq>? Faqs { get; init; }
}