Commit Graph

9 Commits

Author SHA1 Message Date
Peter Meier c9ba88ab80 feat: OrganisationsMapBlock — Karte der Bürgerinitiativen
Deploy / verify (push) Successful in 1m5s
Deploy / deploy (push) Successful in 1m13s
Neuer Block-Typ `organisations_map`: Leaflet-Karte mit CircleMarkern für alle
Organisationen die ein location.lat/lng haben. Klick auf Marker öffnet
Detail-Panel (Desktop: rechte Sidebar / Mobile: Bottom Sheet) mit Name,
Standort, Beschreibung und Website-Link.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 12:03:26 +02:00
Peter Meier 363d4edb76 feat: Adressbuch-Block mit Suche, Org- und Buchstabenfilter
Deploy / verify (push) Successful in 1m14s
Deploy / deploy (push) Successful in 1m18s
- AdressbuchBlock: listet alle Kontakte alphabetisch mit Suche,
  Org-Filter-Chips und A–Z-Buchstabenfilter; /adressbuch-Seite
- ContactCard: neues Design passend zu OrganisationsCard (Badges, Links)
- ContactsBlock: Karussell mit snap-scroll, volle Breite
- block-types, blog-utils, cms: AdressbuchBlockData, resolveAdressbuchBlocks,
  getContacts; BlockRenderer registriert adressbuch
- Kontakt-Seite: Link auf /adressbuch statt eingebettetem Block

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 10:08:54 +02:00
Peter Meier 7bd62b75b0 feat(contacts): ContactCard + ContactsBlock-Komponente, BlockRenderer registriert
Deploy / verify (push) Successful in 1m8s
Deploy / deploy (push) Successful in 1m13s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 08:49:23 +02:00
Peter Meier 6d0861bb0a 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>
2026-05-27 14:41:00 +02:00
Peter Meier b7bcdd76ee feat(calendar): compact variant for next-events teaser
Deploy / verify (push) Successful in 1m8s
Deploy / deploy (push) Successful in 1m13s
Calendar block now supports variant: "default" | "compact".
- default = full calendar (unchanged)
- compact = next N events (default 3) + link to a target page

New CalendarCompactBlock.svelte: small card with month/day badge,
title, date/time/location line, "Alle kommenden Termine →" footer
link resolved from the schema's linkTo reference. Filters to future
events (12h tolerance for running ones).

BlockRenderer dispatches by block.variant inside the calendar case.
Schema (cms_content/_types/core/calendar.json5) adds variant + linkTo
+ limit fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 08:49:08 +02:00
Peter Meier 81c82c33e6 perf: review-fixes (N+1, waterfalls, sanitize-cache, lazy strommix)
Deploy / verify (push) Successful in 56s
Deploy / deploy (push) Successful in 1m3s
- blog-utils.resolvePostOverviewBlocks: parallel getPostBySlug via
  Promise.all + .catch(null) instead of sequential await loop.
- blog-utils.resolveCalendarBlocks: same fix for calendar items.
- [...slug] page load: SearchableText/Calendar/DeadlineBanner now run
  parallel after tagsMap (was strict waterfall).
- sanitize-blocks: LRU cache keyed on raw html input — sanitize-html is
  ~ms/KB, the same content repeats across pages and cache hits.
- cms.getNormalizedTranslations: WeakMap-memoised the per-request
  Object.entries normalize loop on top of the existing 5-min bundle TTL.
- cms.cached: opt-in dev cache via DEV_CACHE_CMS=1 (default still off).
- rusty-image.ensureTransformedImage: was async-wrapping a sync URL
  builder; made sync, removed awaits at call sites — saves microtasks.
- BlockRenderer: lazy-load StrommixBlock (~220 KB) via dynamic import
  in the template — pages without the live-strommix widget no longer
  ship its bundle.

Also: enabled Caddy zstd+gzip on windwiderstand.de vhost (server-side
edit; verified `content-encoding: zstd` on response).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 12:30:15 +02:00
Peter Meier 9e05fbb2ba feat: add internal_component block type with contact form
InternalComponentBlock dispatches on `component` field value.
ContactFormComponent submits via /api/contact (SvelteKit proxy →
CMS /api/forms/kontakt/submit) with honeypot + client_age_ms.
BlockRenderer and block-types.ts updated accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:01:47 +02:00
Peter Meier 39d7d70c8b feat(windkarte): Leaflet-Block für Windvorranggebiete SWT
Deploy / verify (push) Successful in 58s
Deploy / deploy (push) Successful in 1m18s
Neuer CMS-Block `wind_map` — platzierbar auf jeder Seite per Row-Content.
Fetcht wind_area-Einträge + GeoJSON-Asset client-side, rendert Leaflet-Karte
(CartoDB Light) mit farbcodierten Polygonen nach Planungsstatus. Klick auf
Gebiet öffnet Slide-in-Panel mit Kenndaten, Gemeinden, Stellungnahme-Link
und Puffer-Ringen (200/600/1000 m via Turf). Erweiterbar für 2. Entwurf 2026.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 09:20:32 +02:00
Peter Meier 63a9721841 feat(embed): standalone widget route /widget/<collection>/<slug>
Deploy / verify (push) Successful in 51s
Deploy / deploy (push) Successful in 53s
Renders a single CMS entry as a block in isolation — no header, footer, or
preview banner. Lets us share a deep link to a single widget (e.g. the live
strommix gauge) for embedding or quick previews without exposing the rest of
the page.

- New BlockRenderer.svelte: switch over `_type` shared with ContentRows.
- Generic `getEntryBySlug(collection, slug, options)` in cms.ts so any
  collection (live_strommix, deadline_banner, image, ...) is fetchable.
- Route group `(embed)/+layout@.svelte` resets the layout chain so no
  Header/Footer/TopBanner inherit. `x-robots-tag: noindex`.
- Optional `?preview=<token>` for drafts. Cache: short s-maxage for live,
  no-store for preview.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 09:37:21 +02:00