Commit design approval workflow and related features
- Add design approval workflow components and API routes - Update checkout process for design approval integration - Add admin navigation for design management - Update mail utilities for design notifications - Update types for design approval system - Update Prisma schema for design approval database Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
14fa3acc7a
commit
313943aeaa
@@ -19,6 +19,8 @@ type CheckoutCartItem = {
|
||||
designPreviewUrlBack: string | null;
|
||||
placementPreviewUrl: string | null;
|
||||
placementPreviewUrlBack: string | null;
|
||||
designWidthCm: number | null;
|
||||
designHeightCm: number | null;
|
||||
};
|
||||
|
||||
type GuestInfo = {
|
||||
@@ -111,6 +113,8 @@ export async function POST(req: Request) {
|
||||
designPreviewUrlBack: i.designPreviewUrlBack,
|
||||
placementPreviewUrl: i.placementPreviewUrl,
|
||||
placementPreviewUrlBack: i.placementPreviewUrlBack,
|
||||
designWidthCm: i.designWidthCm,
|
||||
designHeightCm: i.designHeightCm,
|
||||
})),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -249,6 +249,15 @@ export async function GET(req: Request, { params }: { params: { id: string } })
|
||||
<p><strong>Order ID:</strong> ${order.id}</p>
|
||||
<p><strong>Product:</strong> ${item.productName}</p>
|
||||
<p><strong>Color:</strong> ${item.color} ${item.size ? `| Size: ${item.size}` : ''}</p>
|
||||
${item.designWidthCm && item.designHeightCm ? `<p><strong>Design Dimensions (Overall):</strong> ${item.designWidthCm} cm × ${item.designHeightCm} cm</p>` : ''}
|
||||
${item.designImageDimensions ? (() => {
|
||||
try {
|
||||
const imageDims = JSON.parse(item.designImageDimensions);
|
||||
return imageDims && imageDims.length > 0 ? `<p><strong>Image Dimensions:</strong><ul style="margin: 5px 0 0 20px;">${imageDims.map((img, idx) => `<li>Image ${idx + 1}: ${img.widthCm} cm × ${img.heightCm} cm</li>`).join('')}</ul></p>` : '';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
})() : ''}
|
||||
<p><strong>Order Date:</strong> ${new Date(order.createdAt).toLocaleDateString()}</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ export default function CheckoutPageClient({ isLoggedIn, customer }: CheckoutPag
|
||||
}
|
||||
|
||||
console.log('📡 Fetching /api/checkout with', items.length, 'items');
|
||||
console.log('📦 Cart items:', JSON.stringify(items, null, 2));
|
||||
const res = await fetch('/api/checkout', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
|
||||
@@ -27,6 +27,9 @@ export default function AdminNav() {
|
||||
<Link href="/admin/inbox" className="tag-label hover:text-ink">
|
||||
Inbox
|
||||
</Link>
|
||||
<Link href="/admin/designs" className="tag-label hover:text-ink">
|
||||
Design Approvals
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -173,3 +173,70 @@ export async function sendCustomerBroadcast({ to, name, subject, message, attach
|
||||
return { sent: false as const, reason: err instanceof Error ? err.message : 'Unknown error sending email' };
|
||||
}
|
||||
}
|
||||
|
||||
type SendDesignSubmissionNotificationArgs = {
|
||||
customerName: string | null;
|
||||
productName: string;
|
||||
adminLink: string;
|
||||
};
|
||||
|
||||
export async function sendDesignSubmissionNotification({
|
||||
customerName,
|
||||
productName,
|
||||
adminLink,
|
||||
}: SendDesignSubmissionNotificationArgs) {
|
||||
const to = process.env.ADMIN_NOTIFY_EMAIL ?? process.env.SMTP_USER;
|
||||
if (!process.env.SMTP_HOST || !to) {
|
||||
return { sent: false, reason: 'SMTP not configured — set SMTP_HOST etc. in .env' as const };
|
||||
}
|
||||
|
||||
const transporter = getTransporter();
|
||||
|
||||
try {
|
||||
await transporter.sendMail({
|
||||
from: process.env.MAIL_FROM ?? process.env.SMTP_USER,
|
||||
to,
|
||||
subject: `New design submitted for approval${customerName ? ` from ${customerName}` : ''}`,
|
||||
text: `A new ${productName} design has been submitted for your review and approval.\n\nReview it here:\n${adminLink}`,
|
||||
html: `<p>A new ${productName} design has been submitted for your review and approval.</p><p><a href="${adminLink}">${adminLink}</a></p>`,
|
||||
});
|
||||
return { sent: true as const };
|
||||
} catch (err) {
|
||||
return { sent: false as const, reason: err instanceof Error ? err.message : 'Unknown error sending email' };
|
||||
}
|
||||
}
|
||||
|
||||
type SendDesignApprovedEmailArgs = {
|
||||
to: string;
|
||||
customerName: string | null;
|
||||
productName: string;
|
||||
checkoutLink: string;
|
||||
};
|
||||
|
||||
export async function sendDesignApprovedEmail({
|
||||
to,
|
||||
customerName,
|
||||
productName,
|
||||
checkoutLink,
|
||||
}: SendDesignApprovedEmailArgs) {
|
||||
if (!process.env.SMTP_HOST) {
|
||||
return { sent: false, reason: 'SMTP not configured — set SMTP_HOST etc. in .env' as const };
|
||||
}
|
||||
|
||||
const transporter = getTransporter();
|
||||
|
||||
const greeting = customerName ? `Hi ${customerName},` : 'Hi,';
|
||||
|
||||
try {
|
||||
await transporter.sendMail({
|
||||
from: process.env.MAIL_FROM ?? process.env.SMTP_USER,
|
||||
to,
|
||||
subject: `Your ${productName} design has been approved!`,
|
||||
text: `${greeting}\n\nYour ${productName} design has been approved! You can now add it to your cart and proceed to checkout.\n\n${checkoutLink}\n\n— Craft2Prints`,
|
||||
html: `<p>${greeting}</p><p>Your ${productName} design has been approved! You can now add it to your cart and proceed to checkout.</p><p><a href="${checkoutLink}">${checkoutLink}</a></p><p>— Craft2Prints</p>`,
|
||||
});
|
||||
return { sent: true as const };
|
||||
} catch (err) {
|
||||
return { sent: false as const, reason: err instanceof Error ? err.message : 'Unknown error sending email' };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,8 @@ export type CartItem = {
|
||||
designPreviewUrlBack: string | null;
|
||||
placementPreviewUrl: string | null;
|
||||
placementPreviewUrlBack: string | null;
|
||||
designWidthCm: number | null;
|
||||
designHeightCm: number | null;
|
||||
};
|
||||
|
||||
export type ProofDTO = {
|
||||
|
||||
Reference in New Issue
Block a user