"use client"; import { useRef } from "react"; import type { Artifact } from "@/lib/types"; export interface PendingFile { /** Client-side temp id for keying */ tempId: string; name: string; size: number; status: "uploading" | "done" | "error"; artifact?: Artifact; error?: string; } interface FileUploadButtonProps { taskId: string | null; onFileStart: (file: PendingFile) => void; onFileComplete: (tempId: string, artifact: Artifact) => void; onFileError: (tempId: string, error: string) => void; disabled?: boolean; } const ACCEPTED = ".fasta,.pdb,.csv,.nwk"; let tempCounter = 0; function formatSize(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 { formatSize }; export default function FileUploadButton({ taskId, onFileStart, onFileComplete, onFileError, disabled, }: FileUploadButtonProps) { const inputRef = useRef(null); const handleClick = () => { if (disabled || !taskId) return; inputRef.current?.click(); }; const handleChange = async (e: React.ChangeEvent) => { const files = e.target.files; if (!files || !taskId) return; for (const file of Array.from(files)) { const tempId = `upload_${++tempCounter}_${Date.now()}`; const pending: PendingFile = { tempId, name: file.name, size: file.size, status: "uploading", }; onFileStart(pending); try { const formData = new FormData(); formData.append("file", file); formData.append("taskId", taskId); const res = await fetch("/api/upload", { method: "POST", body: formData, }); if (!res.ok) { const body = await res.json().catch(() => ({ error: `HTTP ${res.status}` })); throw new Error(body.error || `Upload failed (${res.status})`); } const { artifact } = (await res.json()) as { artifact: Artifact }; onFileComplete(tempId, artifact); } catch (err) { const msg = err instanceof Error ? err.message : "Upload failed"; onFileError(tempId, msg); } } // Reset the input so the same file can be re-uploaded if (inputRef.current) inputRef.current.value = ""; }; return ( <> ); }