import classNames from 'classnames' import IVSpinner from '~/components/IVSpinner' import { useState } from 'react' import CheckIcon from '~/icons/compiled/Check' import UploadsFolderIcon from '~/icons/compiled/UploadsFolder' import { preventDefaultInputEnterKey } from '~/utils/preventDefaultInputEnter' export type UploadStep = 'default' | 'uploading' | 'success' | 'error' interface FileUploadButtonProps { id: string dropZoneClassName?: string onChange: (event: React.ChangeEvent) => void currentStep: UploadStep showUploadStatus: boolean accept?: string value?: File[] disabled?: boolean clickToSelectLabel?: React.ReactNode description?: React.ReactNode onReset?: () => void multiple?: boolean } function truncateFile(file: File, index: number) { const parts = file.name.split('.') const extension = parts.pop() const name = parts.join('.') return (
{name}. {extension}
) } function selectedTitle(files: File[]) { if (files.length === 1) { return 'File selected' } return `${files.length} files selected` } export default function FileUploadButton({ id, dropZoneClassName, currentStep, onChange, showUploadStatus, accept = '*', value, disabled, clickToSelectLabel, description, onReset, multiple = false, }: FileUploadButtonProps) { const [isDragging, setIsDragging] = useState(false) let title: React.ReactNode = value && value.length > 0 ? selectedTitle(value) : clickToSelectLabel ?? ( <> Select a file {' '} or drag and drop ) switch (currentStep) { case 'uploading': if (showUploadStatus) { title = 'Uploading...' description = "Please don't close this window or navigate away from this page." } break case 'error': if (!description) { description = 'Sorry, there was a problem uploading your file. Please try again.' } break case 'success': if (showUploadStatus) { title = 'Upload complete' } break } let icon = if (currentStep === 'success' && showUploadStatus) { icon = } else if (currentStep === 'uploading' && showUploadStatus) { icon = } return (
{/* approximates height of icon + title + description so UI doesn't change height */}
{icon}

{title}

{description ?? value?.map(truncateFile) ?? ''}
{(currentStep === 'default' || currentStep === 'error') && ( setIsDragging(true)} onDragEnter={() => setIsDragging(true)} onDragLeave={() => setIsDragging(false)} onDragEnd={() => setIsDragging(false)} onDrop={() => setIsDragging(false)} onKeyDown={preventDefaultInputEnterKey} /> )}
{currentStep !== 'default' && onReset && (
) }