feat: Enhance image uploader with context menu and deferred upload

This commit is contained in:
gpt-engineer-app[bot]
2025-10-01 19:21:50 +00:00
parent 83260e7f73
commit c582e6fc1b
9 changed files with 364 additions and 193 deletions

View File

@@ -0,0 +1,78 @@
import { supabase } from '@/integrations/supabase/client';
import type { UploadedImage } from '@/components/upload/EntityMultiImageUploader';
export interface CloudflareUploadResponse {
result: {
id: string;
variants: string[];
};
success: boolean;
}
/**
* Uploads pending local images to Cloudflare via Supabase Edge Function
* @param images Array of UploadedImage objects (mix of local and already uploaded)
* @returns Array of UploadedImage objects with all images uploaded
*/
export async function uploadPendingImages(images: UploadedImage[]): Promise<UploadedImage[]> {
const uploadedImages: UploadedImage[] = [];
for (const image of images) {
if (image.isLocal && image.file) {
try {
// Step 1: Get upload URL from our Supabase Edge Function
const { data: uploadUrlData, error: urlError } = await supabase.functions.invoke('upload-image', {
body: { action: 'get-upload-url' }
});
if (urlError || !uploadUrlData?.uploadURL) {
console.error('Error getting upload URL:', urlError);
throw new Error('Failed to get upload URL from Cloudflare');
}
// Step 2: Upload file directly to Cloudflare
const formData = new FormData();
formData.append('file', image.file);
const uploadResponse = await fetch(uploadUrlData.uploadURL, {
method: 'POST',
body: formData,
});
if (!uploadResponse.ok) {
throw new Error(`Upload failed with status: ${uploadResponse.status}`);
}
const result: CloudflareUploadResponse = await uploadResponse.json();
if (!result.success || !result.result) {
throw new Error('Cloudflare upload returned unsuccessful response');
}
// Step 3: Return uploaded image metadata
uploadedImages.push({
url: result.result.variants[0], // Use first variant (usually the original)
cloudflare_id: result.result.id,
caption: image.caption,
isLocal: false,
});
// Clean up object URL
URL.revokeObjectURL(image.url);
} catch (error) {
console.error('Error uploading image:', error);
throw new Error(`Failed to upload image: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
} else {
// Already uploaded, keep as is
uploadedImages.push({
url: image.url,
cloudflare_id: image.cloudflare_id,
caption: image.caption,
isLocal: false,
});
}
}
return uploadedImages;
}