diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css index 3a6c3b3..b898576 100644 --- a/apps/web/app/globals.css +++ b/apps/web/app/globals.css @@ -586,9 +586,9 @@ h1 { color: #6f5b39; } -.severity-strip { +.alert-strips { display: grid; - gap: 8px; + gap: 12px; margin-bottom: 16px; padding: 12px 14px; border-radius: 14px; @@ -596,16 +596,21 @@ h1 { background: rgba(255, 255, 255, 0.7); } -.severity-strip-header { - display: flex; - justify-content: space-between; - font-size: 0.75rem; - color: #6f5b39; - text-transform: uppercase; - letter-spacing: 0.2em; +.alert-strip-section { + display: grid; + gap: 6px; } -.severity-strip-bar { +.alert-strip-header { + display: flex; + justify-content: space-between; + font-size: 0.7rem; + color: #6f5b39; + text-transform: uppercase; + letter-spacing: 0.22em; +} + +.alert-strip-bar { display: flex; height: 26px; border-radius: 999px; @@ -614,28 +619,42 @@ h1 { background: rgba(111, 91, 57, 0.08); } -.severity-segment { +.strip-segment { display: flex; align-items: center; justify-content: center; - font-size: 0.7rem; + font-size: 0.65rem; color: #fffdf7; letter-spacing: 0.08em; + text-transform: uppercase; } -.severity-strip .severity-high { +.alert-strip-bar .severity-high { background: rgba(196, 111, 42, 0.85); color: #3b1a09; } -.severity-strip .severity-medium { +.alert-strip-bar .severity-medium { background: rgba(31, 74, 123, 0.8); } -.severity-strip .severity-low { +.alert-strip-bar .severity-low { background: rgba(47, 109, 79, 0.8); } +.alert-strip-bar .direction-bullish { + background: rgba(47, 109, 79, 0.85); +} + +.alert-strip-bar .direction-bearish { + background: rgba(196, 111, 42, 0.85); + color: #3b1a09; +} + +.alert-strip-bar .direction-neutral { + background: rgba(111, 91, 57, 0.65); +} + .flow-meta span { display: inline-flex; align-items: center; diff --git a/apps/web/app/page.tsx b/apps/web/app/page.tsx index 433d954..bdc0f71 100644 --- a/apps/web/app/page.tsx +++ b/apps/web/app/page.tsx @@ -971,7 +971,7 @@ type AlertSeverityStripProps = { const AlertSeverityStrip = ({ alerts }: AlertSeverityStripProps) => { const windowMs = 30 * 60 * 1000; const now = Date.now(); - const counts = alerts.reduce( + const severityCounts = alerts.reduce( (acc, alert) => { if (now - alert.source_ts > windowMs) { return acc; @@ -988,26 +988,63 @@ const AlertSeverityStrip = ({ alerts }: AlertSeverityStripProps) => { { high: 0, medium: 0, low: 0 } ); - const total = counts.high + counts.medium + counts.low; - const highPct = total > 0 ? (counts.high / total) * 100 : 0; - const mediumPct = total > 0 ? (counts.medium / total) * 100 : 0; - const lowPct = total > 0 ? (counts.low / total) * 100 : 0; + const directionCounts = alerts.reduce( + (acc, alert) => { + if (now - alert.source_ts > windowMs) { + return acc; + } + const direction = normalizeDirection(alert.hits[0]?.direction ?? "neutral"); + acc[direction] += 1; + return acc; + }, + { bullish: 0, bearish: 0, neutral: 0 } + ); + + const severityTotal = severityCounts.high + severityCounts.medium + severityCounts.low; + const highPct = severityTotal > 0 ? (severityCounts.high / severityTotal) * 100 : 0; + const mediumPct = severityTotal > 0 ? (severityCounts.medium / severityTotal) * 100 : 0; + const lowPct = severityTotal > 0 ? (severityCounts.low / severityTotal) * 100 : 0; + + const directionTotal = + directionCounts.bullish + directionCounts.bearish + directionCounts.neutral; + const bullishPct = directionTotal > 0 ? (directionCounts.bullish / directionTotal) * 100 : 0; + const bearishPct = directionTotal > 0 ? (directionCounts.bearish / directionTotal) * 100 : 0; + const neutralPct = directionTotal > 0 ? (directionCounts.neutral / directionTotal) * 100 : 0; return ( -
-
- Last 30m - {total} alerts +
+
+
+ Severity (last 30m) + {severityTotal} alerts +
+
+
+ {severityCounts.high > 0 ? `High ${severityCounts.high}` : ""} +
+
+ {severityCounts.medium > 0 ? `Med ${severityCounts.medium}` : ""} +
+
+ {severityCounts.low > 0 ? `Low ${severityCounts.low}` : ""} +
+
-
-
- {counts.high > 0 ? counts.high : ""} +
+
+ Direction (last 30m) + {directionTotal} alerts
-
- {counts.medium > 0 ? counts.medium : ""} -
-
- {counts.low > 0 ? counts.low : ""} +
+
+ {directionCounts.bullish > 0 ? `Bull ${directionCounts.bullish}` : ""} +
+
+ {directionCounts.bearish > 0 ? `Bear ${directionCounts.bearish}` : ""} +
+
+ {directionCounts.neutral > 0 ? `Neut ${directionCounts.neutral}` : ""} +