import clsx from "clsx" import { ReactNode, useState } from "react" import { useHref } from "react-router-dom" import { useTranslation } from "react-i18next" import Tooltip from "../../atoms/tooltip" import Button from "../../fundamentals/button" import CheckCircleIcon from "../../fundamentals/icons/check-circle-icon" import CrossIcon from "../../fundamentals/icons/cross-icon" import DownloadIcon from "../../fundamentals/icons/download-icon" import FileIcon from "../../fundamentals/icons/file-icon" import TrashIcon from "../../fundamentals/icons/trash-icon" import WarningCircleIcon from "../../fundamentals/icons/warning-circle" import Modal from "../../molecules/modal" type FileSummaryProps = { name: string size: number hasError?: boolean errorMessage?: string action: ReactNode progress?: number status?: string } /** * Render an upload file summary (& upload progress). */ function FileSummary(props: FileSummaryProps) { const { action, name, progress, size, status, hasError, errorMessage } = props const formattedSize = size / 1024 < 10 ? `${(size / 1024).toFixed(2)} KiB` : `${(size / (1024 * 1024)).toFixed(2)} MiB` return (
{errorMessage} ) : null } >
{name}
{status || formattedSize}
{action}
) } type UploadSummaryProps = { creations?: number updates?: number type: string } /** * Render a batch update request summary. */ function UploadSummary(props: UploadSummaryProps) { const { creations, updates, type } = props const { t } = useTranslation() return (
{creations || 0} {" "} {t("upload-modal-new", "new")} {type}
{updates || 0} {" "} {t("upload-modal-updates", "updates")}
) } type DropAreaProps = { onUpload: (d: DataTransferItem) => void } /** * Component handles an CSV file drop. */ function DropArea(props: DropAreaProps) { const { t } = useTranslation() const [isDragOver, setIsDragOver] = useState(false) const handleFileDrop = (e) => { e.preventDefault() e.stopPropagation() setIsDragOver(false) if (e.dataTransfer.items?.length) { props.onUpload(e.dataTransfer.items[0].getAsFile()) } } const handleFileSelect = (e) => { props.onUpload(e.target.files[0]) } const onDragOver = (event) => { event.stopPropagation() event.preventDefault() } return (
setIsDragOver(true)} onDragLeave={() => setIsDragOver(false)} onDragOver={onDragOver} onDrop={handleFileDrop} className={clsx( "mt-3 flex flex-col items-center justify-center rounded-xl border border-dashed p-6", { "opacity-50": isDragOver } )} > {t("upload-modal-drop-your-file-here-or", "Drop your file here, or")} {t( "upload-modal-only-csv-files-are-supported", "Only .csv files are supported." )}
) } type UploadModalProps = { type: string status?: string hasError?: boolean errorMessage?: string fileTitle: string description1Text: string description2Title: string description2Text: string onDownloadTemplate: () => any canImport?: boolean progress?: number onClose: () => void onSubmit: () => void onFileRemove: () => void processUpload: (...args: any[]) => Promise summary?: { toCreate?: number; toUpdate?: number } } /** * Upload prices modal. */ function UploadModal(props: UploadModalProps) { const { description1Text, description2Text, description2Title, fileTitle, canImport, processUpload, onClose, onSubmit, onFileRemove, onDownloadTemplate, summary, hasError, errorMessage, status, type, } = props const [uploadFile, setUploadFile] = useState() const { t } = useTranslation() const { name, size } = uploadFile || {} const onUpload = async (file) => { setUploadFile(file) await processUpload(file) } const removeFile = () => { setUploadFile(undefined) onFileRemove() } return (
Import {fileTitle}
{t("upload-modal-import-file-title", "Import {{fileTitle}}", { fileTitle, })}

{description1Text}

{summary && ( )} {!uploadFile ? ( ) : ( } /> )}
{description2Title}

{description2Text}

} />
) } export default UploadModal