Skip to content

Commit

Permalink
feat(ui-commons): create DownloadFileButton
Browse files Browse the repository at this point in the history
  • Loading branch information
skamril committed Sep 13, 2024
1 parent 7ded876 commit 9d6ea71
Showing 1 changed file with 92 additions and 0 deletions.
92 changes: 92 additions & 0 deletions webapp/src/components/common/buttons/DownloadButton.tsx
Original file line number Diff line number Diff line change
@@ -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<OptionValue extends string> = {
children?: React.ReactNode;
disabled?: boolean;
} & (
| {
formatOptions: SplitButtonProps<OptionValue>["options"];
onClick?: (format: OptionValue) => PromiseAny | unknown;
}
| {
formatOptions?: undefined;
onClick?: (format?: undefined) => PromiseAny | unknown;
}
);

function DownloadButton<OptionValue extends string>(
props: DownloadButtonProps<OptionValue>,
) {
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: <FileUploadIcon />,
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 ? (
<SplitButton
{...btnProps}
options={formatOptions}
onClick={(format) => handleDownload(format)}
ButtonProps={loadingBtnProps}
>
{label}
</SplitButton>
) : (
<LoadingButton
{...btnProps}
{...loadingBtnProps}
onClick={() => handleDownload()}
>
{label}
</LoadingButton>
);
}

export default DownloadButton;

0 comments on commit 9d6ea71

Please sign in to comment.