Files
boka-gasol247/src/app/[locale]/booking/[number]/page.tsx
2026-05-22 10:50:48 +02:00

130 lines
4.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 { setRequestLocale, getTranslations } from 'next-intl/server';
import { notFound } from 'next/navigation';
import { prisma } from '@/lib/prisma';
import { Header } from '@/components/Header';
import { formatOre } from '@/lib/money';
import { Link } from '@/i18n/routing';
export default async function BookingConfirmedPage({
params,
}: {
params: Promise<{ locale: string; number: string }>;
}) {
const { locale, number } = await params;
setRequestLocale(locale);
const t = await getTranslations();
const booking = await prisma.booking.findUnique({
where: { bookingNumber: number },
include: { items: true, pickupSlot: true },
});
if (!booking) notFound();
const loc = locale as 'sv' | 'en';
return (
<div className="min-h-screen bg-ink-50">
<Header />
<main className="mx-auto max-w-3xl px-4 py-8 sm:py-12">
<div className="card overflow-hidden">
<div className="bg-brand-600 px-6 py-5 text-white">
<div className="flex items-center gap-2 text-sm">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="h-5 w-5"
aria-hidden="true"
>
<path
fillRule="evenodd"
d="M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zm4.7-12.3a1 1 0 0 0-1.4-1.4L11 12.6 8.7 10.3a1 1 0 1 0-1.4 1.4l3 3a1 1 0 0 0 1.4 0l5-5z"
clipRule="evenodd"
/>
</svg>
<span>{t('booking.success.title')}</span>
</div>
<div className="mt-3 text-2xl font-semibold">
{t('booking.success.bookingNumber', { number: booking.bookingNumber })}
</div>
<div className="mt-1 text-sm text-white/80">
{t('booking.success.subtitle', { email: booking.email })}
</div>
</div>
<div className="space-y-6 p-6">
<div>
<h2 className="text-xs font-medium uppercase tracking-wide text-ink-500">
{t('email.orderSummary')}
</h2>
<table className="mt-2 w-full text-sm">
<tbody className="divide-y divide-ink-100">
{booking.items.map((it) => (
<tr key={it.id}>
<td className="py-2">
{loc === 'sv' ? it.nameSv : it.nameEn}
<span className="ml-2 text-ink-400">×{it.quantity}</span>
</td>
<td className="py-2 text-right tabular-nums">
{formatOre(it.lineTotalOre, loc)}
</td>
</tr>
))}
</tbody>
<tfoot>
<tr className="border-t border-ink-200">
<td className="pt-2 text-ink-600">
{t('common.subtotal')}
</td>
<td className="pt-2 text-right tabular-nums">
{formatOre(booking.subtotalOre, loc)}
</td>
</tr>
<tr>
<td className="text-ink-500">{t('common.ofWhichVat')}</td>
<td className="text-right tabular-nums text-ink-500">
{formatOre(booking.vatOre, loc)}
</td>
</tr>
<tr>
<td className="pt-1 font-semibold">{t('common.total')}</td>
<td className="pt-1 text-right font-semibold tabular-nums">
{formatOre(booking.totalOre, loc)}
</td>
</tr>
</tfoot>
</table>
</div>
{booking.pickupSlot && (
<div>
<h2 className="text-xs font-medium uppercase tracking-wide text-ink-500">
{t('email.pickup')}
</h2>
<p className="mt-1 text-sm">
{loc === 'sv'
? booking.pickupSlot.labelSv
: booking.pickupSlot.labelEn}{' '}
·{' '}
{booking.pickupSlot.startsAt.toLocaleString(
loc === 'sv' ? 'sv-SE' : 'en-SE',
{ dateStyle: 'medium', timeStyle: 'short' },
)}
</p>
</div>
)}
<div className="rounded-lg bg-ink-50 p-4 text-sm text-ink-600">
{t('email.invoiceInfo')}
</div>
<Link href="/" className="btn-secondary w-full justify-center">
{t('booking.success.newOrder')}
</Link>
</div>
</div>
</main>
</div>
);
}