fix(frontend): align project types with backend enums

- Fix ProjectStatus: use 'active' instead of 'in_progress'
- Fix AgentStatus: remove 'active'/'pending'/'error', add 'waiting'
- Fix SprintStatus: add 'in_review'
- Rename IssueSummary to IssueCountSummary
- Update all components to use correct enum values

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-31 12:48:02 +01:00
parent 5fab15a11e
commit 35af7daf90
7 changed files with 43 additions and 43 deletions

View File

@@ -126,7 +126,7 @@ function AgentListItem({
<DropdownMenuItem onClick={() => onAction(agent.id, 'view')}> <DropdownMenuItem onClick={() => onAction(agent.id, 'view')}>
View Details View Details
</DropdownMenuItem> </DropdownMenuItem>
{agent.status === 'active' || agent.status === 'working' ? ( {agent.status === 'working' || agent.status === 'waiting' ? (
<DropdownMenuItem onClick={() => onAction(agent.id, 'pause')}> <DropdownMenuItem onClick={() => onAction(agent.id, 'pause')}>
Pause Agent Pause Agent
</DropdownMenuItem> </DropdownMenuItem>
@@ -196,7 +196,7 @@ export function AgentPanel({
} }
const activeAgentCount = agents.filter( const activeAgentCount = agents.filter(
(a) => a.status === 'active' || a.status === 'working' (a) => a.status === 'working' || a.status === 'waiting'
).length; ).length;
return ( return (

View File

@@ -14,21 +14,17 @@ const statusConfig: Record<AgentStatus, { color: string; label: string }> = {
color: 'bg-yellow-500', color: 'bg-yellow-500',
label: 'Idle', label: 'Idle',
}, },
active: {
color: 'bg-green-500',
label: 'Active',
},
working: { working: {
color: 'bg-green-500 animate-pulse', color: 'bg-green-500 animate-pulse',
label: 'Working', label: 'Working',
}, },
pending: { waiting: {
color: 'bg-gray-400', color: 'bg-blue-500',
label: 'Pending', label: 'Waiting',
}, },
error: { paused: {
color: 'bg-red-500', color: 'bg-gray-400',
label: 'Error', label: 'Paused',
}, },
terminated: { terminated: {
color: 'bg-gray-600', color: 'bg-gray-600',
@@ -49,7 +45,7 @@ export function AgentStatusIndicator({
showLabel = false, showLabel = false,
className, className,
}: AgentStatusIndicatorProps) { }: AgentStatusIndicatorProps) {
const config = statusConfig[status] || statusConfig.pending; const config = statusConfig[status] || statusConfig.idle;
const sizeClasses = { const sizeClasses = {
sm: 'h-2 w-2', sm: 'h-2 w-2',

View File

@@ -24,7 +24,7 @@ import {
} from '@/components/ui/card'; } from '@/components/ui/card';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { Skeleton } from '@/components/ui/skeleton'; import { Skeleton } from '@/components/ui/skeleton';
import type { IssueSummary as IssueSummaryType } from './types'; import type { IssueCountSummary } from './types';
// ============================================================================ // ============================================================================
// Types // Types
@@ -32,7 +32,7 @@ import type { IssueSummary as IssueSummaryType } from './types';
interface IssueSummaryProps { interface IssueSummaryProps {
/** Issue summary data */ /** Issue summary data */
summary: IssueSummaryType | null; summary: IssueCountSummary | null;
/** Whether data is loading */ /** Whether data is loading */
isLoading?: boolean; isLoading?: boolean;
/** Callback when "View All Issues" is clicked */ /** Callback when "View All Issues" is clicked */
@@ -171,8 +171,8 @@ export function IssueSummary({
<StatusRow <StatusRow
icon={CheckCircle2} icon={CheckCircle2}
iconColor="text-green-500" iconColor="text-green-500"
label="Completed" label="Closed"
count={summary.done} count={summary.closed}
/> />
{onViewAllIssues && ( {onViewAllIssues && (

View File

@@ -28,7 +28,7 @@ import type {
AgentInstance, AgentInstance,
Sprint, Sprint,
BurndownDataPoint, BurndownDataPoint,
IssueSummary as IssueSummaryType, IssueCountSummary,
ActivityItem, ActivityItem,
} from './types'; } from './types';
@@ -52,7 +52,7 @@ const mockProject: Project = {
id: 'proj-001', id: 'proj-001',
name: 'E-Commerce Platform Redesign', name: 'E-Commerce Platform Redesign',
description: 'Complete redesign of the e-commerce platform with modern UI/UX', description: 'Complete redesign of the e-commerce platform with modern UI/UX',
status: 'in_progress', status: 'active',
autonomy_level: 'milestone', autonomy_level: 'milestone',
current_sprint_id: 'sprint-003', current_sprint_id: 'sprint-003',
created_at: '2025-01-15T00:00:00Z', created_at: '2025-01-15T00:00:00Z',
@@ -66,7 +66,7 @@ const mockAgents: AgentInstance[] = [
project_id: 'proj-001', project_id: 'proj-001',
name: 'Product Owner', name: 'Product Owner',
role: 'product_owner', role: 'product_owner',
status: 'active', status: 'working',
current_task: 'Reviewing user story acceptance criteria', current_task: 'Reviewing user story acceptance criteria',
last_activity_at: new Date(Date.now() - 2 * 60 * 1000).toISOString(), last_activity_at: new Date(Date.now() - 2 * 60 * 1000).toISOString(),
spawned_at: '2025-01-15T00:00:00Z', spawned_at: '2025-01-15T00:00:00Z',
@@ -102,7 +102,7 @@ const mockAgents: AgentInstance[] = [
project_id: 'proj-001', project_id: 'proj-001',
name: 'Frontend Engineer', name: 'Frontend Engineer',
role: 'frontend_engineer', role: 'frontend_engineer',
status: 'active', status: 'working',
current_task: 'Implementing product catalog component', current_task: 'Implementing product catalog component',
last_activity_at: new Date(Date.now() - 1 * 60 * 1000).toISOString(), last_activity_at: new Date(Date.now() - 1 * 60 * 1000).toISOString(),
spawned_at: '2025-01-15T00:00:00Z', spawned_at: '2025-01-15T00:00:00Z',
@@ -114,7 +114,7 @@ const mockAgents: AgentInstance[] = [
project_id: 'proj-001', project_id: 'proj-001',
name: 'QA Engineer', name: 'QA Engineer',
role: 'qa_engineer', role: 'qa_engineer',
status: 'pending', status: 'waiting',
current_task: 'Preparing test cases for Sprint 3', current_task: 'Preparing test cases for Sprint 3',
last_activity_at: new Date(Date.now() - 30 * 60 * 1000).toISOString(), last_activity_at: new Date(Date.now() - 30 * 60 * 1000).toISOString(),
spawned_at: '2025-01-15T00:00:00Z', spawned_at: '2025-01-15T00:00:00Z',
@@ -148,12 +148,12 @@ const mockBurndownData: BurndownDataPoint[] = [
{ day: 8, remaining: 20, ideal: 24 }, { day: 8, remaining: 20, ideal: 24 },
]; ];
const mockIssueSummary: IssueSummaryType = { const mockIssueSummary: IssueCountSummary = {
open: 12, open: 12,
in_progress: 8, in_progress: 8,
in_review: 3, in_review: 3,
blocked: 2, blocked: 2,
done: 45, closed: 45,
total: 70, total: 70,
}; };
@@ -392,7 +392,7 @@ export function ProjectDashboard({ projectId, className }: ProjectDashboardProps
<ProjectHeader <ProjectHeader
project={project} project={project}
isLoading={isLoading} isLoading={isLoading}
canPause={project.status === 'in_progress'} canPause={project.status === 'active'}
canStart={true} canStart={true}
onStartSprint={handleStartSprint} onStartSprint={handleStartSprint}
onPauseProject={handlePauseProject} onPauseProject={handlePauseProject}

View File

@@ -84,7 +84,7 @@ export function ProjectHeader({
return null; return null;
} }
const showPauseButton = canPause && project.status === 'in_progress'; const showPauseButton = canPause && project.status === 'active';
const showStartButton = canStart && project.status !== 'completed' && project.status !== 'archived'; const showStartButton = canStart && project.status !== 'completed' && project.status !== 'archived';
return ( return (

View File

@@ -16,12 +16,8 @@ import type { ProjectStatus, AutonomyLevel } from './types';
// ============================================================================ // ============================================================================
const projectStatusConfig: Record<ProjectStatus, { label: string; className: string }> = { const projectStatusConfig: Record<ProjectStatus, { label: string; className: string }> = {
draft: { active: {
label: 'Draft', label: 'Active',
className: 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200',
},
in_progress: {
label: 'In Progress',
className: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200', className: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200',
}, },
paused: { paused: {
@@ -32,10 +28,6 @@ const projectStatusConfig: Record<ProjectStatus, { label: string; className: str
label: 'Completed', label: 'Completed',
className: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200', className: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
}, },
blocked: {
label: 'Blocked',
className: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200',
},
archived: { archived: {
label: 'Archived', label: 'Archived',
className: 'bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400', className: 'bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400',
@@ -48,7 +40,7 @@ interface ProjectStatusBadgeProps {
} }
export function ProjectStatusBadge({ status, className }: ProjectStatusBadgeProps) { export function ProjectStatusBadge({ status, className }: ProjectStatusBadgeProps) {
const config = projectStatusConfig[status] || projectStatusConfig.draft; const config = projectStatusConfig[status] || projectStatusConfig.active;
return ( return (
<Badge variant="outline" className={cn(config.className, className)}> <Badge variant="outline" className={cn(config.className, className)}>

View File

@@ -11,7 +11,10 @@
// Project Types // Project Types
// ============================================================================ // ============================================================================
export type ProjectStatus = 'draft' | 'in_progress' | 'paused' | 'completed' | 'blocked' | 'archived'; /**
* Matches backend: ProjectStatus enum in app/models/syndarix/enums.py
*/
export type ProjectStatus = 'active' | 'paused' | 'completed' | 'archived';
export type AutonomyLevel = 'full_control' | 'milestone' | 'autonomous'; export type AutonomyLevel = 'full_control' | 'milestone' | 'autonomous';
@@ -31,7 +34,10 @@ export interface Project {
// Agent Types // Agent Types
// ============================================================================ // ============================================================================
export type AgentStatus = 'idle' | 'active' | 'working' | 'pending' | 'error' | 'terminated'; /**
* Matches backend: AgentStatus enum in app/models/syndarix/enums.py
*/
export type AgentStatus = 'idle' | 'working' | 'waiting' | 'paused' | 'terminated';
export interface AgentInstance { export interface AgentInstance {
id: string; id: string;
@@ -50,7 +56,10 @@ export interface AgentInstance {
// Sprint Types // Sprint Types
// ============================================================================ // ============================================================================
export type SprintStatus = 'planning' | 'active' | 'review' | 'completed'; /**
* Matches backend: SprintStatus enum in app/models/syndarix/enums.py
*/
export type SprintStatus = 'planned' | 'active' | 'in_review' | 'completed' | 'cancelled';
export interface Sprint { export interface Sprint {
id: string; id: string;
@@ -78,7 +87,10 @@ export interface BurndownDataPoint {
// Issue Types // Issue Types
// ============================================================================ // ============================================================================
export type IssueStatus = 'open' | 'in_progress' | 'in_review' | 'blocked' | 'done' | 'closed'; /**
* Matches backend: IssueStatus enum in app/models/syndarix/enums.py
*/
export type IssueStatus = 'open' | 'in_progress' | 'in_review' | 'blocked' | 'closed';
export type IssuePriority = 'low' | 'medium' | 'high' | 'critical'; export type IssuePriority = 'low' | 'medium' | 'high' | 'critical';
@@ -96,12 +108,12 @@ export interface Issue {
labels?: string[]; labels?: string[];
} }
export interface IssueSummary { export interface IssueCountSummary {
open: number; open: number;
in_progress: number; in_progress: number;
in_review: number; in_review: number;
blocked: number; blocked: number;
done: number; closed: number;
total: number; total: number;
} }