Skip to content

Conversation

@0xEmberZz
Copy link
Contributor

Pull Request - Frontend | 前端 PR

💡 提示 Tip: 推荐 PR 标题格式 type(scope): description

建议标题: fix(ui): add empty state for dashboard when no traders configured


📝 Description | 描述

English:
This PR fixes issue #449 where new users accessing the dashboard without configuring any traders would see a perpetual loading skeleton with no guidance. Now, users see a friendly empty state with clear instructions on what to do next.

中文:
此 PR 修复了 issue #449,新用户在未配置任何交易员的情况下访问看板页面时,会看到持续的加载动画而没有任何引导。现在,用户会看到友好的空状态提示,并清楚了解下一步该做什么。


🎯 Type of Change | 变更类型

  • 🐛 Bug fix | 修复 Bug
  • ✨ New feature | 新功能
  • 💥 Breaking change | 破坏性变更
  • 🎨 Code style update | 代码样式更新
  • ♻️ Refactoring | 重构
  • ⚡ Performance improvement | 性能优化

🔗 Related Issues | 相关 Issue


📋 Changes Made | 具体变更

English:

1. Updated TraderDetailsPage Component

File: src/App.tsx

  • Distinguish Loading vs Empty States:

    • When traders is undefined: Show loading skeleton (data is being fetched)
    • When traders is empty array []: Show empty state UI (no traders configured)
    • When traders has items but !selectedTrader: Show loading skeleton (trader data loading)
  • Added Empty State UI:

    • Centered layout with minimum 60vh height
    • Robot icon with brand colors (gold gradient border)
    • Clear title: "No Traders Configured"
    • Helpful description: "You haven't created any AI traders yet..."
    • Prominent CTA button: "Go to Traders Page"
    • Responsive design for all screen sizes
  • Added Navigation Callback:

    • New prop onNavigateToTraders for empty state button
    • Navigates to /traders page when clicked
    • Updates both URL and internal routing state

2. Added I18n Translations

File: src/i18n/translations.ts

English translations:

  • dashboardEmptyTitle: "No Traders Configured"
  • dashboardEmptyDescription: "You haven't created any AI traders yet. Create your first trader to start automated trading."
  • goToTradersPage: "Go to Traders Page"

Chinese translations:

  • dashboardEmptyTitle: "暂无交易员"
  • dashboardEmptyDescription: "您还未创建任何AI交易员,创建您的第一个交易员以开始自动化交易。"
  • goToTradersPage: "前往交易员页面"

中文:

1. 更新 TraderDetailsPage 组件

文件: src/App.tsx

  • 区分加载和空状态:

    • tradersundefined:显示加载骨架屏(数据正在获取中)
    • traders 是空数组 []:显示空状态 UI(未配置交易员)
    • traders 有数据但 !selectedTrader:显示加载骨架屏(交易员数据加载中)
  • 添加空状态 UI:

    • 居中布局,最小高度 60vh
    • 机器人图标,品牌色(金色渐变边框)
    • 清晰的标题:"暂无交易员"
    • 有用的描述:"您还未创建任何AI交易员..."
    • 醒目的 CTA 按钮:"前往交易员页面"
    • 响应式设计,适配所有屏幕尺寸
  • 添加导航回调:

    • 新增 prop onNavigateToTraders 用于空状态按钮
    • 点击时导航到 /traders 页面
    • 更新 URL 和内部路由状态

2. 添加国际化翻译

文件: src/i18n/translations.ts

英文翻译:

  • dashboardEmptyTitle: "No Traders Configured"
  • dashboardEmptyDescription: "You haven't created any AI traders yet. Create your first trader to start automated trading."
  • goToTradersPage: "Go to Traders Page"

中文翻译:

  • dashboardEmptyTitle: "暂无交易员"
  • dashboardEmptyDescription: "您还未创建任何AI交易员,创建您的第一个交易员以开始自动化交易。"
  • goToTradersPage: "前往交易员页面"

📸 Screenshots / Demo | 截图/演示

Before | 变更前:

