Compare commits

...
2 Commits
Author SHA1 Message Date
Nick SzaunigandClaude Opus 5 bffcce127d fix: "Passwort vergessen" schob sich ueber das CAPTCHA
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 2m41s
Im Anmeldeformular standen CAPTCHA, Absenden-Knopf und der
"Passwort vergessen"-Link in EINER Flex-Zeile ohne Umbruch:

    <div className="flex items-center justify-between gap-4">

Das Turnstile-Widget ist ein iframe mit FESTER Breite von rund 300 px und
schrumpft nicht mit. Die Zeile steht zudem in einer der beiden Spalten
der Kontoseite, hat also nur die halbe Breite zur Verfuegung. Der Platz
reichte daher nie — die Elemente schoben sich uebereinander, und zwar
nicht nur auf schmalen Bildschirmen.

Jetzt steht das Widget auf einer eigenen Zeile, Knopf und Link darunter
in einer Zeile mit "flex-wrap". Das Registrierungsformular daneben hat es
schon immer so gemacht; die beiden sind damit endlich gleich aufgebaut.

Damit das an keiner Stelle wiederkommen kann, traegt das Widget selbst
jetzt "w-fit max-w-full overflow-x-auto". Das ist kein Schoenheitsmittel,
sondern eine Zusicherung: der iframe bleibt in jedem Fall innerhalb
seines Kastens. Ist der zu schmal, laesst sich der Inhalt seitlich
schieben, statt das Layout zu zerlegen — unabhaengig davon, wie eine
kuenftige Seite ihn einbettet.

Die uebrigen sieben Einbindungen (Registrierung, Passwort vergessen,
Passwort zuruecksetzen, Zwei-Faktor-Code, Produktseite, Firmenanfrage,
Newsletter, Checkout) habe ich geprueft: dort steht das Widget bereits
auf einer eigenen Zeile.

tsc: 0 Fehler. vitest: 359/359 gruen. eslint: 0 Warnungen.
"next build" laeuft durch.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-20 02:52:15 +02:00
Nick SzaunigandClaude Opus 5 7f9ed7262f refactor: Liefergebiet bekommt einen eigenen Abschnitt "Versand"
Die Einstellung lag unter "Firmendaten" — zwischen Firmenname, Slogan und
Anschrift. Dort sucht sie niemand: eine Versandregel ist keine
Stammdatenangabe. Genau das ist beim ersten Suchen auch passiert.

Jetzt ein eigener Abschnitt "Versand" (englisch "Shipping") unter
Admin → Inhalte → Texte, direkt hinter den Firmendaten. Der
Feldtyp-Vertrag der Registry bekommt dafuer die Gruppe "shipping".

Rein organisatorisch — Schluessel, Wert und Verhalten bleiben gleich, ein
bereits gepflegter Wert wandert einfach mit.

tsc: 0 Fehler. vitest: 359/359 gruen. eslint: 0 Warnungen.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-20 02:16:06 +02:00
7 changed files with 24 additions and 4 deletions

No files matched your search

+1
View File
@@ -205,6 +205,7 @@ export default async function AdminInhaltePage(props: PageProps<"/admin/inhalte"
const groups: { key: ContentFieldDef["group"]; heading: string }[] = [
{ key: "company", heading: t.adminContentPage.groupCompany },
{ key: "shipping", heading: t.adminContentPage.groupShipping },
{ key: "home", heading: t.adminContentPage.groupHome },
{ key: "pages", heading: t.adminContentPage.groupPages },
{ key: "social", heading: t.adminContentPage.groupSocial },
+8 -1
View File
@@ -47,10 +47,17 @@ export default async function KontoPage(props: PageProps<"/konto">) {
<h2 className="text-lg text-forest">{t.account.login}</h2>
<Field name="email" label={t.account.emailLabel} type="email" required autoComplete="email" />
<PasswordField name="password" label={t.account.passwordLabel} required autoComplete="current-password" />
<div className="flex items-center justify-between gap-4">
{/* Das Turnstile-Widget ist ein iframe mit FESTER Breite (rund
300 px) und kann nicht mitschrumpfen. In einer Zeile mit
Knopf und Link — noch dazu in einer der beiden Spalten
dieser Seite — reichte der Platz nie: die Elemente schoben
sich uebereinander. Deshalb steht es auf einer eigenen
Zeile, und Knopf und Link duerfen darunter umbrechen. Das
Registrierungsformular daneben macht es schon immer so. */}
{process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY ? (
<TurnstileField siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY} />
) : null}
<div className="flex flex-wrap items-center gap-x-4 gap-y-2">
<Button type="submit">{t.account.login}</Button>
<Link href="/konto/passwort-vergessen" className="text-xs text-ink/65 hover:text-forest underline">
{t.account.forgotPassword}
+10 -1
View File
@@ -166,8 +166,17 @@ export function TurnstileWidget({ siteKey, onVerify }: TurnstileWidgetProps) {
};
}, [siteKey, attempt]);
// "max-w-full overflow-x-auto" ist kein Schoenheitsmittel, sondern eine
// Zusicherung: Cloudflare liefert einen iframe mit FESTER Breite (rund
// 300 px), der nicht mitschrumpft. Steht er in einem schmaleren Kasten,
// ragt er heraus und schiebt sich ueber das, was daneben liegt — auf der
// Kontoseite traf das den "Passwort vergessen"-Link. Mit diesen Klassen
// bleibt er in jedem Fall innerhalb seines Kastens; ist der zu schmal,
// laesst sich der Inhalt seitlich schieben, statt das Layout zu zerlegen.
// "w-fit" verhindert zugleich, dass der Kasten in einer Flex-Zeile mehr
// Platz beansprucht als der iframe braucht.
return (
<div>
<div className="w-fit max-w-full overflow-x-auto">
<div ref={containerRef} />
{failed ? (
<p className="text-sm text-red-700">
+1
View File
@@ -1164,6 +1164,7 @@ export const de: Dictionary = {
sectionText: "Texte",
sectionTextIntro: "Alle Textinhalte, sortiert nach Bereich.",
groupCompany: "Firmendaten",
groupShipping: "Versand",
groupHome: "Homepage",
groupPages: "Weitere Seiten",
groupLegal: "Rechtstexte",
+1
View File
@@ -1163,6 +1163,7 @@ export const en: Dictionary = {
sectionText: "Text",
sectionTextIntro: "Every text field, grouped by section.",
groupCompany: "Company details",
groupShipping: "Shipping",
groupHome: "Homepage",
groupPages: "Other pages",
groupLegal: "Legal pages",
+1
View File
@@ -856,6 +856,7 @@ export interface Dictionary {
sectionText: string;
sectionTextIntro: string;
groupCompany: string;
groupShipping: string;
groupHome: string;
groupPages: string;
groupLegal: string;
+2 -2
View File
@@ -18,7 +18,7 @@ export type ContentFieldType =
export interface ContentFieldDef {
key: string;
group: "company" | "home" | "pages" | "legal" | "social";
group: "company" | "shipping" | "home" | "pages" | "legal" | "social";
labelDe: string;
labelEn: string;
type: ContentFieldType;
@@ -73,7 +73,7 @@ export const CONTENT_REGISTRY: ContentFieldDef[] = [
// Auswahl und kein Freitext — siehe "options" oben.
{
key: "shipping.region",
group: "company",
group: "shipping",
labelDe: "Liefergebiet",
labelEn: "Shipping region",
type: "select",