import { type FormEvent, useState } from 'react'; import { ArrowLeft, BellRing, Send, Zap } from 'lucide-react'; import type { NotificationSettings } from '../api/settings'; import { navigate } from '../lib/router'; import { useLogoutMutation } from '../queries/auth'; import { useNotificationSettingsQuery, useTestNotificationWebhookMutation, useUpdateNotificationSettingsMutation, } from '../queries/settings'; function SettingsForm({ settings }: { settings: NotificationSettings }) { const [webhookUrl, setWebhookUrl] = useState(settings.webhookUrl ?? ''); const [webhookEnabled, setWebhookEnabled] = useState(settings.webhookEnabled); const updateMutation = useUpdateNotificationSettingsMutation(); const testMutation = useTestNotificationWebhookMutation(); function submit(event: FormEvent) { event.preventDefault(); updateMutation.mutate({ webhookUrl: webhookUrl.trim() || null, webhookEnabled }); } return (
{updateMutation.isSuccess &&

Notification settings saved.

} {testMutation.isSuccess &&

Test webhook delivered successfully.

} {(updateMutation.isError || testMutation.isError) && (

{(updateMutation.error ?? testMutation.error)?.message ?? 'Request failed'}

)}
); } export function SettingsPage() { const settingsQuery = useNotificationSettingsQuery(); const logoutMutation = useLogoutMutation(); return (
Settings

Integrations

Notifications

Route monitor transitions to Slack, Discord, or any service that accepts JSON webhooks.

Incident webhook

Upwatch sends a compact JSON payload for down and recovery events. Delivery failures never interrupt monitoring.

{settingsQuery.isPending ? (
Loading settings…
) : settingsQuery.isError ? (

Unable to load notification settings.

) : ( )}

Payload preview

{`{
  "event": "down",
  "monitor": { "id": 12, "name": "API", "url": "https://api.example.com" },
  "statusCode": 500,
  "error": "Expected HTTP 200, received 500",
  "at": "2026-08-28T03:25:00.000Z"
}`}
); }