import React from 'react' import Link from 'next/link' import type { SDKStep, RAGCorpusStatus, SDKPackageId } from '@/lib/sdk' import { CheckIcon, LockIcon, WarningIcon, ChevronDownIcon } from './SidebarIcons' function withProject(url: string, projectId?: string): string { if (!projectId) return url const separator = url.includes('?') ? '&' : '?' return `${url}${separator}project=${projectId}` } // ============================================================================= // PROGRESS BAR // ============================================================================= interface ProgressBarProps { value: number className?: string } export function ProgressBar({ value, className = '' }: ProgressBarProps) { return (
) } // ============================================================================= // PACKAGE INDICATOR // ============================================================================= interface PackageIndicatorProps { packageId: SDKPackageId order: number name: string icon: string completion: number isActive: boolean isExpanded: boolean isLocked: boolean onToggle: () => void collapsed: boolean } export function PackageIndicator({ order, name, icon, completion, isActive, isExpanded, isLocked, onToggle, collapsed, }: PackageIndicatorProps) { if (collapsed) { return ( ) } return ( ) } // ============================================================================= // STEP ITEM // ============================================================================= interface StepItemProps { step: SDKStep isActive: boolean isCompleted: boolean isLocked: boolean checkpointStatus?: 'passed' | 'failed' | 'warning' | 'pending' collapsed: boolean projectId?: string } export function StepItem({ step, isActive, isCompleted, isLocked, checkpointStatus, collapsed, projectId }: StepItemProps) { const content = (
{isCompleted ? (
) : isLocked ? (
) : isActive ? (
) : (
)}
{!collapsed && {step.nameShort}} {!collapsed && checkpointStatus && checkpointStatus !== 'pending' && (
{checkpointStatus === 'passed' ? (
) : checkpointStatus === 'failed' ? (
!
) : (
)}
)}
) if (isLocked) return content return ( {content} ) } // ============================================================================= // ADDITIONAL MODULE ITEM // ============================================================================= interface AdditionalModuleItemProps { href: string icon: React.ReactNode label: string isActive: boolean | undefined collapsed: boolean projectId?: string } export function AdditionalModuleItem({ href, icon, label, isActive, collapsed, projectId }: AdditionalModuleItemProps) { const isExternal = href.startsWith('http') const className = `flex items-center gap-3 px-4 py-2.5 text-sm transition-colors ${ collapsed ? 'justify-center' : '' } ${ isActive ? 'bg-purple-100 text-purple-900 font-medium' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900' }` if (isExternal) { return ( {icon} {!collapsed && ( {label} )} ) } return ( {icon} {!collapsed && {label}} ) } // ============================================================================= // CORPUS STALENESS INFO // ============================================================================= export function CorpusStalenessInfo({ ragCorpusStatus }: { ragCorpusStatus: RAGCorpusStatus }) { const collections = ragCorpusStatus.collections const collectionNames = Object.keys(collections) if (collectionNames.length === 0) return null const lastUpdated = collectionNames.reduce((latest, name) => { const updated = new Date(collections[name].last_updated) return updated > latest ? updated : latest }, new Date(0)) const daysSinceUpdate = Math.floor((Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24)) const totalChunks = collectionNames.reduce((sum, name) => sum + collections[name].chunks_count, 0) return (
30 ? 'bg-amber-400' : 'bg-green-400'}`} /> RAG Corpus: {totalChunks} Chunks
{daysSinceUpdate > 30 && (
Corpus {daysSinceUpdate}d alt — Re-Evaluation empfohlen
)}
) }