Files
Wabenhain/src/app/admin/patenschaften/angebote/[id]/page.tsx
T
Nick.RosenloecherandClaude Opus 5.5 1d88bac52e
Docker Image bauen und veroeffentlichen / typecheck (push) Successful in 2m18s
Docker Image bauen und veroeffentlichen / test (push) Successful in 5m32s
Docker Image bauen und veroeffentlichen / lint (push) Successful in 3m41s
Docker Image bauen und veroeffentlichen / build-and-push (push) Canceled after 20m38s
feat: Patenschafts-Honig automatisch waehlen (nie cremig, neueste Ernte)
Pakete, Abo-Reservierung und Abo-Lieferungen nehmen immer den aktiven,
nicht cremigen Honig der neuesten Ernte mit genug freiem Bestand, bei
gleichem Jahrgang den mit dem meisten Bestand. Feste Honig-Zuordnung
im Admin entfaellt (Spalte bleibt, wird nicht mehr genutzt).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-16 18:35:04 +02:00

81 lines
3.5 KiB
TypeScript

import Link from "next/link";
import { notFound } from "next/navigation";
import { BackLink } from "@/components/back-link";
import { AdminBadge } from "@/components/admin-list";
import { asStringArray } from "@/lib/json-array";
import { getLocale } from "@/i18n/locale";
import { getSponsorshipAdminStrings } from "@/i18n/sponsorship/admin";
import { updateSponsorshipOfferAction } from "@/app/admin/actions";
import { OfferForm } from "../../_components/offer-form";
import { getOfferOverview } from "../../_lib/offer-overview";
export default async function AdminSponsorshipOfferEditPage(props: PageProps<"/admin/patenschaften/angebote/[id]">) {
const t = getSponsorshipAdminStrings(await getLocale());
const tf = t.offerForm;
const { id } = await props.params;
const {
rows: [row],
} = await getOfferOverview(id);
if (!row) notFound();
const { offer, isAvailable, currentHoney, activeSubscriptions } = row;
return (
<div className="max-w-3xl">
<BackLink href="/admin/patenschaften/angebote" label={tf.backToOffers} />
<h1 className="mb-6 text-2xl text-heading">{tf.editTitle(offer.name)}</h1>
{/* Live-Verfuegbarkeit: dieselbe Entscheidung wie auf der Verkaufsseite. */}
<section className="mb-8 border border-ink/10 bg-background p-6">
<h2 className="mb-3 text-xs tracking-wide-caps text-ink/65">{tf.availabilityHeading}</h2>
<div className="flex flex-wrap items-center gap-3">
<AdminBadge tone={isAvailable ? "positive" : "pending"}>{isAvailable ? t.offers.available : t.offers.unavailable}</AdminBadge>
<span className="text-sm text-ink/75">{isAvailable ? tf.availableNow : tf.unavailableNow}</span>
</div>
{currentHoney ? (
<p className="mt-3 text-sm tabular-nums text-ink/75">
{tf.stockLine(currentHoney.label, currentHoney.stock, currentHoney.reserved, currentHoney.free)}
</p>
) : offer.honeyJars > 0 ? (
<p className="mt-3 text-sm text-ink/75">{tf.noEligibleHoney}</p>
) : null}
{offer.kind === "ABO" ? (
<p className="mt-1 text-sm tabular-nums text-ink/75">{tf.activeSubscriptions(activeSubscriptions, offer.maxActiveSubscriptions)}</p>
) : null}
{offer.kind === "ABO" && offer.cycle === "ERNTE" ? (
<Link href={`/admin/patenschaften/angebote/${offer.id}/erntefenster`} className="link-draw mt-3 inline-block text-sm text-heading">
{t.offers.harvestWindows} →
</Link>
) : null}
</section>
<OfferForm
isNew={false}
currentHoneyLabel={currentHoney?.label ?? null}
action={updateSponsorshipOfferAction}
t={t}
defaults={{
id: offer.id,
kind: offer.kind,
name: offer.name,
nameEn: offer.nameEn ?? "",
slug: offer.slug,
description: offer.description,
descriptionEn: offer.descriptionEn ?? "",
features: asStringArray(offer.features),
featuresEn: asStringArray(offer.featuresEn),
priceCents: offer.priceCents,
honeyShareCentsPerJar: offer.honeyShareCentsPerJar,
honeyShareCentsPerMonth: offer.honeyShareCentsPerMonth,
isActive: offer.isActive,
isPhysical: offer.isPhysical,
sortOrder: offer.sortOrder,
honeyJars: offer.honeyJars,
cycle: offer.cycle,
maxActiveSubscriptions: offer.maxActiveSubscriptions,
medalTier: offer.medalTier,
}}
/>
</div>
);
}