feat: vérification image existante sur Shopify avant upload (statut 'Déjà sur Shopify')
This commit is contained in:
@@ -20,6 +20,7 @@ const STATUS_LABELS: Record<string, { label: string; color: string }> = {
|
|||||||
ready: { label: '✓ Prêt', color: 'text-green-400' },
|
ready: { label: '✓ Prêt', color: 'text-green-400' },
|
||||||
uploading: { label: '⬆️ Upload…', color: 'text-blue-400' },
|
uploading: { label: '⬆️ Upload…', color: 'text-blue-400' },
|
||||||
uploaded: { label: '✅ Uploadé', color: 'text-green-500' },
|
uploaded: { label: '✅ Uploadé', color: 'text-green-500' },
|
||||||
|
skipped: { label: '⏭️ Déjà sur Shopify', color: 'text-slate-400' },
|
||||||
not_found: { label: '❌ Réf. introuvable', color: 'text-red-400' },
|
not_found: { label: '❌ Réf. introuvable', color: 'text-red-400' },
|
||||||
error: { label: '❌ Erreur', color: 'text-red-400' },
|
error: { label: '❌ Erreur', color: 'text-red-400' },
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ export function useImages() {
|
|||||||
})
|
})
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`)
|
if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`)
|
||||||
update(id, { status: 'uploaded', uploadedUrl: data.url })
|
update(id, { status: data.skipped ? 'skipped' : 'uploaded', uploadedUrl: data.url })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
update(id, { status: 'error', error: `Upload : ${(err as Error).message}` })
|
update(id, { status: 'error', error: `Upload : ${(err as Error).message}` })
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-1
@@ -85,13 +85,39 @@ export async function searchProductByRef(ref: string): Promise<ShopifyProductRes
|
|||||||
* @param imageBase64 — contenu JPEG encodé en base64 (sans le préfixe data:)
|
* @param imageBase64 — contenu JPEG encodé en base64 (sans le préfixe data:)
|
||||||
* @param filename — nom de fichier avec extension (ex: "REF-1042.jpg")
|
* @param filename — nom de fichier avec extension (ex: "REF-1042.jpg")
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* Vérifie si une image avec ce nom de fichier existe déjà sur le produit.
|
||||||
|
* Compare le nom de base (sans extension) avec les src des images existantes.
|
||||||
|
*/
|
||||||
|
export async function productImageExists(
|
||||||
|
shopifyProductId: string,
|
||||||
|
filename: string,
|
||||||
|
): Promise<string | null> {
|
||||||
|
const { baseUrl, headers } = getConfig()
|
||||||
|
const res = await fetch(`${baseUrl}/products/${shopifyProductId}/images.json?fields=id,src`, { headers })
|
||||||
|
if (!res.ok) return null
|
||||||
|
const data = await res.json()
|
||||||
|
const images = (data.images ?? []) as Array<{ id: number; src: string }>
|
||||||
|
// Compare le nom de base sans extension (ex: "30827" dans "30827.jpg")
|
||||||
|
const baseName = filename.replace(/\.[^.]+$/, '').toLowerCase()
|
||||||
|
const existing = images.find(img => {
|
||||||
|
const imgFile = img.src.split('/').pop()?.split('?')[0] ?? ''
|
||||||
|
return imgFile.replace(/\.[^.]+$/, '').toLowerCase() === baseName
|
||||||
|
})
|
||||||
|
return existing ? existing.src : null
|
||||||
|
}
|
||||||
|
|
||||||
export async function uploadProductImage(
|
export async function uploadProductImage(
|
||||||
shopifyProductId: string,
|
shopifyProductId: string,
|
||||||
imageBase64: string,
|
imageBase64: string,
|
||||||
filename: string,
|
filename: string,
|
||||||
): Promise<{ url: string }> {
|
): Promise<{ url: string; skipped?: boolean }> {
|
||||||
const { baseUrl, headers } = getConfig()
|
const { baseUrl, headers } = getConfig()
|
||||||
|
|
||||||
|
// Vérifie si l'image existe déjà
|
||||||
|
const existingUrl = await productImageExists(shopifyProductId, filename)
|
||||||
|
if (existingUrl) return { url: existingUrl, skipped: true }
|
||||||
|
|
||||||
const res = await fetch(`${baseUrl}/products/${shopifyProductId}/images.json`, {
|
const res = await fetch(`${baseUrl}/products/${shopifyProductId}/images.json`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers,
|
headers,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export type ImageStatus =
|
|||||||
| 'ready' // prêt à uploader
|
| 'ready' // prêt à uploader
|
||||||
| 'uploading' // upload Shopify en cours
|
| 'uploading' // upload Shopify en cours
|
||||||
| 'uploaded' // uploadé avec succès
|
| 'uploaded' // uploadé avec succès
|
||||||
|
| 'skipped' // image déjà présente sur le produit Shopify
|
||||||
| 'not_found' // référence produit introuvable dans Shopify
|
| 'not_found' // référence produit introuvable dans Shopify
|
||||||
| 'error' // erreur à n'importe quelle étape
|
| 'error' // erreur à n'importe quelle étape
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user