import { FileImage, Upload, X } from 'lucide-react'; import { useEffect, useRef, useState } from 'react'; import { Attachment, AttachmentAction, AttachmentActions, AttachmentContent, AttachmentDescription, AttachmentMedia, AttachmentTitle, AttachmentTrigger, } from '@/components/ui/attachment'; import { uploadFile, UploadError } from '@/lib/upload'; type FileUploadProps = { value: string | null; onChange: (key: string | null) => void; folder?: string; accept?: string; onUploadingChange?: (uploading: boolean) => void; existingUrl?: string | null; onFileMeta?: (meta: { size: number; type: string } | null) => void; }; function formatFileSize(bytes: number): string { if (bytes < 1024) { return `${bytes} B`; } if (bytes < 1024 * 1024) { return `${(bytes / 1024).toFixed(1)} KB`; } return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } export function FileUpload({ value, onChange, folder, accept = 'image/jpeg,image/png,image/webp,image/gif', onUploadingChange, existingUrl, onFileMeta }: FileUploadProps) { const inputRef = useRef(null); const [uploading, setUploading] = useState(false); const [error, setError] = useState(null); const [fileName, setFileName] = useState(null); const [fileSize, setFileSize] = useState(null); const [preview, setPreview] = useState(null); useEffect(() => { onUploadingChange?.(uploading); }, [uploading, onUploadingChange]); async function handleFileChange(e: React.ChangeEvent) { const file = e.target.files?.[0]; if (!file) { return; } setError(null); setUploading(true); setFileName(file.name); setFileSize(file.size); const objectUrl = URL.createObjectURL(file); setPreview(objectUrl); try { const key = await uploadFile(file, folder); onChange(key); onFileMeta?.({ size: file.size, type: file.type }); } catch (err) { const message = err instanceof UploadError ? err.message : 'Gagal mengunggah file.'; setError(message); setPreview(null); setFileName(null); setFileSize(null); onFileMeta?.(null); } finally { setUploading(false); if (inputRef.current) { inputRef.current.value = ''; } } } function handleRemove(e: React.MouseEvent) { e.stopPropagation(); onChange(null); setFileName(null); setFileSize(null); setPreview(null); setError(null); onFileMeta?.(null); if (inputRef.current) { inputRef.current.value = ''; } } const state = uploading ? 'uploading' : error ? 'error' : value ? 'done' : 'idle'; return ( <> inputRef.current?.click()} aria-label={value ? 'Ganti file' : 'Pilih file untuk diunggah'} /> {preview ? ( {fileName ) : existingUrl && value ? ( Bukti ) : uploading ? ( ) : ( )} {value ? ( <> {fileName} {fileSize ? formatFileSize(fileSize) : 'Terupload'} ) : uploading ? ( <> Mengunggah... Memproses file ) : error ? ( <> Gagal {error} ) : ( <> Unggah File Opsional · JPG, PNG, WebP, GIF · Maks 10MB )} {value && ( )} ); }