After | 变更后:

Empty State UI:

  • Clean, centered layout
  • Gold robot icon with gradient border
  • Clear messaging: "No Traders Configured"
  • Helpful description explaining what to do
  • Prominent "Go to Traders Page" button
  • Professional and friendly appearance

Loading State (unchanged):

  • Shows skeleton when data is loading
  • Distinguishes from "no data" state

🧪 Testing | 测试

Test Environment | 测试环境

  • OS | 操作系统: macOS Darwin 25.0.0
  • Node Version | Node 版本: v18+
  • Browser(s) | 浏览器: Chrome, Safari

Manual Testing | 手动测试

  • Tested in development mode | 开发模式测试通过
  • Tested production build | 生产构建测试通过
  • Tested on multiple browsers | 多浏览器测试通过 (Recommended)
  • Tested responsive design | 响应式设计测试通过
  • Verified no existing functionality broke | 确认没有破坏现有功能

Test Scenarios | 测试场景

Scenario 1: New User (No Traders)

  1. Create new account
  2. Navigate to /dashboard
  3. Expected: See empty state UI with CTA button
  4. Click "Go to Traders Page"
  5. Expected: Navigate to /traders page
  6. Result: Works as expected

Scenario 2: Existing User (Has Traders)

  1. User with configured traders
  2. Navigate to /dashboard
  3. Expected: See normal dashboard with trader data
  4. Result: Works as expected

Scenario 3: Loading State

  1. Clear cache and reload
  2. Navigate to /dashboard immediately
  3. Expected: See loading skeleton while data loads
  4. After data loads: See either empty state (no traders) or dashboard (has traders)
  5. Result: Works as expected

Scenario 4: Language Switching

  1. View empty state in English
  2. Switch to Chinese
  3. Expected: All text updates to Chinese
  4. Result: Works as expected

🌐 Internationalization | 国际化

  • All user-facing text supports i18n | 所有面向用户的文本支持国际化
  • Both English and Chinese versions provided | 提供了中英文版本
  • N/A | 不适用

Translation Keys Added:

{
  dashboardEmptyTitle: string,
  dashboardEmptyDescription: string,
  goToTradersPage: string
}

✅ Checklist | 检查清单

Code Quality | 代码质量

  • Code follows project style | 代码遵循项目风格
  • Self-review completed | 已完成代码自查
  • Comments added for complex logic | 已添加必要注释
  • Code builds successfully | 代码构建成功 (npm run build)
  • Ran npm run lint | 已运行 npm run lint (via husky pre-commit)
  • No console errors or warnings | 无控制台错误或警告

Testing | 测试

  • Component tests added/updated | 已添加/更新组件测试 (N/A for this fix)
  • Tests pass locally | 测试在本地通过

Documentation | 文档

  • Updated relevant documentation | 已更新相关文档
  • Updated type definitions (TypeScript) | 已更新类型定义
  • Added JSDoc comments where necessary | 已添加 JSDoc 注释

Git

  • Commits follow conventional format | 提交遵循 Conventional Commits 格式
  • Rebased on latest dev branch | 已 rebase 到最新 dev 分支
  • No merge conflicts | 无合并冲突

📚 Additional Notes | 补充说明

English:

This is a straightforward UX improvement fix that addresses a common pain point for new users. The solution is clean, maintainable, and follows existing code patterns in the application.

Key Design Decisions:

  1. State Distinction: Used the traders array state to determine:

    • undefined = still loading
    • [] = loaded but empty
    • [...] = has data
  2. UI Pattern: Followed common empty state patterns:

    • Icon + Title + Description + CTA
    • Centered layout
    • Brand-consistent colors
    • Clear call-to-action
  3. I18n First: All new user-facing text is internationalized from the start

  4. Navigation: Reused existing navigation patterns for consistency

中文:

这是一个直接的用户体验改进修复,解决了新用户的常见痛点。解决方案简洁、易维护,并遵循应用程序中的现有代码模式。

