Files
Wabenhain/src/app/konto/bestellungen/[id]/retoure/page.tsx
T
Nick Szaunig c7927f2883 feat: Wabenhain Honig-Shop Anwendung
Vollstaendige Next.js/Prisma-E-Commerce-Anwendung fuer eine Imkerei:
Shop, Warenkorb, Stripe-Checkout, Kundenkonto mit 2FA, Admin-Bereich
(Produkte, Ernten, Chargen, Bestellungen, Gutscheine, admin-editierbare
Website-Inhalte), i18n (DE/EN), Rate-Limiting/CSP/Audit-Log-Haertung,
PostgreSQL- und MySQL-Unterstuetzung ueber austauschbare Prisma-
Treiber-Adapter, Unit-/Komponenten-/E2E-Tests.
2026-08-17 14:30:28 +02:00

84 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { redirect, notFound } from "next/navigation";
import { Container, SectionHeading, Button } from "@/components/ui";
import { BackLink } from "@/components/back-link";
import { getCurrentCustomer } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { requestReturnAction } from "../../actions";
import { getLocale } from "@/i18n/locale";
import { getDictionary } from "@/i18n/get-dictionary";
export const dynamic = "force-dynamic";
const RETURN_ELIGIBLE_STATUSES = [
"BEZAHLT",
"IN_VORBEREITUNG",
"VERSANDBEREIT",
"VERSENDET",
"ABHOLBEREIT",
"ABGEHOLT",
];
export default async function RetourePage(props: PageProps<"/konto/bestellungen/[id]/retoure">) {
const t = getDictionary(await getLocale());
const { id } = await props.params;
const { error } = await props.searchParams;
const customer = await getCurrentCustomer();
if (!customer) redirect("/konto");
const order = await prisma.order.findUnique({
where: { id },
select: {
id: true,
orderNumber: true,
customerId: true,
status: true,
items: { select: { id: true, productName: true, quantity: true } },
returnRequest: { select: { id: true } },
},
});
if (!order || order.customerId !== customer.id) notFound();
if (!RETURN_ELIGIBLE_STATUSES.includes(order.status) || order.returnRequest) {
redirect("/konto/bestellungen");
}
return (
<div className="py-20">
<Container className="max-w-lg">
<BackLink href="/konto/bestellungen" label={t.retourePage.backLabel} />
<SectionHeading eyebrow={t.retourePage.orderEyebrow(order.orderNumber)} title={t.retourePage.title} />
<ul className="mt-8 text-sm text-ink/70 space-y-1">
{order.items.map((item) => (
<li key={item.id}>
{item.quantity} × {item.productName}
</li>
))}
</ul>
{error ? (
<p className="mt-6 text-sm text-red-700 bg-red-50 border border-red-200 px-4 py-3">{error}</p>
) : null}
<form action={requestReturnAction} className="mt-6 space-y-4">
<input type="hidden" name="orderId" value={order.id} />
<div>
<label htmlFor="reason" className="text-sm text-ink/70">
{t.retourePage.reasonLabel}
</label>
<textarea
id="reason"
name="reason"
required
minLength={3}
rows={5}
placeholder={t.retourePage.reasonPlaceholder}
className="mt-2 w-full border border-ink/20 bg-background px-4 py-3 text-sm focus:outline-none focus:border-forest"
/>
</div>
<Button type="submit">{t.retourePage.submit}</Button>
</form>
</Container>
</div>
);
}