Files
trumpsignal-frontend/app/[locale]/archive/ArchivePageClient.tsx
T
k 9e0f6554cb copy: tighten Trump / Archive / Case Studies / Glossary / Methodology
Trump:
- PageHint: "move price" → "move the market"
- Filter hints: "verdict is long/short BTC" → "scored as a long/short signal"

Archive:
- PageHint: "Historical fires from old scanner experiments" →
  "Signals from retired scanner experiments … Read-only"

Case Studies:
- heroSubtitle: "worth studying" → "— documented."
- intro: remove redundant "is here to" phrasing
- footer: "signal stack" → "each signal engine"; "return promises" → "return forecasts"

Glossary:
- heroSubtitle: "The precise meaning of every key entity and term on the platform"
  → "Every term on the platform, defined precisely."
- intro: remove internal LLM-indexing rationale; rewrite for users

Methodology:
- heroSubtitle: "from raw input to trading decision"
  → "From raw data to trade decision — how each engine actually works."

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 12:16:09 +08:00

122 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import { useState, useEffect, useMemo } from 'react'
import { useLocale } from 'next-intl'
import type { TrumpPost } from '@/types'
import { getPosts } from '@/lib/api'
import PostRow from '@/components/dashboard/PostCards'
import PageHint from '@/components/ui/PageHint'
import Pagination from '@/components/ui/Pagination'
const ARCHIVE_PAGE_SIZE = 30
const LIVE_SOURCES = new Set([
'truth',
'btc_bottom_reversal',
'funding_reversal',
'kol_divergence',
])
/**
* Archive — legacy / test signals (rsi_reversal, sma_reclaim, breakout,
* test, phase1…). NOT a live system. Kept only so old data is inspectable.
*/
export default function ArchivePageClient() {
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<TrumpPost[]>([])
const [loading, setLoading] = useState(true)
const [loadErr, setLoadErr] = useState('')
const [src, setSrc] = useState<string>('all')
const [archivePage, setArchivePage] = useState(1)
useEffect(() => {
getPosts(500, 1)
.then(p => { setPosts(p); setLoadErr('') })
.catch(e => setLoadErr(e instanceof Error ? e.message : (isZh ? '历史归档加载失败' : 'Failed to load archive')))
.finally(() => setLoading(false))
}, [isZh])
// Archive = legacy / test data only. Exclude every live signal source so
// active modules don't leak in here as users explore old experiments. Keep
// this set in sync with sources emitted by app/services/scanners/*.
const archivePosts = useMemo(
() => posts.filter(p => !LIVE_SOURCES.has(p.source || '')),
[posts],
)
const sources = useMemo(() => {
const m: Record<string, number> = {}
for (const p of archivePosts) m[p.source || '?'] = (m[p.source || '?'] || 0) + 1
return Object.entries(m).sort((a, b) => b[1] - a[1])
}, [archivePosts])
const filtered = useMemo(
() => src === 'all' ? archivePosts : archivePosts.filter(p => p.source === src),
[archivePosts, src],
)
const archiveTotalPages = Math.max(1, Math.ceil(filtered.length / ARCHIVE_PAGE_SIZE))
const archiveSafePage = Math.min(archivePage, archiveTotalPages)
const archivePageItems = filtered.slice((archiveSafePage - 1) * ARCHIVE_PAGE_SIZE, archiveSafePage * ARCHIVE_PAGE_SIZE)
return (
<div className="page">
<div className="page-head">
<div>
<h1 className="page-title">Archive</h1>
<PageHint count={`${archivePosts.length} legacy posts`}>
Signals from retired scanner experiments
(rsi_reversal, sma_reclaim, breakout, test/phase1). Read-only
the bot no longer acts on any of these.
</PageHint>
</div>
</div>
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 12 }}>
{[['all', archivePosts.length] as [string, number], ...sources].map(([s, n]) => (
<button
key={s}
onClick={() => { setSrc(s); setArchivePage(1) }}
style={{
padding: '4px 10px', borderRadius: 6, border: '1px solid var(--line)',
background: src === s ? 'var(--ink)' : 'transparent',
color: src === s ? 'var(--bg)' : 'var(--ink-3)',
fontSize: 11, cursor: 'pointer', fontWeight: src === s ? 600 : 400,
}}
>
{s} <span style={{ opacity: 0.6 }}>{n}</span>
</button>
))}
</div>
{loading && <div style={{ textAlign: 'center', padding: 60, color: 'var(--ink-3)' }}>{isZh ? '加载中…' : 'Loading…'}</div>}
{!loading && loadErr && (
<div className="card" style={{ padding: 24, textAlign: 'center', color: 'var(--down)' }}>
{isZh ? `无法加载归档:${loadErr}` : `Couldn't load archive — ${loadErr}`}
<div style={{ marginTop: 10 }}>
<button className="btn ghost" style={{ fontSize: 12, padding: '6px 14px' }}
onClick={() => location.reload()}>{isZh ? '重试' : 'Retry'}</button>
</div>
</div>
)}
{!loading && !loadErr && filtered.length === 0 && (
<div className="card" style={{ padding: 48, textAlign: 'center', color: 'var(--ink-3)' }}>
{isZh ? '没有可显示的历史信号。' : 'No archived signals.'}
</div>
)}
{!loading && archivePageItems.length > 0 && (
<>
<div className="post-stream">
{archivePageItems.map(p => <PostRow key={p.id} post={p} />)}
</div>
<Pagination
page={archiveSafePage}
total={archiveTotalPages}
count={filtered.length}
pageSize={ARCHIVE_PAGE_SIZE}
onChange={setArchivePage}
/>
</>
)}
</div>
)
}