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:
1 parent
b7a75dddca
commit
11eccec01b
16 files changed
+221
-155
No files matched your search
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in new issue
Block a user