diff --git a/webapp/src/components/common/buttons/DownloadButton.tsx b/webapp/src/components/common/buttons/DownloadButton.tsx new file mode 100644 index 0000000000..3dbcd68cff --- /dev/null +++ b/webapp/src/components/common/buttons/DownloadButton.tsx @@ -0,0 +1,92 @@ +import FileUploadIcon from "@mui/icons-material/FileUpload"; +import SplitButton, { SplitButtonProps } from "./SplitButton"; +import { useState } from "react"; +import useEnqueueErrorSnackbar from "../../../hooks/useEnqueueErrorSnackbar"; +import { useTranslation } from "react-i18next"; +import type { PromiseAny } from "../../../utils/tsUtils"; +import { LoadingButton } from "@mui/lab"; + +export type DownloadButtonProps = { + children?: React.ReactNode; + disabled?: boolean; +} & ( + | { + formatOptions: SplitButtonProps["options"]; + onClick?: (format: OptionValue) => PromiseAny | unknown; + } + | { + formatOptions?: undefined; + onClick?: (format?: undefined) => PromiseAny | unknown; + } +); + +function DownloadButton( + props: DownloadButtonProps, +) { + const { t } = useTranslation(); + const { + disabled, + formatOptions, + onClick, + children: label = t("global.export"), + } = props; + const [isDownloading, setIsDownloading] = useState(false); + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + + const btnProps = { + variant: "contained", + size: "small", + disabled, + } as const; + + const loadingBtnProps = { + startIcon: , + loadingPosition: "start", + loading: isDownloading, + } as const; + + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + const handleDownload = async (format?: OptionValue) => { + setIsDownloading(true); + + try { + if (formatOptions) { + await onClick?.(format!); + } else { + await onClick?.(); + } + } catch (err) { + enqueueErrorSnackbar(t("global.download.error"), String(err)); + } + + setIsDownloading(false); + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return formatOptions ? ( + handleDownload(format)} + ButtonProps={loadingBtnProps} + > + {label} + + ) : ( + handleDownload()} + > + {label} + + ); +} + +export default DownloadButton;