import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { api } from "@/utils/api"; import { AlertBlock } from "@/components/shared/alert-block"; import { zodResolver } from "@hookform/resolvers/zod"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Label } from "@/components/ui/label"; import { AlertTriangle, Mail } from "lucide-react"; import { DiscordIcon, SlackIcon, TelegramIcon, } from "@/components/icons/notification-icons"; import { Switch } from "@/components/ui/switch"; const baseDatabaseSchema = z.object({ name: z.string().min(1, "Name required"), appDeploy: z.boolean().default(false), userJoin: z.boolean().default(false), appBuilderError: z.boolean().default(false), databaseBackup: z.boolean().default(false), dokployRestart: z.boolean().default(false), }); const mySchema = z.discriminatedUnion("type", [ z .object({ type: z.literal("slack"), webhookUrl: z.string().min(1), channel: z.string().min(1), }) .merge(baseDatabaseSchema), z .object({ type: z.literal("telegram"), botToken: z.string().min(1), chatId: z.string().min(1), }) .merge(baseDatabaseSchema), z .object({ type: z.literal("discord"), webhookUrl: z.string().min(1), }) .merge(baseDatabaseSchema), z .object({ type: z.literal("email"), smtpServer: z.string().min(1), smtpPort: z.string().min(1), username: z.string().min(1), password: z.string().min(1), toAddresses: z.array(z.string()).min(1), }) .merge(baseDatabaseSchema), ]); const notificationsMap = { slack: { icon: , label: "Slack", }, telegram: { icon: , label: "Telegram", }, discord: { icon: , label: "Discord", }, email: { icon: , label: "Email", }, }; type AddNotification = z.infer; export const AddNotification = () => { const utils = api.useUtils(); const [visible, setVisible] = useState(false); const slackMutation = api.notification.createSlack.useMutation(); const telegramMutation = api.notification.createTelegram.useMutation(); const discordMutation = api.notification.createDiscord.useMutation(); const emailMutation = api.notification.createEmail.useMutation(); const form = useForm({ defaultValues: { type: "slack", webhookUrl: "", channel: "", }, resolver: zodResolver(mySchema), }); useEffect(() => { form.reset(); }, [form, form.reset, form.formState.isSubmitSuccessful]); const type = form.watch("type"); const activeMutation = { slack: slackMutation, telegram: telegramMutation, discord: discordMutation, email: emailMutation, }; const onSubmit = async (data: AddNotification) => { const { appBuilderError, appDeploy, dokployRestart, databaseBackup, userJoin, } = data; let promise: Promise | null = null; if (data.type === "slack") { promise = slackMutation.mutateAsync({ appBuildError: appBuilderError, appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, userJoin: userJoin, webhookUrl: data.webhookUrl, channel: data.channel, name: data.name, }); } else if (data.type === "telegram") { promise = telegramMutation.mutateAsync({ appBuildError: appBuilderError, appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, userJoin: userJoin, botToken: data.botToken, chatId: data.chatId, name: data.name, }); } else if (data.type === "discord") { promise = discordMutation.mutateAsync({ appBuildError: appBuilderError, appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, userJoin: userJoin, webhookUrl: data.webhookUrl, name: data.name, }); } else if (data.type === "email") { promise = emailMutation.mutateAsync({ appBuildError: appBuilderError, appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, userJoin: userJoin, smtpServer: data.smtpServer, smtpPort: data.smtpPort, username: data.username, password: data.password, toAddresses: data.toAddresses, name: data.name, }); } if (promise) { await promise .then(async () => { toast.success("Notification Created"); form.reset({ type: "slack", webhookUrl: "", }); setVisible(false); await utils.notification.all.invalidate(); }) .catch(() => { toast.error("Error to create a notification"); }); } }; return ( Add Notification Add Notification Create new notifications providers for multiple {/* {isError && {error?.message}} */} ( Select a provider {Object.entries(notificationsMap).map(([key, value]) => ( {value.icon} {value.label} ))} {activeMutation[field.value].isError && ( {activeMutation[field.value].error?.message} )} )} /> Fill the next fields. ( Name )} /> {type === "slack" && ( <> ( Webhook URL )} /> ( Channel )} /> > )} {type === "telegram" && ( <> ( Bot Token )} /> ( Chat ID )} /> > )} {type === "discord" && ( <> ( Webhook URL )} /> > )} {type === "email" && ( <> ( SMTP Server )} /> ( SMTP Port )} /> ( Username )} /> ( Password )} /> ( To Addresses )} /> > )} Select the actions. ( App Deploy Trigger the action when a app is deployed. )} /> ( User Join Trigger the action when a user joins the app. )} /> ( Database Backup Trigger the action when a database backup is created. )} /> ( Deploy Restart Trigger the action when a deploy is restarted. )} /> Create ); };