import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { pb } from "@/lib/stores" import { Separator } from "@/components/ui/separator" import { Card } from "@/components/ui/card" import { BellIcon, LoaderCircleIcon, PlusIcon, SaveIcon, Trash2Icon } from "lucide-react" import { ChangeEventHandler, useEffect, useState } from "react" import { toast } from "@/components/ui/use-toast" import { InputTags } from "@/components/ui/input-tags" import { UserSettings } from "@/types" import { saveSettings } from "./layout" import * as v from "valibot" import { isAdmin } from "@/lib/utils" import { useTranslation } from "react-i18next" interface ShoutrrrUrlCardProps { url: string onUrlChange: ChangeEventHandler onRemove: () => void } const NotificationSchema = v.object({ emails: v.array(v.pipe(v.string(), v.email())), webhooks: v.array(v.pipe(v.string(), v.url())), }) const SettingsNotificationsPage = ({ userSettings }: { userSettings: UserSettings }) => { const { t } = useTranslation() const [webhooks, setWebhooks] = useState(userSettings.webhooks ?? []) const [emails, setEmails] = useState(userSettings.emails ?? []) const [isLoading, setIsLoading] = useState(false) // update values when userSettings changes useEffect(() => { setWebhooks(userSettings.webhooks ?? []) setEmails(userSettings.emails ?? []) }, [userSettings]) function addWebhook() { setWebhooks([...webhooks, ""]) // focus on the new input queueMicrotask(() => { const inputs = document.querySelectorAll("#webhooks input") as NodeListOf inputs[inputs.length - 1]?.focus() }) } const removeWebhook = (index: number) => setWebhooks(webhooks.filter((_, i) => i !== index)) function updateWebhook(index: number, value: string) { const newWebhooks = [...webhooks] newWebhooks[index] = value setWebhooks(newWebhooks) } async function updateSettings() { setIsLoading(true) try { const parsedData = v.parse(NotificationSchema, { emails, webhooks }) await saveSettings(parsedData) } catch (e: any) { toast({ title: "Failed to save settings", description: e.message, variant: "destructive", }) } setIsLoading(false) } return (

{t("settings.notifications.title")}

{t("settings.notifications.subtitle_1")}

{t("settings.notifications.subtitle_2")} {" "} {t("settings.notifications.subtitle_3")}

{t("settings.notifications.email.title")}

{isAdmin() && (

{t("settings.notifications.email.please")}{" "} {t("settings.notifications.email.configure_an_SMTP_server")} {" "} {t("settings.notifications.email.to_ensure_alerts_are_delivered")}{" "}

)}

{t("settings.notifications.email.des")}

{t("settings.notifications.webhook_push.title")}

{t("settings.notifications.webhook_push.des_1")}{" "} Shoutrrr {" "} {t("settings.notifications.webhook_push.des_2")}

{webhooks.length > 0 && (
{webhooks.map((webhook, index) => ( ) => updateWebhook(index, e.target.value)} onRemove={() => removeWebhook(index)} /> ))}
)}
) } const ShoutrrrUrlCard = ({ url, onUrlChange, onRemove }: ShoutrrrUrlCardProps) => { const [isLoading, setIsLoading] = useState(false) const sendTestNotification = async () => { setIsLoading(true) const res = await pb.send("/api/beszel/send-test-notification", { url }) if ("err" in res && !res.err) { toast({ title: "Test notification sent", description: "Check your notification service", }) } else { toast({ title: "Error", description: res.err ?? "Failed to send test notification", variant: "destructive", }) } setIsLoading(false) } return (
) } export default SettingsNotificationsPage