关键设计决策:

  1. 状态区分: 使用 traders 数组状态判断:

    • undefined = 仍在加载
    • [] = 已加载但为空
    • [...] = 有数据
  2. UI 模式: 遵循常见的空状态模式:

    • 图标 + 标题 + 描述 + CTA
    • 居中布局
    • 品牌一致的颜色
    • 清晰的行动号召
  3. 优先国际化: 所有新的面向用户的文本从一开始就国际化

  4. 导航: 重用现有导航模式以保持一致性


By submitting this PR, I confirm | 提交此 PR,我确认:

  • I have read the Contributing Guidelines | 已阅读贡献指南
  • I agree to the Code of Conduct | 同意行为准则
  • My contribution is licensed under AGPL-3.0 | 贡献遵循 AGPL-3.0 许可证

🌟 Thank you for your contribution! | 感谢你的贡献!

0xEmberZz and others added 5 commits November 7, 2025 17:05
Fixes NoFxAiOS#449

## Problem
When users first register and access the dashboard without configuring any traders,
the page shows a perpetual loading skeleton with no guidance, resulting in poor UX.

## Solution
- Distinguish between "loading" and "empty" states
- Show friendly empty state when traders array is empty
- Add i18n support for empty state messages (English & Chinese)
- Provide clear CTA button to navigate to traders configuration page

## Changes
1. **Updated TraderDetailsPage component** (App.tsx)
   - Added `onNavigateToTraders` callback prop
   - Check if `traders` array is loaded and empty
   - Show empty state UI with icon, title, description, and CTA button
   - Keep loading skeleton for actual loading states

2. **Added i18n translations** (translations.ts)
   - `dashboardEmptyTitle`: "No Traders Configured" / "暂无交易员"
   - `dashboardEmptyDescription`: Helpful guidance text
   - `goToTradersPage`: "Go to Traders Page" / "前往交易员页面"

3. **Empty State UI Features**
   - Centered layout with icon and text
   - Brand-colored robot icon
   - Clear messaging about what to do next
   - Prominent CTA button with gradient style
   - Responsive design

## Testing
- ✅ Build passes
- ✅ TypeScript compilation succeeds
- ✅ Loading skeleton shows during initial load
- ✅ Empty state shows when no traders configured
- ✅ Normal dashboard shows when traders exist
- ✅ CTA button navigates to traders page

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
## Problem
When backend API returns 404 or other errors (e.g., backend not running),
the dashboard shows perpetual loading skeleton because traders data remains
undefined and there's no error handling.

## Solution
- Added error state handling from useSWR
- When API error occurs, show empty state UI instead of loading skeleton
- Set shouldRetryOnError: false to avoid infinite retries when backend is down
- Provide clear guidance to users even when backend is unavailable

## Changes
1. **Updated useSWR call** (App.tsx)
   - Extract error state: const { data: traders, error: tradersError }
   - Add shouldRetryOnError: false option
   - Prevents infinite retry loops when backend is unavailable

2. **Updated TraderDetailsPage component**
   - Added tradersError prop and type definition
   - Check tradersError first before checking empty state
   - Show empty state UI when API fails (likely backend not running)
   - Provides same friendly UI whether backend is down or no traders configured

## Testing
- ✅ Build passes
- ✅ TypeScript compilation succeeds
- ✅ Shows loading skeleton initially
- ✅ Shows empty state when API fails (404)
- ✅ Shows empty state when traders array is empty
- ✅ Shows normal dashboard when traders exist

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Replaced the 📡 emoji in the Signal Source button with a Radio icon
from lucide-react to fix a white square appearing in the bottom-right
corner on hover. Emojis can cause rendering artifacts when combined
with CSS transforms like hover:scale-105. This change makes the button
consistent with other buttons that use icon components.

Changes:
- Added Radio icon import from lucide-react
- Replaced emoji with <Radio> component in Signal Source button
- Added flex layout and gap for proper icon spacing
- Removed emojis from warning text and modal title for consistency

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Changed button container overflow from 'overflow-x-auto' to
'overflow-hidden' to prevent a scrollbar from appearing when
buttons scale up on hover. The scrollbar was appearing as a
white square in the corner when hovering over buttons.

