'use client' import { useState, useEffect, useMemo } from 'react' import { useLocale } from 'next-intl' import type { TrumpPost } from '@/types' import { getPosts } from '@/lib/api' import { swrFetch } from '@/lib/cache' import PostRow from '@/components/dashboard/PostCards' import SystemControl from '@/components/signals/SystemControl' /** * System 1 — Trump (event-driven scalp). Its own dedicated page. * Shows ONLY source === 'truth'. No scanner panel (that's System 2). */ const SENTIMENTS = ['all', 'bullish', 'bearish', 'neutral'] as const type SentimentFilter = (typeof SENTIMENTS)[number] type SignalFilter = 'all' | 'actionable' | 'buy' | 'short' interface TrumpSignalPageProps { initialPosts?: TrumpPost[] | null } export default function TrumpSignalPage({ initialPosts = null }: TrumpSignalPageProps) { const locale = useLocale() const isZh = false // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json const [posts, setPosts] = useState(initialPosts ?? []) const [loading, setLoading] = useState(initialPosts === null) const [loadErr, setLoadErr] = useState('') const [sentFilter, setSentFilter] = useState('all') const [sigFilter, setSigFilter] = useState('all') useEffect(() => { swrFetch( 'posts-500', 3 * 60_000, // 3 min TTL () => getPosts(500, 1), fresh => setPosts(fresh), // background revalidation callback ) .then(p => { setPosts(p); setLoadErr('') }) .catch(e => setLoadErr(e instanceof Error ? e.message : (isZh ? '帖子加载失败' : 'Failed to load posts'))) .finally(() => setLoading(false)) }, [isZh]) const trumpPosts = useMemo( () => posts.filter(p => (p.source || '') === 'truth'), [posts], ) const filtered = useMemo(() => trumpPosts.filter(p => { if (sentFilter !== 'all' && p.sentiment !== sentFilter) return false if (sigFilter === 'actionable' && p.signal !== 'buy' && p.signal !== 'short') return false if (sigFilter === 'buy' && p.signal !== 'buy') return false if (sigFilter === 'short' && p.signal !== 'short') return false return true }), [trumpPosts, sentFilter, sigFilter]) const sigCounts = useMemo(() => ({ all: trumpPosts.length, actionable: trumpPosts.filter(p => p.signal === 'buy' || p.signal === 'short').length, buy: trumpPosts.filter(p => p.signal === 'buy').length, short: trumpPosts.filter(p => p.signal === 'short').length, }), [trumpPosts]) const signalLabels: Record = { all: isZh ? '全部' : 'All', actionable: isZh ? '可执行' : 'Actionable', buy: isZh ? '做多' : 'Buy', short: isZh ? '做空' : 'Short', } const sentimentLabels: Record = { all: isZh ? '全部' : 'All', bullish: isZh ? '看多' : 'Bullish', bearish: isZh ? '看空' : 'Bearish', neutral: isZh ? '中性' : 'Neutral', } return (

{isZh ? '① Trump 信号' : '① Trump Signal'}

{`Event-driven scalp · ${sigCounts.actionable} actionable · ${trumpPosts.length} posts`}

Live
This engine watches Trump Truth Social in real time, classifies each post, and only opens trades on high-confidence market-moving events. It is built for tight risk, short holds, and a 12-hour cooldown between entries.
{([ { key: 'all' }, { key: 'actionable' }, { key: 'buy' }, { key: 'short' }, ] as const).map(f => ( ))}
{SENTIMENTS.map(f => ( ))}
{loading && } {!loading && loadErr && (
⚠️ {`Couldn’t load signals — ${loadErr}`}
)} {!loading && !loadErr && filtered.length === 0 && (
No Trump signals match the current filter.
)} {!loading && filtered.length > 0 && (
{filtered.map(p => )}
)}
) } function TrumpSkeleton() { return (
{Array.from({ length: 6 }).map((_, i) => (
))}
) }