Fix order-filter dropdowns, restructure Konto identity line, drop blog reset link

- CustomSelect.tsx: mousedown on an option blurred the trigger button
  before the click landed, unmounting the list before anything could be
  selected — add preventDefault on the list's mousedown to stop that.
- KontoShell no longer renders "Eingeloggt als ..." above each page's
  content; each page renders its own title then AccountIdentity right
  below it, and ProfileForm's now-duplicate email/Kundennummer line is
  removed.
- Blog category filter: drop the separate "Zurücksetzen" link — clicking
  an active category badge again already deactivates it.
- Werkzeuge cards: more vertical gap between stacked cards below sm:.
- Legal pages' "Stand: ..." line is now derived from the LegalPages doc's
  own updatedAt instead of a hand-typed string.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018unaXmuzVA8ct1b6WoyP1U
This commit is contained in:
Marco
2026-07-31 22:29:36 +00:00
parent d018d87e25
commit bf6c5d079a
15 changed files with 80 additions and 50 deletions
+18 -5
View File
@@ -165,7 +165,7 @@ explains what does have access instead.
| `discount-codes` | Cart discount input (`/cart`, display-only on `/checkout`) | `code`, `type` (`percent`/`fixed`), `value`, `validFrom`/`validUntil`, `minOrderValue`, `maxRedemptions`, `redemptionCount` (server-incremented only), `active`. **Not public-read** — see Discount codes section below |
| `posts` | `/blog`, `/blog/[slug]` | `title`, `slug`, `categories` (`hasMany` relation to `categories` — a post can have several, joined with `", "` wherever rendered), `excerpt`, `thumbnail`, `content` (richText, supports custom Lexical blocks — Bild/Bildergalerie/Video/Zitat — rendered via `app/components/RichText.tsx`'s `@payloadcms/richtext-lexical/react` renderer with custom `JSXConverters`), `readTime` (auto-calculated on save from word count), `featured` (shown as the `/blog` hero post; most-recently-published wins if several are marked), `publishedAt`, `quoteLabel` (label + icon + underline shown next to every blockquote in `content`, default `"Merke dir:"` — leave empty to hide that framing, the blockquote text itself still renders), `relatedProduct` (optional relation to `products`, powers the "Passend dazu" card at the end of the post — leave empty to hide that card, or empty if the linked product has no `detailHref`), `seoTitle`/`seoDescription`/`seoImage` (each falls back to `title`/`excerpt`/`thumbnail` when empty, consumed by `/blog/[slug]`'s `generateMetadata()`) |
| `categories` | Blog post categorization | `name`, `slug` (unique per tenant, not globally) |
| `legal-pages` | `/impressum`, `/datenschutz`, `/agb`, `/widerruf` | `type` (`impressum`/`datenschutz`/`agb`/`widerruf`, one doc per type per tenant), `title`, `content` (richText), `attachment` (optional file, e.g. the Muster-Widerrufsformular PDF) |
| `legal-pages` | `/impressum`, `/datenschutz`, `/agb`, `/widerruf` | `type` (`impressum`/`datenschutz`/`agb`/`widerruf`, one doc per type per tenant), `title`, `content` (richText), `attachment` (optional file, e.g. the Muster-Widerrufsformular PDF). Each page's "Stand: …" line is derived from this doc's own `updatedAt` (`formatMonthYear()` in `app/lib/format.ts`), not a hand-typed string — it updates automatically the moment an admin edits the content, no separate field to remember |
| `trust-badges` | Horizontal "Schneller Versand / Versandkostenfrei / Mit Liebe verpackt" row — shown on `/shop`, `/cart`, `/checkout`, `/widerruf`, `/agb`, 404 | `title`, `description` (supports `{{lieferzeit}}`/`{{kostenfreiab}}` placeholders, resolved by the frontend from `shipping-settings`/`shipping-methods` at render time — not by Payload itself), `icon`, `sortOrder` |
| `cart-trust-badges` | Sidebar bullets on `/cart` (title only) and `/checkout` (title + description) — deliberately a separate collection from `trust-badges` so the two pages can't drift into showing different claims | `title`, `description`, `icon`, `sortOrder` |
| `shipping-methods` | `/checkout` shipping selection | `title` (no day-range in the title text — that lives in `shipping-settings` now, keeping both in one title used to drift), `description`, `price`, `freeShippingThreshold` (per-method, optional — leave empty for a method that should never be free, e.g. Express), `active` (inactive methods are hidden, not shown disabled), `sortOrder` |
@@ -1269,16 +1269,29 @@ whatever page sent the visitor to log in instead of always
`orders/[orderNumber]` (PATCH — cancel/return-request, see "Order
cancellation & returns" below), and `orders/[orderNumber]/invoice`
(GET — invoice PDF download, see "Invoice PDFs" below).
- **`app/konto/components/KontoShell.tsx`** is the shared shell for every
logged-in `/konto/*` page (bestellungen, merkliste, profil) —
`AccountNav.tsx` (persistent sidebar on `sm:`+, a horizontal tab bar
below it) plus the `<main>`/`<Footer>` wrapping used to be duplicated
per page, with the equivalent of the nav buried as plain links at the
bottom of the orders list (unreachable once that list got long). Each
page still owns its own auth-check/redirect/data-fetching and renders
its own heading; right under that heading it renders
`AccountIdentity.tsx` ("Eingeloggt als …, Kundennummer …") so that line
looks identical on every page without `KontoShell` itself needing to
know each page's title. `AccountNav` also renders the "Abmelden"
button (logout, folded into the nav rather than living at the bottom of
a specific page).
- **`/konto/bestellungen`** lists a customer's own orders — a per-card CSS
Grid (`grid grid-cols-2 min-[500px]:grid-cols-4`, so every card's
Bestellnummer/Datum/Artikel/Status/Zahlungsstatus/Gesamtbetrag fields
line up at identical x-positions regardless of label width, dropping to
2 columns below 500px), status shown as a colored `OrderStatusBadge.tsx`
plus a `PaymentStatusBadge.tsx` (Offen/Bezahlt/…, in the same
red/subtle-background style as a failed fulfillment status when unpaid),
plus an "Abmelden" link (`LogoutButton.tsx`); optional
status/paymentStatus/year filters (`OrderFilters.tsx`, 3 `CustomSelect`
dropdowns, URL-search-param-driven) when the tenant's `orderFilterEnabled`
red/subtle-background style as a failed fulfillment status when unpaid);
optional status/paymentStatus/year filters (`OrderFilters.tsx`, 3
`CustomSelect` dropdowns, URL-search-param-driven, collapsed behind a
"Filter" toggle below `sm:`) when the tenant's `orderFilterEnabled`
toggle is on (see "Feature toggles" below). **`/konto/bestellungen/[orderNumber]`**
shows one order's full detail (items, address, totals, `status`, plus
companyName/VAT-ID and a VAT-exemption note when the order has them). A