Initial commit: Craft2Prints with Stages 1-3
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function CheckoutCancelPage() {
|
||||
return (
|
||||
<div className="mx-auto max-w-lg px-6 py-20 text-center">
|
||||
<p className="tag-label text-splash-orange">Checkout cancelled</p>
|
||||
<h1 className="mt-2 font-display text-4xl">No charge was made</h1>
|
||||
<p className="mt-4 text-muted">Your bag is still here, exactly as you left it.</p>
|
||||
<Link
|
||||
href="/cart"
|
||||
className="mt-8 inline-block bg-clay px-6 py-3 text-sm font-medium text-paper hover:bg-clay-dark"
|
||||
>
|
||||
Back to your bag
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import Link from 'next/link';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import ClearCartOnMount from '@/components/ClearCartOnMount';
|
||||
import Price from '@/components/Price';
|
||||
|
||||
export default async function CheckoutSuccessPage({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: { session_id?: string };
|
||||
}) {
|
||||
const sessionId = searchParams.session_id;
|
||||
const order = sessionId
|
||||
? await prisma.order.findUnique({
|
||||
where: { stripeSessionId: sessionId },
|
||||
include: { items: true },
|
||||
})
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-2xl px-6 py-20 text-center">
|
||||
<ClearCartOnMount />
|
||||
<p className="tag-label text-splash-pink">Order confirmed</p>
|
||||
<h1 className="mt-2 font-display text-4xl">Thank you!</h1>
|
||||
|
||||
{!order ? (
|
||||
<p className="mt-4 text-muted">
|
||||
Your payment went through. We couldn't find the order details on this page, but
|
||||
you'll get a confirmation from Stripe by email.
|
||||
</p>
|
||||
) : (
|
||||
<>
|
||||
<p className="mt-4 text-muted">
|
||||
{order.status === 'PAID'
|
||||
? "We've got your order and we'll get started on it."
|
||||
: "We're just confirming your payment — this updates automatically, no need to refresh."}
|
||||
</p>
|
||||
|
||||
<div className="mt-10 divide-y divide-line border-t border-line text-left">
|
||||
{order.items.map((item) => (
|
||||
<div key={item.id} className="flex items-center gap-4 py-4">
|
||||
<img
|
||||
src={item.placementPreviewUrl || item.designPreviewUrl || undefined}
|
||||
alt={item.productName}
|
||||
className="h-16 w-16 border border-line bg-surface object-contain"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<p className="font-medium">{item.productName}</p>
|
||||
<p className="text-sm text-muted">
|
||||
{item.color}
|
||||
{item.size ? `, ${item.size}` : ''} · qty {item.quantity}
|
||||
</p>
|
||||
</div>
|
||||
<Price cents={item.unitPrice * item.quantity} className="font-mono text-sm" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-6 flex justify-end">
|
||||
<div className="flex items-baseline gap-3">
|
||||
<span className="tag-label">Total</span>
|
||||
<span className="font-mono text-xl">
|
||||
<Price cents={order.total} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Link href="/" className="mt-10 inline-block tag-label hover:text-ink">
|
||||
← Back to home
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user