Since the container uses flex-wrap on mobile and only has 4
buttons, overflow-hidden is safe and won't cut off content.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@github-actions
Copy link

github-actions bot commented Nov 7, 2025

🤖 Advisory Check Results

These are advisory checks to help improve code quality. They won't block your PR from being merged.

📋 PR Information

Title Format: ⚠️ Suggestion - Consider using type(scope): description

Recommended format

Valid types: feat, fix, docs, style, refactor, perf, test, chore, ci, security, build

Examples:

  • feat(trader): add new trading strategy
  • fix(api): resolve authentication issue
  • docs: update README

PR Size: 🟢 Small (146 lines: +140 -6)

🔧 Backend Checks

Go Formatting: ✅ Good
Go Vet: ✅ Good
Tests: ✅ Passed

Fix locally:

go fmt ./...      # Format code
go vet ./...      # Check for issues
go test ./...     # Run tests

⚛️ Frontend Checks

Build & Type Check: ✅ Success

Fix locally:

cd web
npm run build  # Test build (includes type checking)

📖 Resources

Questions? Feel free to ask in the comments! 🙏


These checks are advisory and won't block your PR from being merged. This comment is automatically generated from pr-checks-run.yml.

@hzb1115
Copy link
Member

hzb1115 commented Nov 8, 2025

Could you pls add some snapshots?

@xqliu
Copy link
Contributor

xqliu commented Nov 8, 2025

代码审查报告 - PR #709

审查结果:✅ 通过

业务层面审查

✅ 需求验证

  • 需求明确:Dashboard 空状态时显示友好提示
  • 需求合理:区分"API失败"和"无交易员"两种场景
  • 用户体验提升:提供明确的CTA按钮引导用户

✅ 功能完整性

  • API错误时显示空状态(后端未运行)
  • 交易员列表为空时显示空状态
  • 提供导航按钮跳转到交易员页面
  • 多语言支持(i18n)

技术层面审查

✅ 实现合理性

  • 错误处理:通过 tradersError 检测API失败
  • 状态区分tradersError vs traders.length === 0
  • 导航逻辑:使用 window.history.pushState + state更新

✅ UI/UX设计

  • 视觉层次清晰(图标 → 标题 → 描述 → 按钮)
  • 颜色符合Binance设计规范(金色主题)
  • 交互反馈(hover缩放、active缩放)

✅ 性能优化

  • 重要改进shouldRetryOnError: false
    • 避免后端未运行时无限重试
    • 减少不必要的网络请求
    • 提升用户体验(不会一直loading)

E2E 验证报告

✅ 用户流程验证

场景1:后端未运行

步骤1:用户登录成功
步骤2:useSWR 调用 api.getTraders() 失败
步骤3:tradersError 有值
预期:显示空状态 + "前往交易员页面"按钮
实际:✅ 符合预期

场景2:无交易员

步骤1:用户登录成功
步骤2:api.getTraders() 成功返回 []
步骤3:traders.length === 0
预期:显示空状态 + "前往交易员页面"按钮
实际:✅ 符合预期

场景3:点击CTA按钮

步骤1:用户点击"前往交易员页面"
步骤2:onNavigateToTraders 触发
步骤3:window.history.pushState + setRoute('/traders')
预期:导航到交易员页面
实际:✅ 符合预期(需验证路由正常工作)

✅ 导航验证

  • onClick 处理器存在
  • window.history.pushState 更新浏览器URL
  • setRoute 更新应用状态
  • setCurrentPage 更新当前页面

🟡 改进建议(非 BLOCKING)

建议1:使用 React Router 导航(如果项目有)

当前:手动 window.history.pushState + state更新
建议:如果项目使用 React Router,应使用 navigate('/traders')

import { useNavigate } from 'react-router-dom'

const navigate = useNavigate()

<button onClick={() => navigate('/traders')}>
  {t('goToTradersPage', language)}
</button>

理由

  • 更符合 React 生态
  • 自动处理状态更新
  • 避免手动同步多个状态

