Files
Checkmate/client/src/Pages/Notifications/create/index.tsx
T

315 lines
10 KiB
TypeScript

import { BasePage, ConfigBox } from "@/Components/design-elements";
import { Button } from "@/Components/inputs";
import Stack from "@mui/material/Stack";
import { useTheme } from "@mui/material/styles";
import { useEffect, useMemo } from "react";
import { useParams } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import { FormProvider, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useGet, usePost, usePatch } from "@/Hooks/UseApi";
import { useNotificationForm } from "@/Hooks/useNotificationForm";
import type { NotificationFormData } from "@/Validation/notifications";
import type { Notification } from "@/Types/Notification";
import { useTranslation } from "react-i18next";
import { NotificationChannels } from "@/Types/Notification";
import { FormTextField } from "@/Components/inputs/forms/FormTextField";
import { FormSelectField } from "@/Components/inputs/forms/FormSelectField";
const NotificationsCreatePage = () => {
const { t } = useTranslation();
const theme = useTheme();
const navigate = useNavigate();
const { notificationId } = useParams<{ notificationId: string }>();
const isEditMode = Boolean(notificationId);
const { data: existingNotification } = useGet<Notification>(
isEditMode ? `/notifications/${notificationId}` : null
);
const { post, loading: isSubmitting } = usePost<NotificationFormData, Notification>();
const { patch, loading: isPatching } = usePatch<NotificationFormData, Notification>();
const { post: testPost, loading: isTesting } = usePost<NotificationFormData, void>();
const { schema, defaults } = useNotificationForm({ data: existingNotification });
const form = useForm<NotificationFormData>({
resolver: zodResolver(schema),
defaultValues: defaults,
});
const { watch, reset, handleSubmit, clearErrors, trigger, getValues } = form;
useEffect(() => {
reset(defaults);
}, [defaults, reset]);
const watchedType = watch("type");
useEffect(() => {
clearErrors();
}, [watchedType, clearErrors]);
const addressConfig = useMemo(() => {
if (watchedType === "pager_duty") {
return {
title: t("pages.notifications.form.pagerDuty.title"),
description: t("pages.notifications.form.pagerDuty.description"),
fieldLabel: t("pages.notifications.form.pagerDuty.optionIntegrationKey"),
placeholder: t("pages.notifications.form.pagerDuty.placeholder"),
};
}
if (watchedType === "email") {
return {
title: t("pages.notifications.form.address.title"),
description: t("pages.notifications.form.address.description"),
fieldLabel: t("pages.notifications.form.address.optionAddress"),
placeholder: t("pages.notifications.form.address.placeholderEmail"),
};
}
return {
title: t("pages.notifications.form.address.title"),
description: t("pages.notifications.form.address.description"),
fieldLabel: t("pages.notifications.form.address.optionAddress"),
placeholder: t("pages.notifications.form.address.placeholderWebhook"),
};
}, [watchedType, t]);
const onSubmit = async (data: NotificationFormData) => {
const result = isEditMode
? await patch(`/notifications/${notificationId}`, data)
: await post("/notifications", data);
if (result) {
navigate("/notifications");
}
};
const handleTest = async () => {
const isValid = await trigger();
if (!isValid) return;
const data = getValues();
await testPost("/notifications/test", data);
};
return (
<FormProvider {...form}>
<BasePage
component="form"
onSubmit={handleSubmit(onSubmit)}
>
<ConfigBox
title={t("pages.notifications.form.notificationName.title")}
subtitle={t("pages.notifications.form.notificationName.description")}
rightContent={
<FormTextField
name="notificationName"
fieldLabel={t("pages.notifications.form.notificationName.optionName")}
placeholder={t("pages.notifications.form.notificationName.placeholder")}
/>
}
/>
<ConfigBox
title={t("pages.notifications.form.type.title")}
subtitle={t("pages.notifications.form.type.description")}
rightContent={
<FormSelectField
name="type"
fieldLabel={t("pages.notifications.form.type.optionType")}
options={NotificationChannels.map((channel) => ({
value: channel,
label: t(`pages.notifications.form.type.value.${channel}`),
}))}
/>
}
/>
{watchedType !== "matrix" &&
watchedType !== "telegram" &&
watchedType !== "pushover" &&
watchedType !== "signalgrid" &&
watchedType !== "twilio" &&
watchedType !== "ntfy" && (
<ConfigBox
title={addressConfig.title}
subtitle={addressConfig.description}
rightContent={
<FormTextField
name="address"
fieldLabel={addressConfig.fieldLabel}
placeholder={addressConfig.placeholder}
/>
}
/>
)}
{watchedType === "ntfy" && (
<ConfigBox
title={t("pages.notifications.form.ntfy.title")}
subtitle={t("pages.notifications.form.ntfy.description")}
rightContent={
<Stack spacing={theme.spacing(8)}>
<FormTextField
name="address"
fieldLabel={t("pages.notifications.form.ntfy.optionServerUrl")}
placeholder={t("pages.notifications.form.ntfy.placeholderServerUrl")}
/>
<FormTextField
name="topic"
fieldLabel={t("pages.notifications.form.ntfy.optionTopic")}
placeholder={t("pages.notifications.form.ntfy.placeholderTopic")}
/>
</Stack>
}
/>
)}
{watchedType === "telegram" && (
<ConfigBox
title={t("pages.notifications.form.telegram.title")}
subtitle={t("pages.notifications.form.telegram.description")}
rightContent={
<Stack spacing={theme.spacing(8)}>
<FormTextField
name="accessToken"
fieldLabel={t("pages.notifications.form.telegram.optionBotToken")}
placeholder={t("pages.notifications.form.telegram.placeholderBotToken")}
/>
<FormTextField
name="address"
fieldLabel={t("pages.notifications.form.telegram.optionChatId")}
placeholder={t("pages.notifications.form.telegram.placeholderChatId")}
/>
</Stack>
}
/>
)}
{watchedType === "pushover" && (
<ConfigBox
title={t("pages.notifications.form.pushover.title")}
subtitle={t("pages.notifications.form.pushover.description")}
rightContent={
<Stack spacing={theme.spacing(8)}>
<FormTextField
name="accessToken"
fieldLabel={t("pages.notifications.form.pushover.optionAppToken")}
placeholder={t("pages.notifications.form.pushover.placeholderAppToken")}
/>
<FormTextField
name="address"
fieldLabel={t("pages.notifications.form.pushover.optionUserKey")}
placeholder={t("pages.notifications.form.pushover.placeholderUserKey")}
/>
</Stack>
}
/>
)}
{watchedType === "signalgrid" && (
<ConfigBox
title={t("pages.notifications.form.signalgrid.title")}
subtitle={t("pages.notifications.form.signalgrid.description")}
rightContent={
<Stack spacing={theme.spacing(8)}>
<FormTextField
name="accessToken"
fieldLabel={t("pages.notifications.form.signalgrid.optionClientKey")}
placeholder={t(
"pages.notifications.form.signalgrid.placeholderClientKey"
)}
/>
<FormTextField
name="address"
fieldLabel={t("pages.notifications.form.signalgrid.optionChannel")}
placeholder={t(
"pages.notifications.form.signalgrid.placeholderChannel"
)}
/>
</Stack>
}
/>
)}
{watchedType === "twilio" && (
<ConfigBox
title={t("pages.notifications.form.twilio.title")}
subtitle={t("pages.notifications.form.twilio.description")}
rightContent={
<Stack spacing={theme.spacing(8)}>
<FormTextField
name="accountSid"
fieldLabel={t("pages.notifications.form.twilio.optionAccountSid")}
placeholder={t("pages.notifications.form.twilio.placeholderAccountSid")}
/>
<FormTextField
name="accessToken"
fieldLabel={t("pages.notifications.form.twilio.optionAuthToken")}
placeholder={t("pages.notifications.form.twilio.placeholderAuthToken")}
/>
<FormTextField
name="twilioPhoneNumber"
fieldLabel={t("pages.notifications.form.twilio.optionFromNumber")}
placeholder={t("pages.notifications.form.twilio.placeholderFromNumber")}
/>
<FormTextField
name="phone"
fieldLabel={t("pages.notifications.form.twilio.optionToNumber")}
placeholder={t("pages.notifications.form.twilio.placeholderToNumber")}
/>
</Stack>
}
/>
)}
{watchedType === "matrix" && (
<ConfigBox
title={t("pages.notifications.form.matrix.title")}
subtitle={t("pages.notifications.form.matrix.description")}
rightContent={
<Stack spacing={theme.spacing(8)}>
<FormTextField
name="homeserverUrl"
fieldLabel={t("pages.notifications.form.homeServer.optionHomeServer")}
placeholder={t("pages.notifications.form.homeServer.placeholder")}
/>
<FormTextField
name="roomId"
fieldLabel={t("pages.notifications.form.roomId.optionRoomId")}
placeholder={t("pages.notifications.form.roomId.placeholder")}
/>
<FormTextField
name="accessToken"
fieldLabel={t("pages.notifications.form.accessToken.optionAccessToken")}
placeholder={t("pages.notifications.form.accessToken.placeholder")}
/>
</Stack>
}
/>
)}
<Stack
direction="row"
justifyContent="flex-end"
spacing={theme.spacing(2)}
>
<Button
variant="contained"
color="primary"
onClick={handleTest}
loading={isTesting}
>
{t("common.buttons.test")}
</Button>
<Button
loading={isSubmitting || isPatching}
type="submit"
variant="contained"
color="primary"
>
{t("common.buttons.save")}
</Button>
</Stack>
</BasePage>
</FormProvider>
);
};
export default NotificationsCreatePage;