"use client"; import React, { useState, useCallback, useRef } from "react"; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/Card"; interface CreativeUploaderProps { onImageReady: (imageUrl: string, imageBytes?: File) => void; isLoading?: boolean; } export const CreativeUploader: React.FC = ({ onImageReady, isLoading = false, }) => { const [uploadMode, setUploadMode] = useState<"file" | "url">("file"); const [urlInput, setUrlInput] = useState(""); const [previewUrl, setPreviewUrl] = useState(null); const [selectedFile, setSelectedFile] = useState(null); const [isDragging, setIsDragging] = useState(false); const [error, setError] = useState(null); const fileInputRef = useRef(null); const handleFileSelect = useCallback((file: File) => { setError(null); // Validate file type const allowedTypes = ["image/png", "image/jpeg", "image/jpg", "image/webp"]; if (!allowedTypes.includes(file.type)) { setError("Invalid file type. Please upload PNG, JPG, or WebP images."); return; } // Validate file size (max 10MB) if (file.size > 10 * 1024 * 1024) { setError("File too large. Maximum size is 10MB."); return; } setSelectedFile(file); const objectUrl = URL.createObjectURL(file); setPreviewUrl(objectUrl); }, []); const handleDragOver = useCallback((e: React.DragEvent) => { e.preventDefault(); setIsDragging(true); }, []); const handleDragLeave = useCallback((e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); }, []); const handleDrop = useCallback((e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); const files = e.dataTransfer.files; if (files.length > 0) { handleFileSelect(files[0]); } }, [handleFileSelect]); const handleFileInputChange = useCallback((e: React.ChangeEvent) => { const files = e.target.files; if (files && files.length > 0) { handleFileSelect(files[0]); } }, [handleFileSelect]); const handleUrlSubmit = useCallback(() => { setError(null); if (!urlInput.trim()) { setError("Please enter an image URL."); return; } // Basic URL validation try { new URL(urlInput); } catch { setError("Invalid URL format."); return; } setPreviewUrl(urlInput); setSelectedFile(null); }, [urlInput]); const handleContinue = useCallback(() => { if (uploadMode === "file" && selectedFile) { // For file upload, we pass both the preview URL and the file onImageReady(previewUrl!, selectedFile); } else if (uploadMode === "url" && previewUrl) { onImageReady(previewUrl); } }, [uploadMode, selectedFile, previewUrl, onImageReady]); const handleClear = useCallback(() => { setPreviewUrl(null); setSelectedFile(null); setUrlInput(""); setError(null); if (fileInputRef.current) { fileInputRef.current.value = ""; } }, []); return ( Upload Your Creative Upload an existing ad creative to analyze and modify with new angles or concepts {/* Mode Toggle */}
{/* Error Display */} {error && (
{error}
)} {/* File Upload Area */} {uploadMode === "file" && !previewUrl && (
fileInputRef.current?.click()} className={`border-2 border-dashed rounded-xl p-8 text-center cursor-pointer transition-all ${ isDragging ? "border-blue-500 bg-blue-50" : "border-gray-300 hover:border-blue-400 hover:bg-gray-50" }`} >
Click to upload or drag and drop

PNG, JPG, or WebP (max 10MB)

)} {/* URL Input */} {uploadMode === "url" && !previewUrl && (
setUrlInput(e.target.value)} placeholder="https://example.com/image.png" className="flex-1 px-4 py-3 rounded-xl border-2 border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />

Enter a direct link to an image (PNG, JPG, or WebP)

)} {/* Image Preview */} {previewUrl && (
Creative preview { setError("Failed to load image. Please check the URL or try a different image."); setPreviewUrl(null); }} />
)}
); };