Files
homarr/packages/modals/src/confirm-modal.tsx
homarr-renovate[bot] a87c937b69 fix(deps): update dependency eslint-plugin-react-hooks to v5 (#1280)
* fix(deps): update dependency eslint-plugin-react-hooks to v5

* fix: lint issues after reenabling hook rules

* fix: format issues

---------

Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2024-10-16 21:43:51 +02:00

95 lines
2.9 KiB
TypeScript

import { useCallback, useState } from "react";
import type { ComponentPropsWithoutRef, ReactNode } from "react";
import type { ButtonProps, GroupProps } from "@mantine/core";
import { Box, Button, Group } from "@mantine/core";
import type { stringOrTranslation, TranslationFunction } from "@homarr/translation";
import { translateIfNecessary } from "@homarr/translation";
import { useI18n } from "@homarr/translation/client";
import { createModal } from "./creator";
type MaybePromise<T> = T | Promise<T>;
export interface ConfirmModalProps {
title: string;
children: ReactNode;
onConfirm?: () => MaybePromise<void>;
onCancel?: () => MaybePromise<void>;
closeOnConfirm?: boolean;
closeOnCancel?: boolean;
cancelProps?: ButtonProps & ComponentPropsWithoutRef<"button">;
confirmProps?: ButtonProps & ComponentPropsWithoutRef<"button">;
groupProps?: GroupProps;
labels?: {
confirm?: stringOrTranslation;
cancel?: stringOrTranslation;
};
}
export const ConfirmModal = createModal<Omit<ConfirmModalProps, "title">>(({ actions, innerProps }) => {
const [loading, setLoading] = useState(false);
const t = useI18n();
const { children, onConfirm, onCancel, cancelProps, confirmProps, groupProps, labels } = innerProps;
const closeOnConfirm = innerProps.closeOnConfirm ?? true;
const closeOnCancel = innerProps.closeOnCancel ?? true;
const cancelLabel = labels?.cancel ?? ((t: TranslationFunction) => t("common.action.cancel"));
const confirmLabel = labels?.confirm ?? ((t: TranslationFunction) => t("common.action.confirm"));
const handleCancel = useCallback(
async (event: React.MouseEvent<HTMLButtonElement>) => {
if (typeof cancelProps?.onClick === "function") {
cancelProps.onClick(event);
}
if (typeof onCancel === "function") {
await onCancel();
}
if (closeOnCancel) {
actions.closeModal();
}
},
[cancelProps, onCancel, closeOnCancel, actions],
);
const handleConfirm = useCallback(
async (event: React.MouseEvent<HTMLButtonElement>) => {
setLoading(true);
if (typeof confirmProps?.onClick === "function") {
confirmProps.onClick(event);
}
if (typeof onConfirm === "function") {
await onConfirm();
}
if (closeOnConfirm) {
actions.closeModal();
}
setLoading(false);
},
[confirmProps, onConfirm, closeOnConfirm, actions],
);
return (
<>
{children && <Box mb="md">{children}</Box>}
<Group justify="flex-end" {...groupProps}>
<Button variant="default" {...cancelProps} onClick={handleCancel}>
{cancelProps?.children ?? translateIfNecessary(t, cancelLabel)}
</Button>
<Button data-autofocus {...confirmProps} onClick={handleConfirm} color="red.9" loading={loading}>
{confirmProps?.children ?? translateIfNecessary(t, confirmLabel)}
</Button>
</Group>
</>
);
}).withOptions({});