import { useState, useEffect } from "react"; import AlertForm from "../components/AlertForm"; import Button from "../components/Button"; import Input from "../components/Input"; import { getAddresses } from "../api/addresses"; import { getAlerts, createAlert, updateAlertStatus, deleteAlert, } from "../api/alerts"; import { getNotificationConfig, updateNotificationConfig, testNotificationChannels, setupEmail, sendEmailDigest, } from "../api/notificationConfig"; import "./Alerts.css"; export default function Alerts() { const [addresses, setAddresses] = useState([]); const [selectedAddressId, setSelectedAddressId] = useState(null); const [alerts, setAlerts] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [notificationEnabled, setNotificationEnabled] = useState(false); const [discordWebhookUrl, setDiscordWebhookUrl] = useState(""); const [telegramBotToken, setTelegramBotToken] = useState(""); const [telegramChatId, setTelegramChatId] = useState(""); const [email, setEmail] = useState(""); const [slackWebhookUrl, setSlackWebhookUrl] = useState(""); const [notificationLoading, setNotificationLoading] = useState(false); const [notificationError, setNotificationError] = useState(null); const [notificationSuccess, setNotificationSuccess] = useState(null); const [testingChannels, setTestingChannels] = useState(false); const [settingUpEmail, setSettingUpEmail] = useState(false); const [sendingDigest, setSendingDigest] = useState(false); const [hasExistingConfig, setHasExistingConfig] = useState(false); useEffect(() => { async function fetchData() { try { setLoading(true); const addressData = await getAddresses(); setAddresses(addressData); if (addressData.length > 0) { setSelectedAddressId(addressData[0].id); } const configData = await getNotificationConfig(); setNotificationEnabled( configData.notification_enabled !== false, ); setDiscordWebhookUrl(configData.discord_webhook_url || ""); setTelegramBotToken(configData.telegram_bot_token || ""); setTelegramChatId(configData.telegram_chat_id || ""); setEmail(configData.email || ""); setSlackWebhookUrl(configData.slack_webhook_url || ""); const hasSaved = !!configData.discord_webhook_url || !!configData.telegram_bot_token || !!configData.telegram_chat_id || !!configData.email || !!configData.slack_webhook_url; setHasExistingConfig(hasSaved); } catch (err) { setError(err.message); console.error("Failed to fetch data:", err); } finally { setLoading(false); } } fetchData(); }, []); useEffect(() => { if (!selectedAddressId) { setAlerts([]); return; } async function fetchAlerts() { try { const data = await getAlerts(selectedAddressId); setAlerts(data); setError(null); } catch (err) { setError(err.message); console.error("Failed to fetch alerts:", err); } } fetchAlerts(); }, [selectedAddressId]); async function handleAlertSubmit(data) { if (!selectedAddressId) return; try { const newAlert = await createAlert(selectedAddressId, data); setAlerts((prev) => [...prev, newAlert]); setError(null); } catch (err) { setError(err.message); console.error("Failed to create alert:", err); } } async function handleToggleAlert(alertId, currentStatus) { try { const updated = await updateAlertStatus(alertId, !currentStatus); setAlerts((prev) => prev.map((alert) => (alert.id === alertId ? updated : alert)), ); setError(null); } catch (err) { setError(err.message); console.error("Failed to update alert:", err); } } async function handleDeleteAlert(alertId) { try { await deleteAlert(alertId); setAlerts((prev) => prev.filter((alert) => alert.id !== alertId)); setError(null); } catch (err) { setError(err.message); console.error("Failed to delete alert:", err); } } async function handleSaveNotificationConfig() { if (hasExistingConfig) { const confirmed = window.confirm( "This will overwrite your previously saved notification settings. Continue?", ); if (!confirmed) return; } try { setNotificationLoading(true); setNotificationError(null); setNotificationSuccess(null); const config = { notification_enabled: notificationEnabled, discord_webhook_url: discordWebhookUrl || null, telegram_bot_token: telegramBotToken || null, telegram_chat_id: telegramChatId || null, email: email || null, slack_webhook_url: slackWebhookUrl || null, }; await updateNotificationConfig(config); setHasExistingConfig(true); setNotificationSuccess("Notification settings saved!"); setTimeout(() => setNotificationSuccess(null), 3000); } catch (err) { setNotificationError(err.message); console.error("Failed to save notification config:", err); } finally { setNotificationLoading(false); } } async function handleTestChannels() { try { setTestingChannels(true); setNotificationError(null); setNotificationSuccess(null); const data = await testNotificationChannels(); const results = data.results || []; const failed = results.filter((r) => !r.success); const succeeded = results.filter((r) => r.success); if (failed.length === 0 && succeeded.length > 0) { setNotificationSuccess( `Test sent to: ${succeeded.map((r) => r.channel).join(", ")}`, ); } else if (failed.length > 0 && succeeded.length > 0) { setNotificationSuccess( `Sent: ${succeeded.map((r) => r.channel).join(", ")}. Failed: ${failed.map((r) => `${r.channel} (${r.error})`).join(", ")}`, ); } else if (failed.length > 0) { setNotificationError( `Test failed: ${failed.map((r) => `${r.channel} (${r.error})`).join(", ")}`, ); } setTimeout(() => { setNotificationSuccess(null); setNotificationError(null); }, 6000); } catch (err) { setNotificationError(err.message); } finally { setTestingChannels(false); } } async function handleSetupEmail() { try { setSettingUpEmail(true); setNotificationError(null); setNotificationSuccess(null); await handleSaveNotificationConfig(); const result = await setupEmail(); setNotificationSuccess( result.message || "Confirmation email sent!", ); setTimeout(() => setNotificationSuccess(null), 5000); } catch (err) { setNotificationError(err.message); } finally { setSettingUpEmail(false); } } async function handleSendDigest() { try { setSendingDigest(true); setNotificationError(null); setNotificationSuccess(null); const result = await sendEmailDigest(); setNotificationSuccess(result.message || "Digest email sent!"); setTimeout(() => setNotificationSuccess(null), 5000); } catch (err) { setNotificationError(err.message); } finally { setSendingDigest(false); } } const selectedAddress = addresses.find((a) => a.id === selectedAddressId); if (loading) { return
No addresses tracked yet. Add an address first to create alerts.
Error: {error}
)} {alerts.length === 0 ? (No alert rules defined yet. Create one above.
) : (