Feature: Add product selection when starting design from photo request
Added intermediate page (/admin/custom-requests/[id]/start-design) that lets the admin choose which product to design the photo on. Shows the photo request details and all available products with the originally requested product pre-selected.
This commit is contained in:
@@ -82,7 +82,8 @@
|
|||||||
"Bash(git commit -m 'Fix: Remove function prop from client component *)",
|
"Bash(git commit -m 'Fix: Remove function prop from client component *)",
|
||||||
"Bash(git commit -m 'Fix: Import revalidatePath from correct module *)",
|
"Bash(git commit -m 'Fix: Import revalidatePath from correct module *)",
|
||||||
"Bash(git commit -m 'Fix: Route photo requests to design canvas instead of approval upload *)",
|
"Bash(git commit -m 'Fix: Route photo requests to design canvas instead of approval upload *)",
|
||||||
"Bash(git commit -m 'Fix: Pass photo request ID instead of data URL *)"
|
"Bash(git commit -m 'Fix: Pass photo request ID instead of data URL *)",
|
||||||
|
"Bash(git commit -m 'Feature: Add product selection when starting design from photo request *)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,6 @@ export default async function CustomRequestDetailPage({ params }: { params: { id
|
|||||||
const whatsappDigits = request.customerPhone ? request.customerPhone.replace(/\D/g, '') : null;
|
const whatsappDigits = request.customerPhone ? request.customerPhone.replace(/\D/g, '') : null;
|
||||||
const whatsappMessage = `Hi ${request.customerName}, thanks for sending over your photo for a ${request.product.name} — we're working on it!`;
|
const whatsappMessage = `Hi ${request.customerName}, thanks for sending over your photo for a ${request.product.name} — we're working on it!`;
|
||||||
|
|
||||||
const designParams = new URLSearchParams({
|
|
||||||
customRequestId: request.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto max-w-2xl px-6 py-12">
|
<div className="mx-auto max-w-2xl px-6 py-12">
|
||||||
<AdminNav />
|
<AdminNav />
|
||||||
@@ -61,7 +57,7 @@ export default async function CustomRequestDetailPage({ params }: { params: { id
|
|||||||
<DownloadPhotoButton photoUrl={request.imageDataUrl} customerName={request.customerName} />
|
<DownloadPhotoButton photoUrl={request.imageDataUrl} customerName={request.customerName} />
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`/made-to-order/${request.product.slug}?${designParams.toString()}`}
|
href={`/admin/custom-requests/${request.id}/start-design`}
|
||||||
className="bg-clay px-6 py-3 text-sm font-medium text-paper hover:bg-clay-dark"
|
className="bg-clay px-6 py-3 text-sm font-medium text-paper hover:bg-clay-dark"
|
||||||
>
|
>
|
||||||
Start a design for this
|
Start a design for this
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { notFound, redirect } from 'next/navigation';
|
||||||
|
import { prisma } from '@/lib/prisma';
|
||||||
|
import AdminNav from '@/components/AdminNav';
|
||||||
|
|
||||||
|
export default async function StartDesignPage({ params }: { params: { id: string } }) {
|
||||||
|
const request = await prisma.customRequest.findUnique({
|
||||||
|
where: { id: params.id },
|
||||||
|
include: { product: true },
|
||||||
|
});
|
||||||
|
if (!request) notFound();
|
||||||
|
|
||||||
|
const products = await prisma.product.findMany({
|
||||||
|
where: { showOnPersonalised: true },
|
||||||
|
orderBy: { name: 'asc' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSubmit = async (formData: FormData) => {
|
||||||
|
'use server';
|
||||||
|
const productId = String(formData.get('productId') ?? '');
|
||||||
|
const product = await prisma.product.findUnique({ where: { id: productId } });
|
||||||
|
if (product) {
|
||||||
|
redirect(`/made-to-order/${product.slug}?customRequestId=${request.id}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mx-auto max-w-2xl px-6 py-12">
|
||||||
|
<AdminNav />
|
||||||
|
<h1 className="font-display text-3xl">Start design for this photo</h1>
|
||||||
|
<p className="mt-2 text-sm text-muted">Select which product to design this photo on</p>
|
||||||
|
|
||||||
|
<div className="mt-6 border border-line bg-surface p-6">
|
||||||
|
<img src={request.imageDataUrl} alt="Customer's photo" className="mx-auto max-h-64 object-contain" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6 border border-line bg-surface p-6">
|
||||||
|
<p className="tag-label mb-2">Photo request details</p>
|
||||||
|
<p className="text-sm mb-2"><span className="font-medium">Customer:</span> {request.customerName}</p>
|
||||||
|
<p className="text-sm"><span className="font-medium">Originally requested for:</span> {request.product.name}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action={handleSubmit} className="mt-6 space-y-4 border border-line bg-surface p-6">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="productId" className="tag-label mb-2 block">
|
||||||
|
Which product to design on?
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="productId"
|
||||||
|
name="productId"
|
||||||
|
required
|
||||||
|
defaultValue={request.productId}
|
||||||
|
className="w-full border border-line bg-paper px-3 py-2 text-sm"
|
||||||
|
>
|
||||||
|
<option value="">Select a product...</option>
|
||||||
|
{products.map((p) => (
|
||||||
|
<option key={p.id} value={p.id}>
|
||||||
|
{p.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-3 pt-4">
|
||||||
|
<button type="submit" className="bg-clay px-6 py-3 text-sm font-medium text-paper hover:bg-clay-dark">
|
||||||
|
Go to design canvas
|
||||||
|
</button>
|
||||||
|
<a
|
||||||
|
href={`/admin/custom-requests/${request.id}`}
|
||||||
|
className="border border-line px-6 py-3 text-sm hover:border-clay hover:text-clay"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user