FAQ im Inhalte-Editor vollständig bearbeitbar: Bereich je Frage statt verschachtelter sections

Die Bereiche der FAQ-Seite lagen als verschachtelte Listen in sections, der Editor zeigte
davon nur JSON-Text. Jetzt stehen alle Fragen in questions mit dem Feld category, Überschrift
und Symbol der Bereiche in categories. FAQ::groups baut daraus die Seite (allgemeine Fragen
zuerst), alte Einträge werden weiter dargestellt. FaqCategoriesSeeder stellt gespeicherte
Einträge um (FAQ und Immobilien-FAQ), Texte bleiben.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-10-09 09:50:44 +00:00
parent 69d50eed0f
commit dc31cdb401
8 changed files with 406 additions and 208 deletions

View file

@ -20,8 +20,84 @@ class FAQ extends Component
$this->content = cms_theme_section($this->section);
}
/**
* Fragen nach Bereich gruppiert, in Seitenreihenfolge: zuerst die allgemeinen Fragen ohne
* Bereich, dann die Bereiche aus `categories` (Überschrift + Symbol), zuletzt Bereiche, die nur
* an Fragen stehen. Leere Bereiche entfallen.
*
* @param array<string, mixed> $content
* @return list<array{title: ?string, icon: ?string, questions: list<array<string, mixed>>}>
*/
public static function groups(array $content): array
{
$content = self::flatten($content);
$groups = ['' => ['title' => null, 'icon' => null, 'questions' => []]];
foreach ($content['categories'] ?? [] as $category) {
$title = trim((string) ($category['title'] ?? ''));
if ($title !== '') {
$groups[$title] = ['title' => $title, 'icon' => ($category['icon'] ?? '') ?: 'question-mark-circle', 'questions' => []];
}
}
foreach ($content['questions'] ?? [] as $question) {
if (! is_array($question) || trim((string) ($question['question'] ?? '')) === '') {
continue;
}
$title = trim((string) ($question['category'] ?? ''));
$groups[$title] ??= ['title' => $title, 'icon' => 'question-mark-circle', 'questions' => []];
$groups[$title]['questions'][] = $question;
}
return array_values(array_filter($groups, fn (array $group): bool => $group['questions'] !== []));
}
/**
* Wandelt die frühere Form mit verschachtelten `sections` (Bereich mit eigener Fragenliste) in
* die flache Form um, die der Inhalte-Editor bearbeiten kann (09.10.2026): jede Frage trägt
* ihren Bereich in `category`, Überschrift und Symbol stehen in `categories`.
*
* @param array<string, mixed> $content
* @return array<string, mixed>
*/
public static function flatten(array $content): array
{
if (! isset($content['sections']) || ! is_array($content['sections'])) {
return $content;
}
$questions = array_map(
fn (mixed $question): mixed => is_array($question) ? [...$question, 'category' => $question['category'] ?? ''] : $question,
is_array($content['questions'] ?? null) ? $content['questions'] : [],
);
$categories = is_array($content['categories'] ?? null) ? $content['categories'] : [];
foreach ($content['sections'] as $section) {
if (! is_array($section)) {
continue;
}
$title = trim((string) ($section['title'] ?? ''));
$categories[] = ['title' => $title, 'icon' => (string) ($section['icon'] ?? '')];
foreach ($section['questions'] ?? [] as $question) {
if (is_array($question)) {
$questions[] = [...$question, 'category' => $title];
}
}
}
unset($content['sections']);
$content['questions'] = $questions;
$content['categories'] = $categories;
return $content;
}
public function render()
{
return view('livewire.web.components.sections.f-a-q');
return view('livewire.web.components.sections.f-a-q', ['groups' => self::groups($this->content)]);
}
}