feat(stellungnahme): Einwendungs-Assistent für Windvorranggebiete
Deploy / verify (push) Successful in 59s
Deploy / deploy (push) Successful in 2m37s

5-Schritt-Wizard: Gebietskontext → Argumente wählen → Ausgabeform →
persönliche Betroffenheit → Absender + Ausgabe. Alle Eingaben bleiben
lokal im Browser (kein Server-Transfer). Fertigtext- und Leitfaden-Modus.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Peter Meier
2026-05-27 14:41:00 +02:00
parent d781b3140e
commit 6d0861bb0a
7 changed files with 771 additions and 1 deletions
+73
View File
@@ -4,6 +4,8 @@ import {
getPostBySlug,
getTags,
getTextFragmentBySlug,
getTextFragmentsByTag,
getEntryBySlug,
getCalendarBySlug,
getCalendarItemBySlug,
getCalendarItems,
@@ -760,3 +762,74 @@ export async function resolveSearchableTextBlocks(
}
}
}
function isStellingnahmeGeneratorBlock(item: unknown): boolean {
return (item as { _type?: string })?._type === "stellungnahme_generator";
}
/** Löst stellungnahme_generator-Blöcke auf:
* - windArea → vollständiges wind_area-Objekt mit aufgelösten stellungnahme_kriterien
* - allgemeineArgumenteTag → allgemeineArgumente[] via Tag-Filter
*/
export async function resolveStellingnahmeGeneratorBlocks(
layout: RowContentLayout | null | undefined,
): Promise<void> {
if (!layout) return;
const rows = [
layout.row1Content ?? [],
layout.row2Content ?? [],
layout.row3Content ?? [],
];
for (const content of rows) {
if (!Array.isArray(content)) continue;
for (const item of content) {
if (!isStellingnahmeGeneratorBlock(item)) continue;
const block = item as Record<string, unknown>;
// Resolve windArea
const windAreaRef = block.windArea;
const windAreaSlug =
typeof windAreaRef === "string"
? windAreaRef
: (windAreaRef as { _slug?: string })?._slug ?? "";
if (windAreaSlug) {
const windArea = await getEntryBySlug("wind_area", windAreaSlug, {
locale: "de",
resolve: ["stellungnahme_kriterien"],
depth: 2,
});
if (windArea) {
const kriterienRaw =
(windArea as { stellungnahme_kriterien?: unknown[] })
.stellungnahme_kriterien ?? [];
// Fragmente einzeln laden um bulletPoints zu bekommen (nicht im Basis-Resolve)
const kriterien = await Promise.all(
kriterienRaw.map(async (k) => {
const slug =
typeof k === "string"
? k
: (k as { _slug?: string })?._slug ?? "";
if (!slug) return null;
return getTextFragmentBySlug(slug, { locale: "de" });
}),
);
(windArea as Record<string, unknown>).stellungnahme_kriterien =
kriterien.filter(Boolean);
block.windArea = windArea;
}
}
// Resolve allgemeineArgumente via Tag
const tagRef = block.allgemeineArgumenteTag;
const tagSlug =
typeof tagRef === "string"
? tagRef
: (tagRef as { _slug?: string })?._slug ?? "";
if (tagSlug) {
block.allgemeineArgumente = await getTextFragmentsByTag(tagSlug, {
locale: "de",
});
}
}
}
}