From c95093a81f590cbf7a12dfb4baa40037aeb5c900 Mon Sep 17 00:00:00 2001 From: Mathieu Date: Wed, 24 Jun 2026 20:52:18 +0200 Subject: [PATCH] feat: add reprocess button to re-run AI background removal on image cards Co-Authored-By: Claude Sonnet 4.6 --- src/app/(dashboard)/images/page.tsx | 3 ++- src/components/images/ImageCard.tsx | 11 +++++++++++ src/hooks/useImages.ts | 13 ++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/app/(dashboard)/images/page.tsx b/src/app/(dashboard)/images/page.tsx index 4e4b8c6..5fdbee6 100644 --- a/src/app/(dashboard)/images/page.tsx +++ b/src/app/(dashboard)/images/page.tsx @@ -10,7 +10,7 @@ import { useImages } from '@/hooks/useImages' import type { ImageItem } from '@/types/images' function ImagesPageInner() { - const { items, addFiles, setFeather, setAlphaThreshold, rotate, uploadOne, uploadAll, removeItem, assignProduct } = useImages() + const { items, addFiles, setFeather, setAlphaThreshold, rotate, uploadOne, uploadAll, removeItem, assignProduct, reprocess } = useImages() const [lightboxItem, setLightboxItem] = useState(null) return ( @@ -44,6 +44,7 @@ function ImagesPageInner() { onRemove={removeItem} onOpenLightbox={setLightboxItem} onAssignProduct={assignProduct} + onReprocess={reprocess} /> ))} diff --git a/src/components/images/ImageCard.tsx b/src/components/images/ImageCard.tsx index 6073ef7..8595c48 100644 --- a/src/components/images/ImageCard.tsx +++ b/src/components/images/ImageCard.tsx @@ -11,6 +11,7 @@ interface ImageCardProps { onRemove: (id: string) => void onOpenLightbox: (item: ImageItem) => void onAssignProduct: (id: string, shopifyProductId: string, shopifyProductTitle: string) => void + onReprocess: (id: string) => void } const STATUS_LABELS: Record = { @@ -101,6 +102,7 @@ export function ImageCard({ onRemove, onOpenLightbox, onAssignProduct, + onReprocess, }: ImageCardProps) { const statusInfo = STATUS_LABELS[item.status] ?? { label: item.status, color: 'text-slate-400' } const isProcessing = ['pending', 'converting', 'processing', 'searching', 'uploading'].includes(item.status) @@ -201,6 +203,15 @@ export function ImageCard({ ⬆️ Uploader )} + {(item.status === 'ready' || item.status === 'uploaded' || item.status === 'skipped' || item.status === 'error' || item.status === 'not_found') && item.rawPngBlob && ( + + )} {item.status === 'uploaded' && item.uploadedUrl && ( { + const item = items.find((i) => i.id === id) + if (!item) return + queueRef.current.enqueue(() => + runPipeline(item.id, item.originalBlob, item.ref, item.feather, item.rotation, item.alphaThreshold) + ) + }, + [items, runPipeline], + ) + + return { items, addFiles, setFeather, setAlphaThreshold, rotate, uploadOne, uploadAll, removeItem, assignProduct, reprocess } }