feat(ui): Polish-Durchgang Admin und Mobil, Erstattung nur mit Rueckfrage

Sicherheit: "Jetzt per Stripe erstatten" loeste die Rueckerstattung bisher
mit einem einzigen Klick aus. Erstatten und Ablehnen einer Retoure laufen
jetzt ueber ConfirmForm; die Rueckfrage nennt Bestellnummer und Betrag.

Admin: Produkte, Bestellungen und Retouren nutzen dieselben Bausteine wie
die uebrigen Listen (Seitenkopf, Suche mit Zusatzfiltern und Archiv-
Parameter, Status-Badges, Leerzustaende). Produkttabelle ohne seitliches
Scrollen bei 1440 px: Bearbeiten ueber den Produktnamen, Charge ohne
Umbruch. Geschenk-Markierung als SVG statt Emoji. Letzte rohe Knoepfe
(Bestelldetail, ApiCore, Inhalte) auf Button umgestellt.

Mobil (390 px): Ueberlauf auf /konto (Datenexport) und /kontakt
(E-Mail-Adresse) behoben. Tippziele unter 24 px vergroessert
(Zurueck-Link, "Zum Honig", Links auf der Produktseite). Wunschliste mit
SVG-Stern statt Unicode-Zeichen.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-09-25 21:24:55 +02:00
1 parent b7a75dddca
commit 11eccec01b
16 files changed
+221 -155

No files matched your search

+1 -1
View File
@@ -72,7 +72,7 @@ export function AdminArchiveToggle({
{archivedManually ? ` · ${labels.manualHint}` : null}
</span>
) : null}
<button type="submit" className="text-xs text-ink/65 underline hover:text-forest">
<button type="submit" className="link-draw cursor-pointer text-ink/70 hover:text-forest">
{archivedAt ? labels.restore : labels.archive}
</button>
</form>
+14 -1
View File
@@ -39,6 +39,9 @@ export function AdminSearchForm({
submitLabel,
resetHref,
resetLabel,
hiddenFields = {},
children,
isFiltered,
}: {
query: string;
label: string;
@@ -46,9 +49,18 @@ export function AdminSearchForm({
submitLabel: string;
resetHref: string;
resetLabel: string;
/** Mitzusendende Parameter, z.B. die Archiv-Ansicht. */
hiddenFields?: Record<string, string>;
/** Weitere Filterfelder (z.B. Status-Auswahl) zwischen Suche und Knopf. */
children?: ReactNode;
/** Ob "Filter zuruecksetzen" erscheint; Standard: sobald gesucht wird. */
isFiltered?: boolean;
}) {
return (
<form method="GET" role="search" className="mb-6 flex flex-wrap items-end gap-3">
{Object.entries(hiddenFields).map(([name, value]) => (
<input key={name} type="hidden" name={name} value={value} />
))}
<label className="text-sm">
<span className="mb-1 block text-xs text-ink/65">{label}</span>
<input
@@ -59,13 +71,14 @@ export function AdminSearchForm({
className="w-64 max-w-full border border-ink/20 bg-background px-3 py-2 text-sm"
/>
</label>
{children}
<button
type="submit"
className="border border-forest px-4 py-2 text-sm text-forest transition-colors duration-300 hover:bg-forest hover:text-cream"
>
{submitLabel}
</button>
{query ? (
{(isFiltered ?? query !== "") ? (
<Link href={resetHref} className="link-draw py-2 text-sm text-ink/65">
{resetLabel}
</Link>
+3 -2
View File
@@ -1,6 +1,7 @@
import { syncApiCoreAction } from "@/app/admin/actions";
import { getLocale } from "@/i18n/locale";
import { getDictionary } from "@/i18n/get-dictionary";
import { Button } from "@/components/ui";
/**
* Der eine Sync-Knopf und die Anzeige seines Ergebnisses.
@@ -95,9 +96,9 @@ export async function ApiCoreSyncPanel({ returnTo }: { returnTo: string }) {
<p className="text-sm text-ink/65 mb-4">{t.intro}</p>
<form action={syncApiCoreAction}>
<input type="hidden" name="returnTo" value={returnTo} />
<button type="submit" className="bg-forest text-cream px-6 py-2 text-sm">
<Button type="submit" className="px-5 py-2.5">
{t.button}
</button>
</Button>
</form>
</div>
);
+1 -1
View File
@@ -9,7 +9,7 @@ export function BackLink({ href, label }: { href: string; label: string }) {
return (
<Link
href={href}
className="inline-flex items-center gap-1.5 text-sm text-ink/70 hover:text-forest mb-6"
className="-mt-1.5 mb-4.5 inline-flex items-center gap-1.5 py-1.5 text-sm text-ink/70 hover:text-forest"
>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75">
<path d="M15 6l-6 6 6 6" />
+1 -1
View File
@@ -331,7 +331,7 @@ export function ProductCard({
) : null}
<Link
href={`/honig/${product.slug}`}
className="group/more mt-4 inline-flex items-center gap-2 self-start text-sm tracking-wide-caps text-forest"
className="group/more mt-3 inline-flex items-center gap-2 self-start py-1 text-sm tracking-wide-caps text-forest"
>
<span className="link-draw pb-0.5">
{product.category === "HONIG" ? t.product.toHoney : t.product.toProduct}