建议2:空状态组件复用性

当前:两个空状态的代码几乎相同(重复代码)
建议:提取为独立组件

const EmptyState = ({ 
  title, 
  description, 
  onAction 
}: { 
  title: string
  description: string
  onAction: () => void
}) => (
  <div className="flex items-center justify-center min-h-[60vh]">
    {/* 空状态UI */}
  </div>
)

// 使用
if (tradersError) {
  return <EmptyState 
    title={t('dashboardEmptyTitle', language)}
    description={t('dashboardEmptyDescription', language)}
    onAction={onNavigateToTraders}
  />
}

建议3:区分错误类型

当前:所有 tradersError 都显示相同空状态
建议:区分网络错误、认证错误等

if (tradersError) {
  // 网络错误
  if (tradersError.message.includes('Network')) {
    return <EmptyState title="网络连接失败" ... />
  }
  
  // 认证错误
  if (tradersError.message.includes('401')) {
    return <EmptyState title="认证失败" ... />
  }
  
  // 其他错误
  return <EmptyState title="无法加载数据" ... />
}

建议4:添加重试按钮(对于错误场景)

if (tradersError) {
  return (
    <EmptyState 
      title={t('dashboardErrorTitle', language)}
      description={t('dashboardErrorDescription', language)}
      actions={[
        {
          label: t('retry', language),
          onClick: () => mutate('traders'), // 重新请求
        },
        {
          label: t('goToTradersPage', language),
          onClick: onNavigateToTraders,
        },
      ]}
    />
  )
}

多语言验证

✅ i18n 集成

  • 添加了3个翻译key:
    • dashboardEmptyTitle
    • dashboardEmptyDescription
    • goToTradersPage
  • 中英文翻译都已提供

⚠️ 建议验证翻译内容

请确认 translations.ts 中的翻译是否准确:

// 建议检查
dashboardEmptyTitle: {
  zh: "暂无数据", // 是否应该更具体?如"暂无交易员"
  en: "No Data"
}

代码质量审查

✅ 代码风格

  • 符合 React/TypeScript 规范
  • 组件拆分合理
  • Props 类型定义清晰

⚠️ 代码重复

  • 两个空状态的 JSX 代码完全相同(约120行重复)
  • 建议提取为独立组件

✅ 性能

  • shouldRetryOnError: false 避免无限重试
  • 条件渲染合理(早期return)

安全验证

✅ XSS 防护

  • 使用 t() 函数获取翻译,无直接HTML注入
  • 使用 React 组件,自动转义

✅ 导航安全

  • 导航路径硬编码 '/traders',无用户输入

总结

这是一个优质的用户体验改进 PR

优点

  1. ✅ 解决实际痛点(空状态不友好)
  2. ✅ 错误处理完善(区分API失败和数据为空)
  3. ✅ 性能优化(shouldRetryOnError: false)
  4. ✅ UI设计专业(符合Binance设计规范)
  5. ✅ 多语言支持

改进空间(非 BLOCKING)

  1. ⚠️ 代码重复(两个空状态JSX相同)
  2. ⚠️ 导航方式(建议使用React Router)
  3. ⚠️ 错误类型区分(网络错误 vs 认证错误)
  4. ⚠️ 添加重试按钮(错误场景)

审查结论:✅ 通过,建议合并

后续优化建议

  • 提取空状态为独立组件
  • 添加重试功能
  • 区分不同错误类型的提示

@0xEmberZz
Copy link
Contributor Author

image image

Copy link
Member

@hzb1115 hzb1115 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tinkle-community tinkle-community merged commit a4d3cb4 into NoFxAiOS:dev Nov 9, 2025
15 checks passed
bebest2010 pushed a commit to bebest2010/nofx that referenced this pull request Nov 18, 2025
tinkle-community pushed a commit that referenced this pull request Nov 26, 2025
tinkle-community pushed a commit that referenced this pull request Nov 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] 用户刚注册还未配置时,看板一直加载态,可以加一些提示文案

4 participants