({ onSelectMarket, categoryFilter, strengthFilter }: ResolutionPanelProps)
| 102 | } |
| 103 | |
| 104 | export default function ResolutionPanel({ onSelectMarket, categoryFilter, strengthFilter }: ResolutionPanelProps) { |
| 105 | const { t } = useI18n(); |
| 106 | const { enriched } = useResolutionData(); |
| 107 | |
| 108 | const filtered = useMemo(() => { |
| 109 | let result = enriched; |
| 110 | if (strengthFilter.size > 0) result = result.filter((a) => strengthFilter.has(a.strength)); |
| 111 | if (categoryFilter.size > 0) result = result.filter((a) => a.category && categoryFilter.has(a.category)); |
| 112 | return result; |
| 113 | }, [enriched, categoryFilter, strengthFilter]); |
| 114 | |
| 115 | return ( |
| 116 | <div className="font-mono"> |
| 117 | {filtered.length === 0 ? ( |
| 118 | <div className="text-[12px] text-[var(--text-ghost)] py-4 text-center"> |
| 119 | {t("resolutionPanel.noAlerts")} |
| 120 | </div> |
| 121 | ) : ( |
| 122 | <div className="space-y-0"> |
| 123 | {filtered.map((alert) => ( |
| 124 | <div |
| 125 | key={alert.id} |
| 126 | className="border-b border-[var(--border-subtle)] last:border-0" |
| 127 | style={{ background: alert.strength === "strong" ? "rgba(255,68,68,0.03)" : undefined }} |
| 128 | > |
| 129 | <div className="px-1.5 py-[5px]"> |
| 130 | <div className="flex items-center gap-1 mb-0.5"> |
| 131 | <span |
| 132 | className="text-[8px] font-bold rounded-sm px-0.5 leading-[14px]" |
| 133 | style={{ background: STRENGTH_BG[alert.strength], color: STRENGTH_COLORS[alert.strength] }} |
| 134 | > |
| 135 | {t(`signals.${alert.strength === "strong" ? "str" : alert.strength === "moderate" ? "mod" : "wea"}`)} |
| 136 | </span> |
| 137 | <span className="text-[10px] font-bold text-[var(--text-faint)] uppercase tracking-wide"> |
| 138 | {alert.source} |
| 139 | </span> |
| 140 | {alert.prob !== null && ( |
| 141 | <span className="text-[10px] tabular-nums text-[var(--text-dim)]"> |
| 142 | @{(alert.prob * 100).toFixed(0)}% |
| 143 | </span> |
| 144 | )} |
| 145 | <span className="text-[10px] text-[var(--text-ghost)] ml-auto shrink-0"> |
| 146 | {timeAgo(new Date(alert.detectedAt).getTime())} |
| 147 | </span> |
| 148 | </div> |
| 149 | |
| 150 | <a |
| 151 | href={alert.url} |
| 152 | target="_blank" |
| 153 | rel="noopener noreferrer" |
| 154 | className="text-[11px] text-[var(--text-secondary)] leading-tight hover:text-[var(--text)] transition-colors block" |
| 155 | > |
| 156 | {alert.title} |
| 157 | </a> |
| 158 | |
| 159 | <button |
| 160 | onClick={() => onSelectMarket?.(alert.slug)} |
| 161 | className="text-[10px] text-[var(--green,#22c55e)] hover:underline truncate block max-w-full text-left mt-0.5" |
nothing calls this directly
no test coverage detected