import React, { useEffect, useState } from 'react' import { adminApi } from '../../api/client' import { useToast } from '../../components/shared/Toast' import { ADMIN_EVENT_LABEL_KEYS, ADMIN_CHANNEL_LABEL_KEYS } from './AdminPage.constants' // Per-event × per-channel admin notification preference matrix. // Loads its own data and auto-saves each toggle. Markup identical to AdminPage. export default function AdminNotificationsPanel({ t, toast }: { t: (k: string) => string; toast: ReturnType }) { const [matrix, setMatrix] = useState(null) const [saving, setSaving] = useState(false) useEffect(() => { adminApi.getNotificationPreferences().then((data: any) => setMatrix(data)).catch(() => {}) }, []) if (!matrix) return

Loading…

const visibleChannels = (['inapp', 'email', 'webhook', 'ntfy'] as const).filter(ch => { if (!matrix.available_channels[ch]) return false return matrix.event_types.some((evt: string) => matrix.implemented_combos[evt]?.includes(ch)) }) const toggle = async (eventType: string, channel: string) => { const current = matrix.preferences[eventType]?.[channel] ?? true const updated = { ...matrix.preferences, [eventType]: { ...matrix.preferences[eventType], [channel]: !current } } setMatrix((m: any) => m ? { ...m, preferences: updated } : m) setSaving(true) try { await adminApi.updateNotificationPreferences(updated) } catch { setMatrix((m: any) => m ? { ...m, preferences: matrix.preferences } : m) toast.error(t('common.error')) } finally { setSaving(false) } } if (matrix.event_types.length === 0) { return (

{t('settings.notificationPreferences.noChannels')}

) } return (

{t('admin.tabs.notifications')}

{t('admin.notifications.adminNotificationsHint')}

{saving &&

Saving…

} {/* Header row */}
'80px').join(' ')}`, gap: 4, paddingBottom: 6, marginBottom: 4 }}> {visibleChannels.map(ch => ( {t(ADMIN_CHANNEL_LABEL_KEYS[ch]) || ch} ))}
{/* Event rows */} {matrix.event_types.map((eventType: string) => { const implementedForEvent = matrix.implemented_combos[eventType] ?? [] return (
'80px').join(' ')}`, gap: 4, alignItems: 'center', padding: '8px 0' }}> {t(ADMIN_EVENT_LABEL_KEYS[eventType]) || eventType} {visibleChannels.map(ch => { if (!implementedForEvent.includes(ch)) { return } const isOn = matrix.preferences[eventType]?.[ch] ?? true return (
) })}
) })}
) }