feat(15-03): add alert rules UI, alert events table, and notification bell
- AlertRuleFormDialog with rule type selector, threshold input, auto-set units - AlertRulesTab with list, enable toggle, edit, delete, and add button - AlertEventsTable with severity badges, resolve action, and state filter tabs - NotificationBell polls active alert count with 60s interval - Site dashboard gains Alerts tab rendering both AlertRulesTab and AlertEventsTable - NotificationBell integrated into ContextStrip header for tenant users Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,8 @@ import { cn } from '@/lib/utils'
|
||||
import { SiteHealthGrid } from '@/components/sites/SiteHealthGrid'
|
||||
import { SiteSectorView } from '@/components/sites/SiteSectorView'
|
||||
import { SiteLinksTab } from '@/components/sites/SiteLinksTab'
|
||||
import { AlertRulesTab } from '@/components/alerts/AlertRulesTab'
|
||||
import { AlertEventsTable } from '@/components/alerts/AlertEventsTable'
|
||||
|
||||
export const Route = createFileRoute('/_authenticated/tenants/$tenantId/sites/$siteId')({
|
||||
component: SiteDetailPage,
|
||||
@@ -15,7 +17,7 @@ export const Route = createFileRoute('/_authenticated/tenants/$tenantId/sites/$s
|
||||
|
||||
function SiteDetailPage() {
|
||||
const { tenantId, siteId } = Route.useParams()
|
||||
const [activeTab, setActiveTab] = useState<'health' | 'sectors' | 'links'>('health')
|
||||
const [activeTab, setActiveTab] = useState<'health' | 'sectors' | 'links' | 'alerts'>('health')
|
||||
|
||||
const { data: site, isLoading } = useQuery({
|
||||
queryKey: ['sites', tenantId, siteId],
|
||||
@@ -118,7 +120,7 @@ function SiteDetailPage() {
|
||||
|
||||
{/* Tab bar */}
|
||||
<div className="flex gap-1 border-b border-border">
|
||||
{(['health', 'sectors', 'links'] as const).map((tab) => (
|
||||
{(['health', 'sectors', 'links', 'alerts'] as const).map((tab) => (
|
||||
<button
|
||||
key={tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
@@ -129,7 +131,7 @@ function SiteDetailPage() {
|
||||
: 'border-transparent text-text-muted hover:text-text-secondary',
|
||||
)}
|
||||
>
|
||||
{tab === 'health' ? 'Health Grid' : tab === 'sectors' ? 'Sectors' : 'Links'}
|
||||
{tab === 'health' ? 'Health Grid' : tab === 'sectors' ? 'Sectors' : tab === 'links' ? 'Links' : 'Alerts'}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@@ -138,6 +140,12 @@ function SiteDetailPage() {
|
||||
{activeTab === 'health' && <SiteHealthGrid tenantId={tenantId} siteId={siteId} />}
|
||||
{activeTab === 'sectors' && <SiteSectorView tenantId={tenantId} siteId={siteId} />}
|
||||
{activeTab === 'links' && <SiteLinksTab tenantId={tenantId} siteId={siteId} />}
|
||||
{activeTab === 'alerts' && (
|
||||
<div className="space-y-6">
|
||||
<AlertRulesTab tenantId={tenantId} siteId={siteId} />
|
||||
<AlertEventsTable tenantId={tenantId} siteId={siteId} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user