Initial commit: Craft2Prints with Stages 1-3

This commit is contained in:
Andymick
2026-07-15 18:09:59 +01:00
commit 41937ffc15
158 changed files with 16054 additions and 0 deletions
+17
View File
@@ -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>
);
}
+74
View File
@@ -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&apos;t find the order details on this page, but
you&apos;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>
);
}