Improve component stability and user experience with safety checks

Implement robust error handling, safety checks for data structures, and state management improvements across various components to prevent runtime errors and enhance user experience.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: a71e826a-1d38-4b6e-a34f-fbf5ba1f1b25
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
This commit is contained in:
pac7
2025-10-08 19:27:31 +00:00
parent f21602b992
commit bfba3baf7e
12 changed files with 224 additions and 110 deletions

View File

@@ -23,13 +23,16 @@ export async function uploadPendingImages(images: UploadedImage[]): Promise<Uplo
// Process all images in parallel for better performance using allSettled
const uploadPromises = images.map(async (image, index): Promise<UploadedImageWithFlag> => {
if (image.isLocal && image.file) {
const fileName = image.file.name;
// 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) {
throw new Error(`Failed to get upload URL for image ${index + 1}: ${urlError?.message || 'Unknown error'}`);
console.error(`imageUploadHelper.uploadPendingImages: Failed to get upload URL for "${fileName}":`, urlError);
throw new Error(`Failed to get upload URL for "${fileName}": ${urlError?.message || 'Unknown error'}`);
}
// Step 2: Upload file directly to Cloudflare
@@ -43,13 +46,15 @@ export async function uploadPendingImages(images: UploadedImage[]): Promise<Uplo
if (!uploadResponse.ok) {
const errorText = await uploadResponse.text();
throw new Error(`Upload failed for image ${index + 1} (status ${uploadResponse.status}): ${errorText}`);
console.error(`imageUploadHelper.uploadPendingImages: Upload failed for "${fileName}" (status ${uploadResponse.status}):`, errorText);
throw new Error(`Upload failed for "${fileName}" (status ${uploadResponse.status}): ${errorText}`);
}
const result: CloudflareUploadResponse = await uploadResponse.json();
if (!result.success || !result.result) {
throw new Error(`Cloudflare upload returned unsuccessful response for image ${index + 1}`);
console.error(`imageUploadHelper.uploadPendingImages: Cloudflare upload unsuccessful for "${fileName}"`);
throw new Error(`Cloudflare upload returned unsuccessful response for "${fileName}"`);
}
// Clean up object URL
@@ -99,7 +104,7 @@ export async function uploadPendingImages(images: UploadedImage[]): Promise<Uplo
// If any uploads failed, clean up ONLY newly uploaded images and throw error
if (errors.length > 0) {
if (newlyUploadedImageIds.length > 0) {
console.error(`Some uploads failed. Cleaning up ${newlyUploadedImageIds.length} newly uploaded images...`);
console.error(`imageUploadHelper.uploadPendingImages: Some uploads failed. Cleaning up ${newlyUploadedImageIds.length} newly uploaded images...`);
// Attempt cleanup in parallel but don't throw if it fails
await Promise.allSettled(
@@ -107,7 +112,7 @@ export async function uploadPendingImages(images: UploadedImage[]): Promise<Uplo
supabase.functions.invoke('upload-image', {
body: { action: 'delete', imageId }
}).catch(cleanupError => {
console.error(`Failed to cleanup image ${imageId}:`, cleanupError);
console.error(`imageUploadHelper.uploadPendingImages: Failed to cleanup image ${imageId}:`, cleanupError);
})
)
);