140 lines
5.5 KiB
TypeScript
140 lines
5.5 KiB
TypeScript
import Link from 'next/link';
|
|
import { createDirectus, rest, staticToken, readItem, readItems } from '@directus/sdk';
|
|
import type { Order, OrderItem } from '@/lib/directus';
|
|
|
|
const directusUrl = process.env.DIRECTUS_INTERNAL_URL || process.env.NEXT_PUBLIC_DIRECTUS_URL || 'https://katheryn-cms.jeffemmett.com';
|
|
const storeToken = process.env.DIRECTUS_STORE_TOKEN || process.env.DIRECTUS_API_TOKEN || '';
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const client = createDirectus<any>(directusUrl)
|
|
.with(staticToken(storeToken))
|
|
.with(rest());
|
|
|
|
export default async function OrderConfirmationPage({
|
|
searchParams,
|
|
}: {
|
|
searchParams: Promise<{ id?: string }>;
|
|
}) {
|
|
const params = await searchParams;
|
|
const orderId = params.id;
|
|
|
|
if (!orderId) {
|
|
return (
|
|
<div className="min-h-screen flex flex-col items-center justify-center py-20 pt-32">
|
|
<h1 className="font-serif text-2xl">Order not found</h1>
|
|
<Link href="/store" className="mt-8 btn btn-primary">
|
|
Browse Store
|
|
</Link>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
let order: Order;
|
|
let orderItems: OrderItem[];
|
|
|
|
try {
|
|
order = await client.request(readItem('orders', orderId)) as Order;
|
|
orderItems = await client.request(
|
|
readItems('order_items', {
|
|
filter: { order_id: { _eq: parseInt(orderId) } },
|
|
fields: ['*'],
|
|
})
|
|
) as OrderItem[];
|
|
} catch {
|
|
return (
|
|
<div className="min-h-screen flex flex-col items-center justify-center py-20 pt-32">
|
|
<h1 className="font-serif text-2xl">Order not found</h1>
|
|
<p className="mt-4 text-gray-600">We couldn't find this order. Please check your email for confirmation.</p>
|
|
<Link href="/store" className="mt-8 btn btn-primary">
|
|
Browse Store
|
|
</Link>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const currencySymbol = order.currency === 'GBP' ? '\u00a3' : '$';
|
|
const customerName = [order.customer_first_name, order.customer_last_name].filter(Boolean).join(' ') || 'there';
|
|
|
|
return (
|
|
<div className="min-h-screen bg-white pt-24">
|
|
<div className="mx-auto max-w-2xl px-4 py-16 text-center">
|
|
<div className="mb-8">
|
|
<div className="mx-auto h-16 w-16 rounded-full bg-green-100 flex items-center justify-center mb-6">
|
|
<svg className="h-8 w-8 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
</svg>
|
|
</div>
|
|
<h1 className="font-serif text-3xl">Thank you, {customerName}!</h1>
|
|
<p className="mt-4 text-gray-600">
|
|
Your order has been confirmed and a receipt has been sent to {order.customer_email}.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="bg-gray-50 p-8 text-left mt-12">
|
|
<div className="flex justify-between items-start mb-6">
|
|
<div>
|
|
<p className="text-sm text-gray-500 uppercase tracking-wider">Order Number</p>
|
|
<p className="text-lg font-medium">#{order.id}</p>
|
|
</div>
|
|
<div className="text-right">
|
|
<p className="text-sm text-gray-500 uppercase tracking-wider">Total</p>
|
|
<p className="text-lg font-medium">{currencySymbol}{Number(order.total).toLocaleString()}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="border-t border-gray-200 pt-6">
|
|
<h2 className="text-sm font-medium uppercase tracking-wider text-gray-500 mb-4">Items</h2>
|
|
<ul className="space-y-3">
|
|
{orderItems.map((item) => (
|
|
<li key={item.id} className="flex justify-between text-sm">
|
|
<span>{item.artwork_name}</span>
|
|
<span className="font-medium">
|
|
{(item.currency === 'GBP' ? '\u00a3' : '$')}{Number(item.price).toLocaleString()}
|
|
</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
|
|
<div className="border-t border-gray-200 pt-6 mt-6 space-y-2">
|
|
<div className="flex justify-between text-sm">
|
|
<span>Subtotal</span>
|
|
<span>{currencySymbol}{Number(order.subtotal).toLocaleString()}</span>
|
|
</div>
|
|
{order.shipping_cost != null && Number(order.shipping_cost) > 0 && (
|
|
<div className="flex justify-between text-sm">
|
|
<span>Shipping</span>
|
|
<span>{currencySymbol}{Number(order.shipping_cost).toLocaleString()}</span>
|
|
</div>
|
|
)}
|
|
<div className="flex justify-between text-sm font-medium border-t border-gray-200 pt-2">
|
|
<span>Total</span>
|
|
<span>{currencySymbol}{Number(order.total).toLocaleString()}</span>
|
|
</div>
|
|
</div>
|
|
|
|
{(order.shipping_address || order.shipping_city) && (
|
|
<div className="border-t border-gray-200 pt-6 mt-6">
|
|
<h2 className="text-sm font-medium uppercase tracking-wider text-gray-500 mb-2">Shipping To</h2>
|
|
<p className="text-sm text-gray-700">
|
|
{[order.shipping_address, order.shipping_city, order.shipping_postcode, order.shipping_country]
|
|
.filter(Boolean)
|
|
.join(', ')}
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mt-8 space-y-4">
|
|
<p className="text-sm text-gray-500">
|
|
Katheryn will be in touch regarding delivery details.
|
|
</p>
|
|
<Link href="/store" className="inline-block btn btn-primary">
|
|
Continue Shopping
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|