From 95486173f714e097cbeb4e40b9f107d9e1092430 Mon Sep 17 00:00:00 2001 From: tinkle-community Date: Sat, 17 Jan 2026 23:37:12 +0800 Subject: [PATCH] feat(web): add Data page with embedded nofxos.ai dashboard - Add Data navigation item before Market in header - Create DataPage component with iframe embedding - Publicly accessible without login required --- web/src/App.tsx | 31 +++++++++++++++++++++++++++++++ web/src/components/HeaderBar.tsx | 3 +++ web/src/pages/DataPage.tsx | 16 ++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 web/src/pages/DataPage.tsx diff --git a/web/src/App.tsx b/web/src/App.tsx index 0c3c050a..1304d60a 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -14,6 +14,7 @@ import { FAQPage } from './pages/FAQPage' import { StrategyStudioPage } from './pages/StrategyStudioPage' import { DebateArenaPage } from './pages/DebateArenaPage' import { StrategyMarketPage } from './pages/StrategyMarketPage' +import { DataPage } from './pages/DataPage' import { LoginRequiredOverlay } from './components/LoginRequiredOverlay' import HeaderBar from './components/HeaderBar' import { LanguageProvider, useLanguage } from './contexts/LanguageContext' @@ -41,6 +42,7 @@ type Page = | 'backtest' | 'strategy' | 'strategy-market' + | 'data' | 'debate' | 'faq' | 'login' @@ -68,6 +70,7 @@ function App() { if (path === '/backtest' || hash === 'backtest') return 'backtest' if (path === '/strategy' || hash === 'strategy') return 'strategy' if (path === '/strategy-market' || hash === 'strategy-market') return 'strategy-market' + if (path === '/data' || hash === 'data') return 'data' if (path === '/debate' || hash === 'debate') return 'debate' if (path === '/dashboard' || hash === 'trader' || hash === 'details') return 'trader' @@ -88,6 +91,7 @@ function App() { const pathMap: Record = { 'competition': '/competition', 'strategy-market': '/strategy-market', + 'data': '/data', 'traders': '/traders', 'trader': '/dashboard', 'backtest': '/backtest', @@ -152,6 +156,8 @@ function App() { setCurrentPage('strategy') } else if (path === '/strategy-market' || hash === 'strategy-market') { setCurrentPage('strategy-market') + } else if (path === '/data' || hash === 'data') { + setCurrentPage('data') } else if (path === '/debate' || hash === 'debate') { setCurrentPage('debate') } else if ( @@ -370,6 +376,29 @@ function App() { if (route === '/reset-password') { return } + // Data page - publicly accessible with embedded dashboard + if (route === '/data') { + return ( +
+ +
+ +
+
+ ) + } // Show landing page for root route if (route === '/' || route === '') { return @@ -408,6 +437,8 @@ function App() { > {currentPage === 'competition' ? ( + ) : currentPage === 'data' ? ( + ) : currentPage === 'strategy-market' ? ( ) : currentPage === 'traders' ? ( diff --git a/web/src/components/HeaderBar.tsx b/web/src/components/HeaderBar.tsx index e7252a0c..058d9186 100644 --- a/web/src/components/HeaderBar.tsx +++ b/web/src/components/HeaderBar.tsx @@ -13,6 +13,7 @@ type Page = | 'backtest' | 'strategy' | 'strategy-market' + | 'data' | 'debate' | 'faq' | 'login' @@ -98,6 +99,7 @@ export default function HeaderBar({ {(() => { // Define all navigation tabs const navTabs: { page: Page; path: string; label: string; requiresAuth: boolean }[] = [ + { page: 'data', path: '/data', label: language === 'zh' ? '数据' : 'Data', requiresAuth: false }, { page: 'strategy-market', path: '/strategy-market', label: language === 'zh' ? '策略市场' : 'Market', requiresAuth: true }, { page: 'traders', path: '/traders', label: t('configNav', language), requiresAuth: true }, { page: 'trader', path: '/dashboard', label: t('dashboardNav', language), requiresAuth: true }, @@ -327,6 +329,7 @@ export default function HeaderBar({
{(() => { const navTabs: { page: Page; path: string; label: string; requiresAuth: boolean }[] = [ + { page: 'data', path: '/data', label: language === 'zh' ? '数据' : 'Data', requiresAuth: false }, { page: 'strategy-market', path: '/strategy-market', label: language === 'zh' ? '策略市场' : 'Market', requiresAuth: true }, { page: 'traders', path: '/traders', label: t('configNav', language), requiresAuth: true }, { page: 'trader', path: '/dashboard', label: t('dashboardNav', language), requiresAuth: true }, diff --git a/web/src/pages/DataPage.tsx b/web/src/pages/DataPage.tsx new file mode 100644 index 00000000..096fb6e5 --- /dev/null +++ b/web/src/pages/DataPage.tsx @@ -0,0 +1,16 @@ +import { useLanguage } from '../contexts/LanguageContext' + +export function DataPage() { + const { language } = useLanguage() + + return ( +
+