Blocks · @jengacore/alert-queue
Alert queue
Mulisa home: KPI strip, compact queue sorted by SLA then score, alert detail in the side panel.
Mulisa
Monitor · today
Alert queue
Screened today1,284,330+4.1% vs last Monday
Open alerts41 over SLA
Blocked value38,920USD12 transfers
Median decision14MINTarget 30 min · met
| Rules | Transfer | Amount | Status | |||
|---|---|---|---|---|---|---|
| −00:12past SLA, breached | 92, high risk | Sanctions name matchALT-20931 | SAN-001 | tx_01J9…H3V | 12,400.00USD | Breached |
| 00:18until SLA | 71, high risk | Velocity burstALT-20930 | VEL-014 | tx_01J9…W7P | 480.00USD | SLA < 1 h |
| 00:41until SLA | 64, medium risk | Structuring below thresholdALT-20928 | STR-003 | tx_01J9…N0D | 9,950.00USD | In review |
| 01:52until SLA | 48, medium risk | New payee, high valueALT-20925 | PAY-021 | tx_01J9…T5R | 3,200,000SLSH | In review |
Install
terminal
npx shadcn@latest add @jengacore/alert-queueWithout the namespace configured: npx shadcn@latest add https://ui.jengacore.com/r/<new-york-v4|base-nova>/alert-queue.json
Source
components/blocks/alert-queue.tsx
"use client"
import * as React from "react"
import { Download, Plus } from "lucide-react"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Sheet, SheetBody, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle } from "@/components/ui/sheet"
import { Amount } from "@/components/jc/amount"
import { PageHeader } from "@/components/jc/app-shell"
import { DataTable, type ColumnDef } from "@/components/jc/data-table"
import { IdChip } from "@/components/jc/id-chip"
import { KpiStrip } from "@/components/jc/kpi-strip"
import { RiskScore, type FiredRule } from "@/components/jc/risk-score"
import { RuleChip } from "@/components/jc/rule-chip"
import { ScoreChip } from "@/components/jc/score-chip"
import { SlaChip } from "@/components/jc/sla-chip"
import { StatusBadge } from "@/components/jc/status-badge"
export type QueueAlert = {
id: string
title: string
transfer: string
amount: string
currency: string
score: number
slaMinutes: number
status: string
rules: FiredRule[]
fresh?: boolean
}
const SAMPLE: QueueAlert[] = [
{ id: "ALT-20931", title: "Sanctions name match", transfer: "tx_01J9ZK4Q7MXH3V", amount: "12400", currency: "USD", score: 92, slaMinutes: -12, status: "breached", rules: [{ code: "SAN-001", condition: "Payee name matches a sanctions list entry ≥ 0.9" }], fresh: true },
{ id: "ALT-20930", title: "Velocity burst", transfer: "tx_01J9ZK4R2BQW7P", amount: "480", currency: "USD", score: 71, slaMinutes: 18, status: "sla_risk", rules: [{ code: "VEL-014", condition: "More than 12 transfers from one MSISDN in 10 min" }] },
{ id: "ALT-20928", title: "Structuring below threshold", transfer: "tx_01J9ZK3XQ1MN0D", amount: "9950", currency: "USD", score: 64, slaMinutes: 41, status: "in_review", rules: [{ code: "STR-003", condition: "Three transfers within 5% under the reporting threshold in 24 h" }] },
{ id: "ALT-20925", title: "New payee, high value", transfer: "tx_01J9ZK2M8DTT5R", amount: "3200000", currency: "SLSH", score: 48, slaMinutes: 112, status: "in_review", rules: [{ code: "PAY-021", condition: "First transfer to payee above 2,000,000 SLSH" }] },
]
const columns: ColumnDef<QueueAlert, unknown>[] = [
{ accessorKey: "slaMinutes", header: "SLA", cell: ({ row }) => <SlaChip minutes={row.original.slaMinutes} /> },
{ accessorKey: "score", header: "Score", cell: ({ row }) => <ScoreChip score={row.original.score} /> },
{
accessorKey: "title",
header: "Alert",
cell: ({ row }) => (
<div className="grid">
<span className="font-medium">{row.original.title}</span>
<span className="font-mono text-xs text-muted-foreground">{row.original.id}</span>
</div>
),
},
{ id: "rules", header: "Rules", enableSorting: false, cell: ({ row }) => {
const [rule] = row.original.rules
return rule ? <RuleChip code={rule.code} /> : "—"
} },
{ accessorKey: "transfer", header: "Transfer", enableSorting: false, cell: ({ row }) => <IdChip id={row.original.transfer} short /> },
{ accessorKey: "amount", header: "Amount", enableSorting: false, meta: { align: "right" }, cell: ({ row }) => <Amount value={row.original.amount} currency={row.original.currency} /> },
{ accessorKey: "status", header: "Status", enableSorting: false, cell: ({ row }) => <StatusBadge domain="alert" status={row.original.status} /> },
]
/** Mulisa triage: KPI row + compact queue sorted by SLA then score + the alert in a side panel. */
export function AlertQueue({ alerts = SAMPLE }: { alerts?: QueueAlert[] }) {
const [selected, setSelected] = React.useState<QueueAlert | null>(null)
const sorted = React.useMemo(() => [...alerts].sort((a, b) => a.slaMinutes - b.slaMinutes || b.score - a.score), [alerts])
const breached = alerts.filter((a) => a.slaMinutes < 0).length
return (
<div className="flex flex-col gap-6">
<PageHeader
eyebrow="Monitor · today"
title="Alert queue"
actions={
<>
<Button variant="outline">
<Download />
Export
</Button>
<Button>
<Plus />
New rule
</Button>
</>
}
/>
<KpiStrip
items={[
{ label: "Screened today", value: "1,284,330", note: <><b>+4.1%</b> vs last Monday</>, trend: "up" },
{ label: "Open alerts", value: String(alerts.length), note: <><b>{breached} over SLA</b></>, trend: "warn" },
{ label: "Blocked value", value: "38,920", unit: "USD", note: "12 transfers" },
{ label: "Median decision", value: "14", unit: "MIN", note: <><b>Target 30 min</b> · met</>, trend: "up" },
]}
/>
<DataTable
columns={columns}
data={sorted}
density="compact"
getRowId={(r) => r.id}
selectedId={selected?.id}
isFresh={(r) => !!r.fresh}
onRowClick={setSelected}
empty={{ title: "No open alerts.", description: "New alerts appear here as transfers are screened." }}
/>
<Sheet open={!!selected} onOpenChange={(o: boolean) => !o && setSelected(null)}>
<SheetContent>
{selected ? (
<>
<SheetHeader>
<SheetDescription>{selected.id}</SheetDescription>
<SheetTitle>{selected.title}</SheetTitle>
</SheetHeader>
<SheetBody className="flex flex-col gap-5">
<div className="flex flex-wrap items-center gap-2">
<StatusBadge domain="alert" status={selected.status} />
<SlaChip minutes={selected.slaMinutes} />
</div>
<RiskScore score={selected.score} rules={selected.rules} />
<dl className="grid grid-cols-[auto_1fr] gap-x-6 gap-y-2 text-[13.5px]">
<dt className="eyebrow leading-6">Transfer</dt>
<dd><IdChip id={selected.transfer} /></dd>
<dt className="eyebrow leading-6">Amount</dt>
<dd><Amount value={selected.amount} currency={selected.currency} /></dd>
</dl>
</SheetBody>
<SheetFooter>
<Button variant="outline" shortcut="C">Clear</Button>
<Button variant="secondary" shortcut="E">Escalate</Button>
<Button variant="destructive" shortcut="B">Block</Button>
</SheetFooter>
</>
) : null}
</SheetContent>
</Sheet>
</div>
)
}