'use client'; import { useState, useRef } from 'react'; import { Dialog, DialogTitle, DialogContent, DialogActions, Button, Box, Typography, TextField, Paper, Grid, Card, CardMedia, CardContent, CardActions, Alert, LinearProgress, Tabs, Tab } from '@mui/material'; import { CloudUpload as UploadIcon, Image as ImageIcon, InsertPhoto as InsertIcon } from '@mui/icons-material'; interface MediaFile { id: string; filename: string; originalName: string; url: string; alt: string | null; size: number; createdAt: string; } interface ImageUploadProps { open: boolean; onClose: () => void; onImageSelect: (imageUrl: string) => void; } export function ImageUpload({ open, onClose, onImageSelect }: ImageUploadProps) { const [tab, setTab] = useState(0); const [uploading, setUploading] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); const [error, setError] = useState(null); const [mediaFiles, setMediaFiles] = useState([]); const [loadingMedia, setLoadingMedia] = useState(false); const [urlInput, setUrlInput] = useState(''); const fileInputRef = useRef(null); const fetchMediaFiles = async () => { setLoadingMedia(true); try { const response = await fetch('/api/admin/media?type=image', { credentials: 'include' }); if (!response.ok) { throw new Error('Failed to fetch media files'); } const data = await response.json(); setMediaFiles(data.data || []); } catch (error) { console.error('Error fetching media files:', error); setError('Failed to load media files'); } finally { setLoadingMedia(false); } }; const handleFileUpload = async (files: FileList | null) => { if (!files || files.length === 0) return; const file = files[0]; // Validate file type if (!file.type.startsWith('image/')) { setError('Please select an image file'); return; } // Validate file size (5MB limit) if (file.size > 5 * 1024 * 1024) { setError('File size must be less than 5MB'); return; } setUploading(true); setError(null); setUploadProgress(0); try { const formData = new FormData(); formData.append('file', file); const response = await fetch('/api/admin/media', { method: 'POST', credentials: 'include', body: formData }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || 'Upload failed'); } const result = await response.json(); // Add the new file to the media files list setMediaFiles(prev => [result.data, ...prev]); // Auto-select the uploaded image onImageSelect(result.data.url); setUploadProgress(100); // Reset form if (fileInputRef.current) { fileInputRef.current.value = ''; } } catch (error) { console.error('Error uploading file:', error); setError(error instanceof Error ? error.message : 'Upload failed'); } finally { setUploading(false); setTimeout(() => setUploadProgress(0), 1000); } }; const handleTabChange = (event: React.SyntheticEvent, newValue: number) => { setTab(newValue); if (newValue === 1 && mediaFiles.length === 0) { fetchMediaFiles(); } }; const formatFileSize = (bytes: number) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; const handleUrlSubmit = () => { if (urlInput.trim()) { onImageSelect(urlInput.trim()); setUrlInput(''); } }; return ( Insert Image {error && ( setError(null)} sx={{ mb: 2 }}> {error} )} {/* Upload Tab */} {tab === 0 && ( fileInputRef.current?.click()} > Click to upload or drag and drop PNG, JPG, GIF up to 5MB handleFileUpload(e.target.files)} accept="image/*" style={{ display: 'none' }} /> {uploading && ( Uploading... )} )} {/* Media Library Tab */} {tab === 1 && ( {loadingMedia ? ( Loading media files... ) : ( {mediaFiles.length === 0 ? ( No images found. Upload some images first. ) : ( mediaFiles.map((file) => ( {file.originalName} {formatFileSize(file.size)} )) )} )} )} {/* URL Tab */} {tab === 2 && ( setUrlInput(e.target.value)} placeholder="https://example.com/image.jpg" sx={{ mb: 2 }} /> {urlInput && ( Preview: Preview { e.currentTarget.style.display = 'none'; }} /> )} )} ); }