import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { cn } from "~/client/lib/utils"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "~/client/components/ui/form"; import { Input } from "~/client/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~/client/components/ui/select"; import { customNotificationConfigSchema, discordNotificationConfigSchema, emailNotificationConfigSchema, genericNotificationConfigSchema, gotifyNotificationConfigSchema, ntfyNotificationConfigSchema, pushoverNotificationConfigSchema, slackNotificationConfigSchema, telegramNotificationConfigSchema, } from "~/schemas/notifications"; import { useScrollToFormError } from "~/client/hooks/use-scroll-to-form-error"; import { CustomForm, DiscordForm, EmailForm, GenericForm, GotifyForm, NtfyForm, PushoverForm, SlackForm, TelegramForm, } from "./notification-forms"; const baseFields = { name: z.string().min(2).max(32) }; export const formSchema = z.discriminatedUnion("type", [ emailNotificationConfigSchema.extend(baseFields), slackNotificationConfigSchema.extend(baseFields), discordNotificationConfigSchema.extend(baseFields), gotifyNotificationConfigSchema.extend(baseFields), ntfyNotificationConfigSchema.extend(baseFields), pushoverNotificationConfigSchema.extend(baseFields), telegramNotificationConfigSchema.extend(baseFields), genericNotificationConfigSchema.extend(baseFields), customNotificationConfigSchema.extend(baseFields), ]); export type NotificationFormValues = z.input; type Props = { onSubmit: (values: NotificationFormValues) => void; mode?: "create" | "update"; initialValues?: Partial; formId?: string; className?: string; }; const defaultValuesForType = { email: { type: "email" as const, smtpHost: "", smtpPort: 587, username: "", password: "", from: "", to: [], useTLS: true, }, slack: { type: "slack" as const, webhookUrl: "", channel: "", username: "", iconEmoji: "", }, discord: { type: "discord" as const, webhookUrl: "", }, gotify: { type: "gotify" as const, serverUrl: "", token: "", priority: 5, }, ntfy: { type: "ntfy" as const, topic: "", priority: "default" as const, }, pushover: { type: "pushover" as const, userKey: "", apiToken: "", priority: 0 as const, }, telegram: { type: "telegram" as const, botToken: "", chatId: "", threadId: "", }, generic: { type: "generic" as const, url: "", method: "POST" as const, contentType: "application/json", headers: [], useJson: true, titleKey: "title", messageKey: "message", }, custom: { type: "custom" as const, shoutrrrUrl: "", }, }; export const CreateNotificationForm = ({ onSubmit, mode = "create", initialValues, formId, className }: Props) => { const form = useForm({ resolver: zodResolver(formSchema, undefined, { raw: true }), defaultValues: initialValues || { name: "", }, resetOptions: { keepDefaultValues: false, keepDirtyValues: false, }, }); const { watch } = form; const scrollToFirstError = useScrollToFormError(); const watchedType = watch("type"); return (
( Name Unique identifier for this notification destination. )} /> ( Type Choose the notification delivery method. )} /> {watchedType === "email" && } {watchedType === "slack" && } {watchedType === "discord" && } {watchedType === "gotify" && } {watchedType === "ntfy" && } {watchedType === "pushover" && } {watchedType === "telegram" && } {watchedType === "generic" && } {watchedType === "custom" && } ); };