From 96dd88247de73b9c392ed84af8c5d18694831b50 Mon Sep 17 00:00:00 2001 From: Peter Meier Date: Wed, 27 May 2026 15:57:27 +0200 Subject: [PATCH] feat(stellungnahme): UX-Verbesserungen, localStorage, Mini-Map, Druck MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - localStorage: Formularstand + Ausgabe-Historie (max 5) persistieren - Fortsetzen-Banner: gespeicherte Sitzung erkannt → Sprung zu letztem Schritt - Neustart-Button: alles inkl. localStorage leeren - Frist-Banner: deadline-Feld in StellingnahmeGeneratorBlockData, Ampelfarben - Step 1 überspringen wenn keine ortskonkreten Argumente vorhanden - Step-Indikator: goTo() statt step= (scrollt jetzt korrekt) - "Alle wählen" öffnet Gruppe automatisch - Download als .txt neben Kopieren/Drucken -
für konsistentes Schriftbild im Output - Mini-Map für Vorranggebiet in Step 0 (tap-to-activate, fitBoundsMaxZoom=13) - WindkarteMap: fitBoundsMaxZoom-Prop ergänzt - Druckausgabe: 13pt Serif, 2cm Ränder, kein Markdown im Fertigtext Co-Authored-By: Claude Sonnet 4.6 --- src/lib/block-types.ts | 2 + src/lib/components/WindkarteMap.svelte | 4 +- .../blocks/StellingnahmeGeneratorBlock.svelte | 904 ++++++++++++------ 3 files changed, 593 insertions(+), 317 deletions(-) diff --git a/src/lib/block-types.ts b/src/lib/block-types.ts index 0d81891..9e9e72f 100644 --- a/src/lib/block-types.ts +++ b/src/lib/block-types.ts @@ -468,5 +468,7 @@ export interface StellingnahmeGeneratorBlockData { allgemeineArgumenteTag?: string | { _slug: string; name?: string }; /** Vom Resolver befüllt: allgemeine (gebietsunabhängige) Fragmente via Tag. */ allgemeineArgumente?: TextFragment[]; + /** ISO-Datum: Einwendungsfrist-Ende (z.B. "2026-07-04"). */ + deadline?: string; layout?: BlockLayout; } diff --git a/src/lib/components/WindkarteMap.svelte b/src/lib/components/WindkarteMap.svelte index d89a7e4..aae832d 100644 --- a/src/lib/components/WindkarteMap.svelte +++ b/src/lib/components/WindkarteMap.svelte @@ -11,6 +11,7 @@ initialGebietsNr = null, hiddenStatuses = [], hiddenRings = [], + fitBoundsMaxZoom = 11, }: { areas: WindArea[]; onselect: (area: WindArea | null, center: [number, number] | null) => void; @@ -18,6 +19,7 @@ initialGebietsNr?: string | null; hiddenStatuses?: string[]; hiddenRings?: string[]; + fitBoundsMaxZoom?: number; } = $props(); const t = useTranslate(); @@ -167,7 +169,7 @@ map!.fitBounds((layer as import("leaflet").Polygon).getBounds(), { paddingTopLeft: [40, 40], paddingBottomRight: [desktop ? 320 : 40, desktop ? 40 : 300], - maxZoom: 11, + maxZoom: fitBoundsMaxZoom, }); } } diff --git a/src/lib/components/blocks/StellingnahmeGeneratorBlock.svelte b/src/lib/components/blocks/StellingnahmeGeneratorBlock.svelte index 5b199d8..fb510d4 100644 --- a/src/lib/components/blocks/StellingnahmeGeneratorBlock.svelte +++ b/src/lib/components/blocks/StellingnahmeGeneratorBlock.svelte @@ -1,8 +1,13 @@ -
+
+ + {#if deadlineDays !== null && deadlineDays >= 0} + {@const urgent = deadlineDays <= 3} + {@const soon = deadlineDays <= 7} +
+ + + Einwendungsfrist: {deadlineFormatted} + {#if deadlineDays === 0}— heute letzter Tag! + {:else if deadlineDays === 1}— morgen letzter Tag! + {:else}— noch {deadlineDays} Tage + {/if} + +
+ {/if} + -
+
Ihre Daten bleiben auf Ihrem Gerät. Name, Anschrift und alle Eingaben werden nicht an Server übertragen.
- + + {#if hadSavedState && step === 0} +
+ Letzte Sitzung wiederhergestellt. +
+ {#if outputHistory.length > 0} + + {:else if selectedSlugs.size > 0} + + {/if} + +
+
+ {/if} + {#if block.headline}

{block.headline}

{/if} {#if block.intro} -
- {@html md(block.intro)} -
+
{@html md(block.intro)}
{/if}
- {#each ([0, 1, 2, 3, 4] as const) as s} + {#each Array.from({ length: TOTAL_STEPS }, (_, i) => i) as s} - {#if s < 4} + {#if s < TOTAL_STEPS - 1}
{/if} {/each}
- + {#if step === 0}
-

- Schritt 1 – Ihr Vorranggebiet -

+

Schritt 1 – Ihr Vorranggebiet

{#if windArea}
-
- Vorranggebiet -
+
Vorranggebiet
{windArea.gebiets_nr}
{#if windArea.bezeichnung}
{windArea.bezeichnung}
{/if} -
{#if windArea.gemeinden?.length}
@@ -315,145 +546,228 @@ Karl-Liebknecht-Straße 4
{/if}
- {#if windArea.notizen} -
- {@html md(windArea.notizen)} -
+
{@html md(windArea.notizen)}
{/if}
+ + + {#if browser && MapComponent && mapReady && mapAreaData.length > 0} +
+ {#await MapComponent then Map} + {}} + /> + {/await} + {#if !mapActive} + + {/if} +
+ {:else if mapReady && mapAreaData.length === 0} + + {:else if !mapReady} +
+ Karte wird geladen … +
+ {/if} + {:else}
- Kein Vorranggebiet konfiguriert. Bitte Seite im CMS einrichten. + Kein Vorranggebiet konfiguriert.
{/if}

Dieser Assistent hilft Ihnen, eine individuelle Einwendung für den 2. Entwurf des Regionalplans Südwestthüringen zu verfassen. - Im nächsten Schritt wählen Sie die Argumente, die auf Ihre Situation zutreffen. + Sie wählen zuerst ortskonkrete Argumente für Ihr Gebiet, dann allgemeine Einwände.

- - +
+ + {#if selectedSlugs.size > 0 || absenderName} + + {/if} +
- + {:else if step === 1}
-

- Schritt 2 – Argumente wählen -

+

Schritt 2 – Ortskonkrete Argumente

- Wählen Sie alle Punkte, die auf Ihr Gebiet und Ihre Situation zutreffen. - Ortskonkrete Argumente sind vorausgewählt. + Diese Argumente beziehen sich direkt auf das Gebiet {windArea?.gebiets_nr ?? ""}. + Wählen Sie die Punkte, die auf Ihre Situation zutreffen.

- {#if ortskonkreteKriterien.length > 0} -
-
- - Ortskonkrete Argumente -
-
- {#each ortskonkreteKriterien as k} -