Fix: Route photo requests to design canvas instead of approval upload
When admin clicks 'Start a design for this' on a photo request, now routes
to the design canvas at /made-to-order/{productSlug} with the custom photo
passed as a query parameter. The DesignCanvas component now accepts and
displays the custom photo as the background for designing.
Changes:
- Updated photo request link to go to design canvas page
- Added customPhoto query parameter to pass custom image URL
- Updated DesignCanvas to accept and use customPhoto prop
- Modified renderPhoto() to display custom photo when provided
- Updated getPhotoInfo() to use custom photo for compositing
This commit is contained in:
@@ -79,7 +79,9 @@
|
|||||||
"Bash(git commit -m 'Feature: Add order tracking and shipping status updates *)",
|
"Bash(git commit -m 'Feature: Add order tracking and shipping status updates *)",
|
||||||
"Bash(git commit -m 'Feature: Royal Mail tracking integration \\(hybrid approach\\) *)",
|
"Bash(git commit -m 'Feature: Royal Mail tracking integration \\(hybrid approach\\) *)",
|
||||||
"Bash(git commit -m 'Fix: Refresh page after updating order tracking details *)",
|
"Bash(git commit -m 'Fix: Refresh page after updating order tracking details *)",
|
||||||
"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: Route photo requests to design canvas instead of approval upload *)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,8 @@ 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 newProofParams = new URLSearchParams({
|
const designParams = new URLSearchParams({
|
||||||
productId: request.productId,
|
customPhoto: request.imageDataUrl,
|
||||||
customerName: request.customerName,
|
|
||||||
customerEmail: request.customerEmail,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -63,7 +61,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={`/admin/proofs/new?${newProofParams.toString()}`}
|
href={`/made-to-order/${request.product.slug}?${designParams.toString()}`}
|
||||||
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
|
||||||
|
|||||||
@@ -7,7 +7,13 @@ import ProductCard from '@/components/ProductCard';
|
|||||||
|
|
||||||
const DesignCanvas = dynamic(() => import('@/components/DesignCanvas'), { ssr: false });
|
const DesignCanvas = dynamic(() => import('@/components/DesignCanvas'), { ssr: false });
|
||||||
|
|
||||||
export default async function ProductDetailPage({ params }: { params: { slug: string } }) {
|
export default async function ProductDetailPage({
|
||||||
|
params,
|
||||||
|
searchParams,
|
||||||
|
}: {
|
||||||
|
params: { slug: string };
|
||||||
|
searchParams: { customPhoto?: string };
|
||||||
|
}) {
|
||||||
const activePromotions = await fetchActivePromotions();
|
const activePromotions = await fetchActivePromotions();
|
||||||
|
|
||||||
const row = await prisma.product.findUnique({ where: { slug: params.slug } });
|
const row = await prisma.product.findUnique({ where: { slug: params.slug } });
|
||||||
@@ -23,7 +29,7 @@ export default async function ProductDetailPage({ params }: { params: { slug: st
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto max-w-6xl px-6 py-12">
|
<div className="mx-auto max-w-6xl px-6 py-12">
|
||||||
<DesignCanvas product={product} />
|
<DesignCanvas product={product} customPhoto={searchParams.customPhoto} />
|
||||||
|
|
||||||
{related.length > 0 && (
|
{related.length > 0 && (
|
||||||
<section className="mt-20 border-t border-line pt-12">
|
<section className="mt-20 border-t border-line pt-12">
|
||||||
|
|||||||
@@ -494,6 +494,7 @@ export default function DesignCanvas({
|
|||||||
initialColor,
|
initialColor,
|
||||||
initialSize,
|
initialSize,
|
||||||
designId,
|
designId,
|
||||||
|
customPhoto,
|
||||||
}: {
|
}: {
|
||||||
product: ProductDTO;
|
product: ProductDTO;
|
||||||
isAdminEditing?: boolean;
|
isAdminEditing?: boolean;
|
||||||
@@ -501,6 +502,7 @@ export default function DesignCanvas({
|
|||||||
initialColor?: string;
|
initialColor?: string;
|
||||||
initialSize?: string | null;
|
initialSize?: string | null;
|
||||||
designId?: string;
|
designId?: string;
|
||||||
|
customPhoto?: string;
|
||||||
}) {
|
}) {
|
||||||
const [color, setColor] = useState(initialColor ?? product.colors[0]);
|
const [color, setColor] = useState(initialColor ?? product.colors[0]);
|
||||||
const [size, setSize] = useState<string | null>(initialSize ?? (product.sizes[0] ?? null));
|
const [size, setSize] = useState<string | null>(initialSize ?? (product.sizes[0] ?? null));
|
||||||
@@ -1112,6 +1114,11 @@ export default function DesignCanvas({
|
|||||||
};
|
};
|
||||||
|
|
||||||
function renderPhoto(v: 'front' | 'back') {
|
function renderPhoto(v: 'front' | 'back') {
|
||||||
|
// If a custom photo was provided (e.g., from a photo request), use it
|
||||||
|
if (customPhoto && v === 'front') {
|
||||||
|
return <img src={customPhoto} alt="Custom photo" className="h-full w-full object-cover" />;
|
||||||
|
}
|
||||||
|
|
||||||
const colorPhoto = v === 'front' ? product.colorPhotos[color] : product.colorPhotosBack[color];
|
const colorPhoto = v === 'front' ? product.colorPhotos[color] : product.colorPhotosBack[color];
|
||||||
if (colorPhoto) {
|
if (colorPhoto) {
|
||||||
return <img src={colorPhoto} alt={`${product.name} in ${color}`} className="h-full w-full object-cover" />;
|
return <img src={colorPhoto} alt={`${product.name} in ${color}`} className="h-full w-full object-cover" />;
|
||||||
@@ -1140,6 +1147,9 @@ export default function DesignCanvas({
|
|||||||
// Same resolution logic as renderPhoto, but returns raw data instead of JSX —
|
// Same resolution logic as renderPhoto, but returns raw data instead of JSX —
|
||||||
// used when compositing the placement-reference image for the order record.
|
// used when compositing the placement-reference image for the order record.
|
||||||
function getPhotoInfo(v: 'front' | 'back'): { url: string; tint: boolean } | null {
|
function getPhotoInfo(v: 'front' | 'back'): { url: string; tint: boolean } | null {
|
||||||
|
// If a custom photo was provided (e.g., from a photo request), use it
|
||||||
|
if (customPhoto && v === 'front') return { url: customPhoto, tint: false };
|
||||||
|
|
||||||
const colorPhoto = v === 'front' ? product.colorPhotos[color] : product.colorPhotosBack[color];
|
const colorPhoto = v === 'front' ? product.colorPhotos[color] : product.colorPhotosBack[color];
|
||||||
if (colorPhoto) return { url: colorPhoto, tint: false };
|
if (colorPhoto) return { url: colorPhoto, tint: false };
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user