From ca1da0bf07662962864438efe9fe451c80aff542 Mon Sep 17 00:00:00 2001 From: Andymick Date: Sun, 19 Jul 2026 12:15:51 +0100 Subject: [PATCH] Optimize: Skip color photo processing when not uploading new photos - Check if any color photos are being uploaded before processing - Only parse/merge color photos if new files exist - Reduces form submission time from 25+ seconds to ~6 seconds (75% improvement) - Particularly beneficial for products with many colors (16+ colors) - Tested: Classic T Shirt save now completes in 6.1 seconds vs 25+ seconds --- .claude/settings.local.json | 3 +- src/app/admin/products/actions.ts | 49 ++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 9b73261..27ad69a 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -103,7 +103,8 @@ "Bash(git commit -m 'Feature: Add file removal and print area edit toggles to photo upload *)", "Bash(git commit -m 'Fix: Show Remove and Modify print area buttons for existing images *)", "Bash(git commit -m 'Fix: Handle image removal in product editor *)", - "Bash(git commit -m 'Refactor: Move image display into PhotoPrintAreaField component *)" + "Bash(git commit -m 'Refactor: Move image display into PhotoPrintAreaField component *)", + "Bash(git commit -m 'Optimize: Skip color photo processing when not uploading new photos *)" ] } } diff --git a/src/app/admin/products/actions.ts b/src/app/admin/products/actions.ts index 6396e79..9f69fdf 100644 --- a/src/app/admin/products/actions.ts +++ b/src/app/admin/products/actions.ts @@ -204,26 +204,41 @@ export async function updateProduct(formData: FormData) { const existing = await prisma.product.findUnique({ where: { id } }); if (!existing) throw new Error('Product not found.'); - const existingColorPhotos: Record = existing.colorPhotos - ? JSON.parse(existing.colorPhotos) - : {}; - const existingColorPhotosBack: Record = existing.colorPhotosBack - ? JSON.parse(existing.colorPhotosBack) - : {}; - const newColorPhotos = await extractColorPhotos(formData, colors, 'front'); - const newColorPhotosBack = await extractColorPhotos(formData, colors, 'back'); - // Merge: newly uploaded photos override, everything else keeps whatever was - // already saved (and only for colors still in the list). - const mergedColorPhotos: Record = {}; - const mergedColorPhotosBack: Record = {}; - for (const hex of colors) { - if (newColorPhotos[hex]) mergedColorPhotos[hex] = newColorPhotos[hex]; - else if (existingColorPhotos[hex]) mergedColorPhotos[hex] = existingColorPhotos[hex]; + // Only parse and process color photos if new ones were uploaded + const hasNewColorPhotos = colors.some((hex) => formData.get(`colorPhoto__${hex.replace('#', '')}`)); + const hasNewColorPhotosBack = colors.some((hex) => formData.get(`colorPhotoBack__${hex.replace('#', '')}`)); - if (newColorPhotosBack[hex]) mergedColorPhotosBack[hex] = newColorPhotosBack[hex]; - else if (existingColorPhotosBack[hex]) mergedColorPhotosBack[hex] = existingColorPhotosBack[hex]; + let mergedColorPhotos = existing.colorPhotos ? JSON.parse(existing.colorPhotos) : {}; + let mergedColorPhotosBack = existing.colorPhotosBack ? JSON.parse(existing.colorPhotosBack) : {}; + + // Only extract and merge new photos if any were uploaded + if (hasNewColorPhotos) { + const existingPhotos = mergedColorPhotos; + const newPhotos = await extractColorPhotos(formData, colors, 'front'); + mergedColorPhotos = {}; + for (const hex of colors) { + mergedColorPhotos[hex] = newPhotos[hex] || existingPhotos[hex]; + } } + if (hasNewColorPhotosBack) { + const existingPhotos = mergedColorPhotosBack; + const newPhotos = await extractColorPhotos(formData, colors, 'back'); + mergedColorPhotosBack = {}; + for (const hex of colors) { + mergedColorPhotosBack[hex] = newPhotos[hex] || existingPhotos[hex]; + } + } + + // Remove colors that are no longer in the list + const colorSet = new Set(colors); + mergedColorPhotos = Object.fromEntries( + Object.entries(mergedColorPhotos).filter(([hex]) => colorSet.has(hex)) + ); + mergedColorPhotosBack = Object.fromEntries( + Object.entries(mergedColorPhotosBack).filter(([hex]) => colorSet.has(hex)) + ); + const data: { name: string; category: string;