Phase 0 of the e-invoicing migration plan (see the E-Rechnung planning
session) — moves invoicePdf.tsx, correctionInvoicePdf.tsx, and
taxBreakdown.ts into a new shared package, consumed as a git dependency
by both this repo and the payload backend, instead of hand-duplicating
the correction-invoice logic between them (see that package's own README
for the three real drifts the duplication had already caused).
Consumed as raw TS/TSX source via next.config.ts's transpilePackages, not
a pre-built package. Needs `git` in the Docker deps stage and a
project .npmrc (allow-git=root) to let npm ci fetch a git-URL dependency
at all — npm 12+ disables that by default.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same row shape as the Gesamtsumme total line itself (label left, flex-1
spacer, value right) instead of the grid — label stays flush with
"Gesamtsumme", rate+amount land flush right under the total's own €
figure. Fixed-width rate column keeps multiple rates aligned to each
other regardless of digit count.
Back to self-start (flush with "Gesamtsumme", not pinned under the total
€ amount). Multi-rate case switched from a stacked flex column to a
3-column CSS grid so the first rate sits on the same line as "enthält
MwSt.:" instead of dropping to its own row — grid auto-sizes each column
to its widest cell across all rows, so the rate column still stays
aligned between single- and double-digit rates without a hardcoded width.
self-end instead of self-start so the block sits directly beneath the
total's € amount (same right edge) rather than flush left. Dropped the
per-rate rows' pl-2 indent to match — now flush with the "enthält MwSt:"
label above them instead of offset from it.
The earlier right-alignment fix spanned the row edge-to-edge across the
full summary panel (same width as the Gesamtsumme total line), which
visually disconnected the "enthält X% MwSt." hint from its own amount on
wide panels. Reverted to content-sized (self-start, no w-full/flex-1
spacer), with a fixed-width right-aligned rate column instead so
single-digit rates (7%) still line up with two-digit ones (19%).
- Removed the inline "Nur noch wenige verfügbar" text hint from
AddToCartButton/AddToCartInlineButton (was making card heights vary in
every grid that renders them — RelatedProducts, ProductSpotlight's CTA
row) — now only shown via the same image-overlaid pill badge
Ausverkauft/discount already use (position: absolute, doesn't affect
layout). Added that badge to RelatedProducts.tsx and todo-cards'
Pricing.tsx, which didn't have it before.
- RelatedProducts cards now also show "inkl. X% MwSt." (was missing
entirely)
- VatBreakdown rows are now flex rows with a spacer instead of plain
text, so every € amount right-aligns to the same edge regardless of
how many digits the rate itself has (was visibly staggered with mixed
7%/19% rates)
- Cart's manual discount-code field only renders when Payload actually
has at least one active code right now (lib/discountServer.ts's new
hasActiveDiscountCode()) — no point showing an open field that could
never validate. An already-applied code (e.g. from an older session)
still always shows its own result row regardless.
- Checkout's "1. Rechnungsadresse" no longer offers a Packstation option
— a Packstation isn't a valid billing address for an invoice. Only a
plain street address now; Packstation is only offered on the separate,
optional "Abweichende Lieferadresse" section, which already had its own
address/Packstation toggle.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bug fixes:
- Navbar login/logout state now updates immediately (custom ep-auth-changed
event) instead of requiring a hard reload
- Status-change email links were broken by an un-encoded "#" in the order
number; fixed for all 4 status emails
- Cart discount code: manual input field restored (was removed entirely)
- Quote-label underline now scales with the label's actual text width
- Number Ranges admin list now shows the invoice prefix/counter columns
Pricing & VAT:
- Prices show the real per-product VAT rate ("inkl. X% MwSt.") instead of
a generic disclosure
- Cart/checkout/confirmation totals show the actual € amount of VAT
included, broken down per rate when a cart spans more than one
(new lib/taxBreakdown.ts, shared with the invoice PDF's own math)
- Account order pages gained product thumbnails and the same VAT breakdown
Low-stock warning: a "Nur noch wenige verfügbar" badge/hint across the
shop grid, spotlight, and add-to-cart variant pickers, driven by the
existing lowStockThreshold field (still never exposes raw stock counts).
Invoice PDFs: product thumbnails on every line item, a plain "Netto"
label (rate was redundant, already stated on the MwSt. line below), no
more duplicate USt-IdNr. in the header, and — for a Stornorechnung
specifically — an explicit "Versand" line that was previously only
folded silently into the tax totals.
Checkout:
- Optional deviating shipping address (separate from the billing address
used for the invoice), with its own toggle + address form
- Full checkout draft persistence (name/address/shipping/payment
selections) survives navigating away and back, via localStorage
- Invoice PDF shows a third "Lieferadresse" block when the shipping
address differs from billing
Mobile navigation: fullscreen panel with a circular reveal animation from
the hamburger's corner, replacing the old in-flow accordion drawer; no
login CTA inside it (redundant with the always-visible header icon).
Admin-facing (Payload backend, mirrored where the frontend has a ported
copy of the same renderer): dashboard rebuilt as individual cards, split
into 3 task queues (received/processing/returns) instead of 2, revenue
and order counts now exclude cancelled/returned orders immediately, and
the low-stock alert links to the specific affected product(s) instead of
the unfiltered list. A new immediate email notifies the shop owner the
moment an order comes in, instead of only via the daily digest.
Testimonials admin list now groups by page instead of interleaving all
three grids' entries. ~45 English admin field descriptions translated to
German for consistency.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>