Files
trumpsignal-frontend/components/dashboard/PostCards.tsx
T
2026-04-21 19:32:53 +08:00

76 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import type { TrumpPost } from '@/types'
function fmtPct(n: number | null | undefined) {
if (n == null || isNaN(n)) return '—'
const s = n.toFixed(2) + '%'
return n >= 0 ? '+' + s : s
}
function timeAgo(iso: string) {
const diff = Date.now() - new Date(iso).getTime()
const m = Math.floor(diff / 60000)
if (m < 1) return 'just now'
if (m < 60) return m + 'm'
const h = Math.floor(m / 60)
if (h < 24) return h + 'h'
return Math.floor(h / 24) + 'd'
}
function SourceIcon({ source }: { source: string }) {
if (source === 'x') return <div className="src-ico x">𝕏</div>
return <div className="src-ico truth">T</div>
}
function SignalPill({ signal }: { signal: string | null }) {
if (!signal || signal === 'hold') return <span className="sig hold">HOLD</span>
return <span className={`sig ${signal}`}>{signal.toUpperCase()}</span>
}
interface PostRowProps {
post: TrumpPost
selected?: boolean
onClick?: () => void
}
export default function PostRow({ post, selected, onClick }: PostRowProps) {
const impact = post.price_impact
return (
<div className={`post-row ${selected ? 'selected' : ''}`} onClick={onClick}>
<SourceIcon source={post.source} />
<div className="post-body">
<div className="meta">
<span className="mono" style={{ color: 'var(--ink-2)', fontWeight: 500 }}>@realDonaldTrump</span>
<span>·</span>
<span>{timeAgo(post.published_at)} ago</span>
<span>·</span>
<span className={`chip ${post.sentiment === 'bullish' ? 'up' : post.sentiment === 'bearish' ? 'down' : 'neutral'}`} style={{ padding: '2px 8px', fontSize: 11 }}>
{post.sentiment}
</span>
</div>
<p className="text">{post.text.slice(0, 180)}{post.text.length > 180 ? '…' : ''}</p>
</div>
<div className="post-aside">
<SignalPill signal={post.signal} />
<div className="impact-mini">
{impact ? (
<>
<span className="tf">1h</span>
<span className={`delta ${(impact.m1h ?? 0) >= 0 ? 'up' : 'down'}`}>{fmtPct(impact.m1h)}</span>
</>
) : (
<span className="tf">no data</span>
)}
</div>
<div className="row gap-s" style={{ fontSize: 11, color: 'var(--ink-3)' }}>
<span>AI</span>
<span className="mono" style={{ color: 'var(--ink-2)', fontWeight: 500 }}>{post.ai_confidence}%</span>
</div>
</div>
</div>
)
}
export { SignalPill, SourceIcon, fmtPct, timeAgo }