mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-16 17:12:25 +08:00
feat: cream terminal redesign, English-only UI, autopilot launch fixes
- Redesign dashboard into a cream-paper + vermilion IBM Plex Mono terminal (live L2 order book, cost/liq map, WS K-line, signal matrix, orchestration topology, risk radar, execution log, current positions, equity curve) - Convert all user-facing UI and backend strings/prompts from Chinese to English (multi-language retained, default English) - Add /api/statistics/full endpoint + full-stats frontend wiring - Fix Autopilot launch: reuse the existing trader instead of creating duplicates (eliminates repeat ~35s create cost and stale-trader 404s); launch sends 5m scan interval - Fix unreadable toasts: cream theme with high-contrast text + per-type accent - Silence background dashboard polls (getTraderConfig) to stop error-toast spam
This commit is contained in:
@@ -25,7 +25,7 @@ import { BeginnerOnboardingPage } from '../pages/BeginnerOnboardingPage'
|
||||
import { DataPage } from '../pages/DataPage'
|
||||
import { SettingsPage } from '../pages/SettingsPage'
|
||||
import { StrategyStudioPage } from '../pages/StrategyStudioPage'
|
||||
import { TraderDashboardPage } from '../pages/TraderDashboardPage'
|
||||
import { TerminalDashboard } from '../components/terminal/TerminalDashboard'
|
||||
import { useAuth } from '../contexts/AuthContext'
|
||||
import { useLanguage } from '../contexts/LanguageContext'
|
||||
import { useSystemConfig } from '../hooks/useSystemConfig'
|
||||
@@ -35,9 +35,7 @@ import { getUserMode } from '../lib/onboarding'
|
||||
import type {
|
||||
AccountInfo,
|
||||
DecisionRecord,
|
||||
Exchange,
|
||||
Position,
|
||||
Statistics,
|
||||
SystemStatus,
|
||||
TraderInfo,
|
||||
} from '../types'
|
||||
@@ -73,7 +71,7 @@ function LoadingScreen() {
|
||||
return (
|
||||
<div
|
||||
className="min-h-screen flex items-center justify-center"
|
||||
style={{ background: '#0B0E11' }}
|
||||
style={{ background: '#F1ECE2' }}
|
||||
>
|
||||
<div className="text-center">
|
||||
<img
|
||||
@@ -81,7 +79,7 @@ function LoadingScreen() {
|
||||
alt="NoFx Logo"
|
||||
className="w-16 h-16 mx-auto mb-4 animate-pulse"
|
||||
/>
|
||||
<p style={{ color: '#EAECEF' }}>{t('loading', language)}</p>
|
||||
<p style={{ color: '#1A1813' }}>{t('loading', language)}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -160,7 +158,7 @@ function AppChrome({
|
||||
return (
|
||||
<div
|
||||
className="min-h-screen"
|
||||
style={{ background: '#0B0E11', color: '#EAECEF' }}
|
||||
style={{ background: '#F1ECE2', color: '#1A1813' }}
|
||||
>
|
||||
<HeaderBar
|
||||
isLoggedIn={!!user}
|
||||
@@ -226,14 +224,13 @@ function TradersRoute({
|
||||
}
|
||||
|
||||
function DashboardRoute() {
|
||||
const { language } = useLanguage()
|
||||
const { user, token } = useAuth()
|
||||
const navigate = useNavigate()
|
||||
const [searchParams] = useSearchParams()
|
||||
const selectedTraderSlug = searchParams.get('trader') || undefined
|
||||
const [selectedTraderId, setSelectedTraderId] = useState<string | undefined>()
|
||||
const [lastUpdate, setLastUpdate] = useState<string>('--:--:--')
|
||||
const [decisionsLimit, setDecisionsLimit] = useState(5)
|
||||
const [, setLastUpdate] = useState<string>('--:--:--')
|
||||
const [decisionsLimit] = useState(5)
|
||||
const [accountPollOff, setAccountPollOff] = useState(false)
|
||||
const [positionsPollOff, setPositionsPollOff] = useState(false)
|
||||
const [decisionsPollOff, setDecisionsPollOff] = useState(false)
|
||||
@@ -244,7 +241,7 @@ function DashboardRoute() {
|
||||
setDecisionsPollOff(false)
|
||||
}, [selectedTraderId])
|
||||
|
||||
const { data: traders, error: tradersError } = useSWR<TraderInfo[]>(
|
||||
const { data: traders } = useSWR<TraderInfo[]>(
|
||||
user && token ? 'traders-dashboard' : null,
|
||||
() => api.getTraders(true),
|
||||
{
|
||||
@@ -253,15 +250,6 @@ function DashboardRoute() {
|
||||
}
|
||||
)
|
||||
|
||||
const { data: exchanges } = useSWR<Exchange[]>(
|
||||
user && token ? 'exchanges-dashboard' : null,
|
||||
api.getExchangeConfigs,
|
||||
{
|
||||
refreshInterval: 60000,
|
||||
shouldRetryOnError: false,
|
||||
}
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!traders || traders.length === 0) {
|
||||
return
|
||||
@@ -359,16 +347,6 @@ function DashboardRoute() {
|
||||
}
|
||||
)
|
||||
|
||||
const { data: stats } = useSWR<Statistics>(
|
||||
selectedTraderId ? `statistics-${selectedTraderId}` : null,
|
||||
() => api.getStatistics(selectedTraderId, true),
|
||||
{
|
||||
refreshInterval: 30000,
|
||||
revalidateOnFocus: false,
|
||||
dedupingInterval: 20000,
|
||||
}
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (account) {
|
||||
setLastUpdate(new Date().toLocaleTimeString())
|
||||
@@ -381,22 +359,13 @@ function DashboardRoute() {
|
||||
|
||||
return (
|
||||
<AppChrome currentPage="trader" animateContent>
|
||||
<TraderDashboardPage
|
||||
<TerminalDashboard
|
||||
selectedTrader={selectedTrader}
|
||||
status={status}
|
||||
account={account}
|
||||
accountFailed={accountPollOff}
|
||||
positions={positions}
|
||||
positionsFailed={positionsPollOff}
|
||||
decisions={decisions}
|
||||
decisionsFailed={decisionsPollOff}
|
||||
decisionsLimit={decisionsLimit}
|
||||
onDecisionsLimitChange={setDecisionsLimit}
|
||||
stats={stats}
|
||||
lastUpdate={lastUpdate}
|
||||
language={language}
|
||||
traders={traders}
|
||||
tradersError={tradersError}
|
||||
selectedTraderId={selectedTraderId}
|
||||
onTraderSelect={(traderId) => {
|
||||
setSelectedTraderId(traderId)
|
||||
@@ -408,8 +377,6 @@ function DashboardRoute() {
|
||||
}
|
||||
)
|
||||
}}
|
||||
onNavigateToTraders={() => navigate(ROUTES.traders)}
|
||||
exchanges={exchanges}
|
||||
/>
|
||||
</AppChrome>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user