UI / frontend /components /ImageUpload.tsx
Chan-Y's picture
Initial commit for HF Space
a94ab76
import React, { useRef, useState } from 'react';
import { Upload, X, Image as ImageIcon } from 'lucide-react';
interface ImageUploadProps {
onImageSelect: (image: string | null) => void;
currentImage: string | null;
disabled?: boolean;
}
export const ImageUpload: React.FC<ImageUploadProps> = ({
onImageSelect,
currentImage,
disabled = false
}) => {
const fileInputRef = useRef<HTMLInputElement>(null);
const [preview, setPreview] = useState<string | null>(currentImage);
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
const result = reader.result as string;
setPreview(result);
onImageSelect(result);
};
reader.readAsDataURL(file);
}
};
const handleRemove = () => {
setPreview(null);
onImageSelect(null);
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
};
const handleClick = () => {
if (!disabled) {
fileInputRef.current?.click();
}
};
return (
<div>
<label className="flex items-center gap-2 text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
<ImageIcon size={16} />
Resim Yükle
{disabled && <span className="text-gray-400 dark:text-gray-600 text-xs font-normal">(Sadece Gemma 3 12B)</span>}
</label>
<input
ref={fileInputRef}
type="file"
accept="image/*"
onChange={handleFileChange}
className="hidden"
disabled={disabled}
/>
{preview ? (
<div className="relative inline-block group">
<img
src={preview}
alt="Preview"
className="max-w-full h-40 object-contain rounded-lg border-2 border-gray-200 dark:border-gray-700"
/>
<button
onClick={handleRemove}
className="absolute top-2 right-2 p-1.5 bg-red-500 hover:bg-red-600 text-white rounded-lg transition-all shadow-lg opacity-0 group-hover:opacity-100"
>
<X size={16} />
</button>
</div>
) : (
<button
onClick={handleClick}
disabled={disabled}
className={`w-full border-2 border-dashed rounded-lg p-6 text-center transition-all ${
disabled
? 'border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-900 cursor-not-allowed'
: 'border-gray-300 dark:border-gray-700 hover:border-primary-400 dark:hover:border-primary-600 hover:bg-primary-50 dark:hover:bg-primary-900/10 cursor-pointer'
}`}
>
<Upload
className={`mx-auto mb-2 ${disabled ? 'text-gray-300 dark:text-gray-700' : 'text-gray-400 dark:text-gray-500'}`}
size={28}
/>
<p className={`text-sm ${disabled ? 'text-gray-400 dark:text-gray-600' : 'text-gray-600 dark:text-gray-400'}`}>
{disabled ? 'Resim yüklemek için görsel destekli model seçin' : 'Resim yüklemek için tıklayın'}
</p>
{!disabled && (
<p className="text-xs text-gray-500 dark:text-gray-500 mt-1">PNG, JPG, GIF</p>
)}
</button>
)}
</div>
);
};