// app/components/MediaUploader.tsx (Client)
import { useState, useCallback, useEffect } from "react";
import { useDropzone } from "react-dropzone";
export default function MediaUploader() {
const [image, setImage] = useState<{
file: File;
preview: string;
} | null>(null);
const [isUploading, setIsUploading] = useState(false);
useEffect(() => {
return () => {
if (image?.preview) {
URL.revokeObjectURL(image.preview);
}
};
}, [image]);
const onDrop = useCallback((acceptedFiles: File[]) => {
const file = acceptedFiles[0];
if (file) {
setImage({
file,
preview: URL.createObjectURL(file),
});
}
}, []);
const { getRootProps, getInputProps } = useDropzone({
onDrop,
accept: {
"image/*": [".jpeg", ".jpg", ".png", ".gif"],
},
maxFiles: 1,
});
const handleUpload = async () => {
if (!image?.file) return;
setIsUploading(true);
try {
// Send to your API route
const formData = new FormData();
formData.append("file", image.file);
const response = await fetch("/api/upload", {
method: "POST",
body: formData,
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error);
}
// Clear the form after successful upload
setImage(null);
} catch (error) {
console.error("Upload failed:", error);
} finally {
setIsUploading(false);
}
};
return (
<div className="space-y-4">
<div
{...getRootProps()}
className="border-2 border-dashed rounded-lg p-8"
>
<input {...getInputProps()} />
{image?.preview ? (
<img
src={image.preview}
alt="Preview"
className="max-w-full h-auto"
/>
) : (
<p>Drag & drop an image here, or click to select</p>
)}
</div>
{image && (
<button
onClick={handleUpload}
disabled={isUploading}
className="px-4 py-2 bg-blue-500 text-white rounded"
>
{isUploading ? "Uploading..." : "Upload"}
</button>
)}
</div>
);
}