hierarchy: parsear nomenclatura [E05-F04-U02], badges de tipo en dashboard, clean title

This commit is contained in:
2026-05-27 21:59:37 -05:00
parent 9ae2af3ea2
commit cf770a6a44
4 changed files with 195 additions and 30 deletions
+50 -26
View File
@@ -3,8 +3,21 @@ import { ref, computed } from 'vue'
import { kappa } from '@/services/kappa-api'
import { tauriDb, type UserStoryRecord, type EpicRecord } from '@/services/tauri-db'
import { stripHtml } from '@/services/clean-html'
import { parseHierarchy, stripHierarchy, getItemType, type ItemType } from '@/services/hierarchy'
import type { KappaUserStory, KappaLogbookEntry, KappaPlanningEntry, KappaEpicDevelopment } from '@/types/kappa'
export interface EnrichedUserStory extends KappaUserStory {
_itemType: ItemType
_hierarchyPath: string | null
_cleanTitle: string
}
export interface EnrichedEpic extends KappaEpicDevelopment {
_itemType: ItemType
_hierarchyPath: string | null
_cleanName: string
}
export const useWorkItemsStore = defineStore('workitems', () => {
const creating = ref(false)
const loading = ref(false)
@@ -12,8 +25,8 @@ export const useWorkItemsStore = defineStore('workitems', () => {
const error = ref<string | null>(null)
const firstVisit = ref<Set<number>>(new Set())
const userStories = ref<KappaUserStory[]>([])
const epics = ref<KappaEpicDevelopment[]>([])
const userStories = ref<EnrichedUserStory[]>([])
const epics = ref<EnrichedEpic[]>([])
const logbooks = ref<KappaLogbookEntry[]>([])
const plannings = ref<KappaPlanningEntry[]>([])
@@ -27,13 +40,41 @@ export const useWorkItemsStore = defineStore('workitems', () => {
)
const totalSessions = computed(() => logbooks.value.length)
async function createUserStory(story: KappaUserStory): Promise<KappaUserStory | null> {
function enrichEpic(e: { name?: string; title?: string; id?: number }, initiativeId: number): EnrichedEpic {
const title = e.name || e.title || ''
const h = parseHierarchy(title)
return {
id: e.id ?? 0,
code: undefined,
name: e.name,
title: e.name || e.title,
initiative: initiativeId,
_itemType: h?.items[h.items.length - 1]?.type || 'E',
_hierarchyPath: h?.fullPath ?? null,
_cleanName: h ? stripHierarchy(title) : title,
}
}
function enrichHU(hu: { title?: string; id?: number }, initiativeId: number): EnrichedUserStory {
const h = parseHierarchy(hu.title || '')
return {
id: hu.id ?? 0,
title: hu.title || '',
initiative: initiativeId,
_itemType: h?.items[h.items.length - 1]?.type || 'U',
_hierarchyPath: h?.fullPath ?? null,
_cleanTitle: h ? stripHierarchy(hu.title || '') : (hu.title || ''),
}
}
async function createUserStory(story: KappaUserStory): Promise<EnrichedUserStory | null> {
creating.value = true
error.value = null
try {
const result = await kappa.createUserStory(story)
userStories.value.push(result)
return result
const enriched = enrichHU(result, Number(result.initiative))
userStories.value.push(enriched)
return enriched
} catch (e: any) {
error.value = e.message
return null
@@ -62,27 +103,9 @@ export const useWorkItemsStore = defineStore('workitems', () => {
tauriDb.getUserStories(id).catch(() => [] as UserStoryRecord[]),
])
epics.value = localEpics.map(e => ({
id: e.id,
code: e.code || undefined,
name: e.name,
title: e.name,
description: e.description || undefined,
status: e.status || undefined,
client_taker: e.client_taker || undefined,
initiative: id,
}))
epics.value = localEpics.map(e => enrichEpic(e, id))
userStories.value = localHUs.map(hu => ({
id: hu.id,
code: hu.code || undefined,
title: hu.title,
description: hu.description || undefined,
acceptance_criteria: hu.acceptance_criteria || undefined,
status: hu.status || undefined,
priority: hu.priority || undefined,
initiative: id,
}))
userStories.value = localHUs.map(hu => enrichHU(hu, id))
}
// 2. Consultar KAPPA (siempre, para detectar cambios)
@@ -100,11 +123,12 @@ export const useWorkItemsStore = defineStore('workitems', () => {
const newEpics = epicData.filter(e => !localEpicIds.has(e.id))
// 4. Actualizar UI con datos frescos de KAPPA
userStories.value = stories
userStories.value = stories.map(hu => enrichHU(hu, id))
epics.value = epicData.map(epic => ({
...epic,
description: stripHtml(epic.description || ''),
...enrichEpic(epic, id),
}))
// 5. Guardar en Turso: insertar/actualizar HUs y épicas