({
smartTrades,
markets,
onSelectMarket,
onSelectWallet,
}: {
smartTrades: WhaleTrade[];
markets: ProcessedMarket[];
onSelectMarket?: (slug: string) => void;
onSelectWallet?: (address: string) => void;
})
| 280 | } |
| 281 | |
| 282 | function SignalsView({ |
| 283 | smartTrades, |
| 284 | markets, |
| 285 | onSelectMarket, |
| 286 | onSelectWallet, |
| 287 | }: { |
| 288 | smartTrades: WhaleTrade[]; |
| 289 | markets: ProcessedMarket[]; |
| 290 | onSelectMarket?: (slug: string) => void; |
| 291 | onSelectWallet?: (address: string) => void; |
| 292 | }) { |
| 293 | const { t } = useI18n(); |
| 294 | const signals = useMemo( |
| 295 | () => detectSignals(smartTrades, markets), |
| 296 | [smartTrades, markets] |
| 297 | ); |
| 298 | |
| 299 | if (signals.length === 0) { |
| 300 | return ( |
| 301 | <div className="text-[12px] text-[var(--text-ghost)] py-4 text-center"> |
| 302 | {t("smartMoney.noSignals6h")} |
| 303 | </div> |
| 304 | ); |
| 305 | } |
| 306 | |
| 307 | return ( |
| 308 | <div className="space-y-0.5"> |
| 309 | {signals.map((sig) => ( |
| 310 | <div |
| 311 | key={sig.id} |
| 312 | className="border-b border-[var(--border-subtle)] last:border-0 px-1.5 py-[5px]" |
| 313 | > |
| 314 | {/* Header row */} |
| 315 | <div className="flex items-center gap-1.5"> |
| 316 | <span className="text-[12px] shrink-0">{SIGNAL_ICONS[sig.type] || "?"}</span> |
| 317 | <span |
| 318 | className="text-[8px] px-1 rounded-sm shrink-0 font-bold uppercase" |
| 319 | style={{ |
| 320 | color: STRENGTH_COLORS[sig.strength], |
| 321 | background: sig.strength === "strong" ? "rgba(255,68,68,0.1)" : sig.strength === "moderate" ? "rgba(245,158,11,0.1)" : "rgba(128,128,128,0.1)", |
| 322 | }} |
| 323 | > |
| 324 | {sig.strength} |
| 325 | </span> |
| 326 | <span className="text-[10px] text-[var(--text-faint)] shrink-0"> |
| 327 | {t(SIGNAL_LABEL_KEYS[sig.type] || sig.type)} |
| 328 | </span> |
| 329 | <span className="text-[10px] text-[var(--text-ghost)] ml-auto shrink-0 tabular-nums"> |
| 330 | {signalTimeAgo(sig.timestamp)} |
| 331 | </span> |
| 332 | </div> |
| 333 | |
| 334 | {/* Market title */} |
| 335 | <button |
| 336 | onClick={() => onSelectMarket?.(sig.market.slug)} |
| 337 | className="text-[11px] text-[var(--text-secondary)] truncate w-full text-left hover:text-[var(--text)] transition-colors mt-0.5" |
| 338 | title={sig.market.title} |
| 339 | > |
nothing calls this directly
no test coverage detected