PlatDetect / frontend /src /components /UploadPanel.jsx
haisyam's picture
Update kodingan PlatDetect
1f6c75f
Raw History Blame Contribute Delete
2.91 kB
import { useRef } from "react";
import { Upload, X, ImagePlus } from "lucide-react";
import { isValidImageFile, isFileSizeValid, formatFileSize } from "../utils/formatters";
export default function UploadPanel({ onFileSelect, selectedFile, previewUrl, onReset }) {
const fileInputRef = useRef(null);
function handleFileChange(e) {
const file = e.target.files?.[0];
if (!file) return;
if (!isValidImageFile(file)) {
alert("File harus berupa gambar JPG, PNG, JPEG, atau WEBP.");
return;
}
if (!isFileSizeValid(file)) {
alert("Ukuran gambar maksimal 10MB.");
return;
}
onFileSelect(file);
}
function handleDrop(e) {
e.preventDefault();
const file = e.dataTransfer.files?.[0];
if (!file) return;
if (!isValidImageFile(file)) {
alert("File harus berupa gambar JPG, PNG, JPEG, atau WEBP.");
return;
}
if (!isFileSizeValid(file)) {
alert("Ukuran gambar maksimal 10MB.");
return;
}
onFileSelect(file);
}
function handleDragOver(e) {
e.preventDefault();
}
return (
<div className="space-y-4">
{!previewUrl ? (
<div
onClick={() => fileInputRef.current?.click()}
onDrop={handleDrop}
onDragOver={handleDragOver}
className="border-2 border-dashed border-slate-300 rounded-xl p-8 md:p-12 text-center cursor-pointer hover:border-blue-400 hover:bg-blue-50/50 transition-all duration-200 group"
>
<ImagePlus className="w-10 h-10 text-slate-400 mx-auto mb-3 group-hover:text-blue-500 transition-colors" />
<p className="text-sm font-medium text-slate-600 mb-1">
Klik atau seret gambar ke sini
</p>
<p className="text-xs text-slate-400">
JPG, JPEG, PNG, WEBP • Maks 10MB
</p>
</div>
) : (
<div className="relative">
<img
src={previewUrl}
alt="Preview"
className="w-full rounded-xl border border-slate-200 object-contain max-h-72"
/>
<button
onClick={onReset}
className="absolute top-2 right-2 bg-red-500 hover:bg-red-600 text-white rounded-full p-1.5 shadow-md transition-colors cursor-pointer"
>
<X className="w-4 h-4" />
</button>
{selectedFile && (
<div className="mt-2 flex items-center gap-2 text-xs text-slate-500">
<Upload className="w-3.5 h-3.5" />
<span className="truncate">{selectedFile.name}</span>
<span className="text-slate-400">({formatFileSize(selectedFile.size)})</span>
</div>
)}
</div>
)}
<input
ref={fileInputRef}
type="file"
accept=".jpg,.jpeg,.png,.webp"
onChange={handleFileChange}
className="hidden"
/>
</div>
);
}