'use client'; import { useState } from 'react'; import { Version } from '@/libs/api'; type TreeNode = { version: Version; children: TreeNode[] }; function buildTree(versions: Version[]): TreeNode | null { const map = new Map(versions.map(v => [v.id, { version: v, children: [] as TreeNode[] }])); let root: TreeNode | null = null; for (const node of map.values()) { const pid = node.version.parent_version_id; if (!pid) { root = node; } else { map.get(pid)?.children.push(node); } } return root; } const DOT_COLORS = ['#0a0a0a', '#2563eb', '#7c3aed', '#059669', '#d97706', '#dc2626', '#0891b2']; function Node({ node, depth, selectedId, onSelect, onDelete, colorIndex = 0 }: { node: TreeNode; depth: number; selectedId: string | null; onSelect: (id: string) => void; onDelete?: (id: string) => void; colorIndex?: number; }) { const [open, setOpen] = useState(true); const [hovered, setHovered] = useState(false); const v = node.version; const isRoot = !v.parent_version_id; const isSelected = v.id === selectedId; const dotColor = DOT_COLORS[colorIndex % DOT_COLORS.length]; return (
{depth > 0 && (
)}
onSelect(v.id)} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} style={{ display: 'flex', alignItems: 'center', gap: 6, paddingLeft: depth > 0 ? 18 : 8, paddingRight: 4, height: 30, cursor: 'pointer', borderRadius: 4, userSelect: 'none', background: isSelected ? 'var(--selected-bg)' : hovered ? 'var(--hover)' : 'transparent', borderLeft: isSelected && depth === 0 ? '2px solid var(--selected-border)' : '2px solid transparent', }} > {v.version_label || v.branch_name} {v.patches.length > 0 && ( {v.patches.length} )} {!isRoot && onDelete && hovered && ( )}
{open && node.children.length > 0 && (
0 ? 22 : 14, borderLeft: `1px solid var(--border)`, paddingLeft: 0, }}> {node.children.map((child, i) => ( ))}
)}
); } export default function CVTree({ versions, selectedVersionId, onSelect, onDeleteVersion }: { versions: Version[]; selectedVersionId: string | null; onSelect: (id: string) => void; onDeleteVersion?: (id: string) => void; }) { const tree = buildTree(versions); if (!tree) return
No versions
; return (
); }