import { getClient } from "@/api/AxiosClient"; import { useCredentialGetter } from "@/hooks/useCredentialGetter"; import { cn } from "@/util/utils"; import { Cross2Icon, FileIcon, ReloadIcon } from "@radix-ui/react-icons"; import { useMutation } from "@tanstack/react-query"; import { useId, useState } from "react"; import { Button } from "./ui/button"; import { Input } from "./ui/input"; import { Label } from "./ui/label"; import { toast } from "./ui/use-toast"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs"; export type FileInputValue = | { s3uri: string; presignedUrl: string; } | string | null; type Props = { value: FileInputValue; onChange: (value: FileInputValue) => void; }; const FILE_SIZE_LIMIT_IN_BYTES = 10 * 1024 * 1024; // 10 MB function showFileSizeError() { toast({ variant: "destructive", title: "File size limit exceeded", description: "The file you are trying to upload exceeds the 10MB limit, please try again with a different file", }); } function FileUpload({ value, onChange }: Props) { const credentialGetter = useCredentialGetter(); const [file, setFile] = useState(null); const inputId = useId(); const uploadFileMutation = useMutation({ mutationFn: async (file: File) => { const client = await getClient(credentialGetter); const formData = new FormData(); formData.append("file", file); return client.post< FormData, { data: { s3_uri: string; presigned_url: string; }; } >("/upload_file", formData, { headers: { "Content-Type": "multipart/form-data", }, }); }, onSuccess: (response) => { onChange({ s3uri: response.data.s3_uri, presignedUrl: response.data.presigned_url, }); }, onError: (error) => { setFile(null); toast({ variant: "destructive", title: "Failed to upload file", description: `An error occurred while uploading the file: ${error.message}`, }); }, }); const handleFileChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { const file = e.target.files[0] as File; if (file.size > FILE_SIZE_LIMIT_IN_BYTES) { showFileSizeError(); return; } setFile(file); uploadFileMutation.mutate(file); } }; function reset() { setFile(null); onChange(null); } const isManualUpload = typeof value === "object" && value !== null && file && "s3uri" in value; return ( { if (value === "upload") { onChange(null); } else { onChange(""); } }} > Upload File URL {isManualUpload && ( // redundant check for ts compiler
{file.name}
)} {value === null && ( )}
{typeof value === "string" && ( onChange(event.target.value)} /> )}
); } export { FileUpload };