"use client"; import { GlassPanel } from "@/components/primitives"; import { SectionHeader } from "@/components/shared"; import type { MessageActivityBucket } from "@/lib/types"; const HOURS = Array.from({ length: 24 }, (_, i) => i); function heatColor(t: number): string { // t in [0,1] → signal gradient (dark → bright). if (t <= 0) return "var(--color-hairline)"; return `rgba(45, 212, 191, ${0.15 + 0.85 * t})`; } export function ActivityHeatmap({ buckets, }: { buckets: MessageActivityBucket[]; }) { // Group by channel, find max count for normalization. const channels = Array.from(new Set(buckets.map((b) => b.channelId))); const byKey = new Map(); let max = 0; for (const b of buckets) { const k = `${b.channelId}:${b.hour}`; byKey.set(k, (byKey.get(k) ?? 0) + b.count); if ((byKey.get(k) ?? 0) > max) max = byKey.get(k) ?? 0; } if (buckets.length === 0) { return (

No message activity recorded yet.

); } return ( {channels.length} channels · messages/hour } />
{channels.map((ch) => (
{ch.slice(-6)}
{HOURS.map((h) => { const c = byKey.get(`${ch}:${h}`) ?? 0; const t = max > 0 ? c / max : 0; return (
); })}
))}
{[0, 6, 12, 18, 23].map((h) => ( {String(h).padStart(2, "0")}h ))}
); }