From 91fa594578d493fa9ae4f47096fb5feb9e05eb76 Mon Sep 17 00:00:00 2001 From: catlog22 Date: Wed, 4 Mar 2026 11:51:30 +0800 Subject: [PATCH] feat: Improve DynamicPipeline component with enhanced fallback UI and add localization for no stages message --- .../src/components/team/DynamicPipeline.tsx | 16 ++++++++++++---- ccw/frontend/src/locales/en/team.json | 3 ++- ccw/frontend/src/locales/zh/team.json | 3 ++- ccw/frontend/src/pages/TeamPage.tsx | 12 ++++++++---- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/ccw/frontend/src/components/team/DynamicPipeline.tsx b/ccw/frontend/src/components/team/DynamicPipeline.tsx index b7da23d0..1ebde5de 100644 --- a/ccw/frontend/src/components/team/DynamicPipeline.tsx +++ b/ccw/frontend/src/components/team/DynamicPipeline.tsx @@ -7,7 +7,6 @@ import { useIntl } from 'react-intl'; import { CheckCircle2, Circle, Loader2, Ban, SkipForward } from 'lucide-react'; import { Badge } from '@/components/ui/Badge'; import { cn } from '@/lib/utils'; -import { TeamPipeline } from './TeamPipeline'; import type { DynamicStage, DynamicStageStatus, PhaseInfo } from '@/types/team'; interface DynamicPipelineProps { @@ -70,9 +69,18 @@ function Arrow() { export function DynamicPipeline({ stages, phaseInfo }: DynamicPipelineProps) { const { formatMessage } = useIntl(); - // Fallback to static pipeline when no dynamic stages + // Fallback: empty state when no dynamic stages are available if (stages.length === 0) { - return ; + return ( +
+

+ {formatMessage({ id: 'team.pipeline.title' })} +

+

+ {formatMessage({ id: 'team.pipeline.noStages' })} +

+
+ ); } return ( @@ -91,7 +99,7 @@ export function DynamicPipeline({ stages, phaseInfo }: DynamicPipelineProps) { {phaseInfo.currentStep && ( - {phaseInfo.currentStep} + {formatMessage({ id: 'team.coordinates.step' })}: {phaseInfo.currentStep} )} {phaseInfo.gapIteration > 0 && ( diff --git a/ccw/frontend/src/locales/en/team.json b/ccw/frontend/src/locales/en/team.json index e89fe97a..54102456 100644 --- a/ccw/frontend/src/locales/en/team.json +++ b/ccw/frontend/src/locales/en/team.json @@ -79,7 +79,8 @@ "inProgress": "In Progress", "pending": "Pending", "blocked": "Blocked", - "skipped": "Skipped" + "skipped": "Skipped", + "noStages": "No pipeline stages defined for this session" }, "coordinates": { "phase": "Phase", diff --git a/ccw/frontend/src/locales/zh/team.json b/ccw/frontend/src/locales/zh/team.json index 951d537a..c5a3c584 100644 --- a/ccw/frontend/src/locales/zh/team.json +++ b/ccw/frontend/src/locales/zh/team.json @@ -79,7 +79,8 @@ "inProgress": "进行中", "pending": "待处理", "blocked": "已阻塞", - "skipped": "已跳过" + "skipped": "已跳过", + "noStages": "此会话未定义流水线阶段" }, "coordinates": { "phase": "阶段", diff --git a/ccw/frontend/src/pages/TeamPage.tsx b/ccw/frontend/src/pages/TeamPage.tsx index d5ece343..e4cbd658 100644 --- a/ccw/frontend/src/pages/TeamPage.tsx +++ b/ccw/frontend/src/pages/TeamPage.tsx @@ -77,8 +77,8 @@ export function TeamPage() { [teamData?.role_state] ); - // List view - if (viewMode === 'list' || !selectedTeam) { + // List view (also fallback when selected team data is not available) + if (viewMode === 'list' || !selectedTeam || (viewMode === 'detail' && teams.length > 0 && !teamData)) { return (
@@ -163,11 +163,15 @@ export function TeamPage() { tabs={tabs} /> - {/* Pipeline Tab */} + {/* Pipeline Tab - shows role details */} {detailTab === 'pipeline' && ( - + )}