export type ItemType = 'E' | 'F' | 'U' | 'T' | 'B' export interface HierarchyInfo { fullPath: string items: { type: ItemType; number: number }[] epicCode: string | null featureCode: string | null itemCode: string | null } const TYPE_LABELS: Record = { E: 'Γ‰pica', F: 'Feature', U: 'HU', T: 'Tarea', B: 'Bug', } const TYPE_COLORS: Record = { E: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400', F: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400', U: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400', T: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400', B: 'bg-rose-100 text-rose-700 dark:bg-rose-900/30 dark:text-rose-400', } const TYPE_ICONS: Record = { E: 'πŸ“¦', F: '⭐', U: 'πŸ“‹', T: 'βš™οΈ', B: 'πŸ›', } export function getTypeLabel(type: ItemType): string { return TYPE_LABELS[type] || type } export function getTypeColor(type: ItemType): string { return TYPE_COLORS[type] || 'bg-muted text-muted-foreground' } export function getTypeIcon(type: ItemType): string { return TYPE_ICONS[type] || 'πŸ“„' } const HIERARCHY_REGEX = /\[(([EFUTB]\d+)(?:-([EFUTB]\d+))?(?:-([EFUTB]\d+))?)\]/i export function parseHierarchy(title: string): HierarchyInfo | null { const match = title.match(HIERARCHY_REGEX) if (!match) return null const fullPath = match[1].toUpperCase() const segments = [match[2]] if (match[3]) segments.push(match[3]) if (match[4]) segments.push(match[4]) const items = segments.map(s => ({ type: s[0] as ItemType, number: parseInt(s.slice(1), 10), })) const epic = items.find(i => i.type === 'E') const feature = items.find(i => i.type === 'F') const item = items[items.length - 1] return { fullPath, items, epicCode: epic ? `E${String(epic.number).padStart(2, '0')}` : null, featureCode: feature ? `F${String(feature.number).padStart(2, '0')}` : null, itemCode: item ? `${item.type}${String(item.number).padStart(2, '0')}` : null, } } export function stripHierarchy(title: string): string { return title.replace(HIERARCHY_REGEX, '').trim() } export function getItemType(title: string): ItemType { const h = parseHierarchy(title) if (h?.items.length) return h.items[h.items.length - 1].type return 'U' } export function buildHierarchyPath( epicNum?: number, featureNum?: number, itemType?: ItemType, itemNum?: number, ): string { const parts: string[] = [] if (epicNum !== undefined) parts.push(`E${String(epicNum).padStart(2, '0')}`) if (featureNum !== undefined) parts.push(`F${String(featureNum).padStart(2, '0')}`) if (itemType && itemNum !== undefined) parts.push(`${itemType}${String(itemNum).padStart(2, '0')}`) return parts.length ? `[${parts.join('-')}]` : '' } export function buildFullTitle( name: string, epicNum?: number, featureNum?: number, itemType?: ItemType, itemNum?: number, ): string { const path = buildHierarchyPath(epicNum, featureNum, itemType, itemNum) return path ? `${path} ${name}` : name } export function extractItemNumber(title: string, type: ItemType): number | null { const h = parseHierarchy(title) if (!h) return null const found = h.items.find(i => i.type === type) return found?.number ?? null }