diff --git a/src/stores/workitems.ts b/src/stores/workitems.ts index d49b751..500b5fc 100644 --- a/src/stores/workitems.ts +++ b/src/stores/workitems.ts @@ -1,14 +1,16 @@ import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { kappa } from '@/services/kappa-api' -import { tauriDb } from '@/services/tauri-db' +import { tauriDb, type UserStoryRecord, type EpicRecord } from '@/services/tauri-db' import { stripHtml } from '@/services/clean-html' import type { KappaUserStory, KappaLogbookEntry, KappaPlanningEntry, KappaEpicDevelopment } from '@/types/kappa' export const useWorkItemsStore = defineStore('workitems', () => { const creating = ref(false) const loading = ref(false) + const syncing = ref(false) const error = ref(null) + const firstVisit = ref>(new Set()) const userStories = ref([]) const epics = ref([]) @@ -49,42 +51,115 @@ export const useWorkItemsStore = defineStore('workitems', () => { return } + const isFirstVisit = !firstVisit.value.has(id) + try { - const [stories, logs, plans, epicData] = await Promise.all([ + // 1. Cargar desde Turso (instantáneo) + if (!isFirstVisit) { + const [localEpics, localHUs] = await Promise.all([ + tauriDb.getEpics(id).catch(() => [] as EpicRecord[]), + 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, + })) + + 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, + })) + } + + // 2. Consultar KAPPA (siempre, para detectar cambios) + syncing.value = true + const [stories, epicData] = await Promise.all([ kappa.getAllUserStories(id).catch(() => [] as KappaUserStory[]), - kappa.getLogbooks(id).catch(() => [] as KappaLogbookEntry[]), - kappa.getPlannings(id).catch(() => [] as KappaPlanningEntry[]), kappa.getAllEpicDevelopment(id).catch(() => [] as KappaEpicDevelopment[]), ]) + // 3. Merge: detectar nuevos/cambiados + const localHUIds = new Set(userStories.value.map(hu => hu.id)) + const newHUs = stories.filter(s => !localHUIds.has(s.id)) + + const localEpicIds = new Set(epics.value.map(e => e.id)) + const newEpics = epicData.filter(e => !localEpicIds.has(e.id)) + + // 4. Actualizar UI con datos frescos de KAPPA userStories.value = stories - logbooks.value = Array.isArray(logs) ? logs : ((logs as any).results ?? []) - plannings.value = Array.isArray(plans) ? plans : ((plans as any).results ?? []) epics.value = epicData.map(epic => ({ ...epic, description: stripHtml(epic.description || ''), })) - syncHUsToTurso(id, userStories.value) + // 5. Guardar en Turso: insertar/actualizar HUs y épicas + if (isFirstVisit || newHUs.length > 0) { + await syncHUsToTurso(id, isFirstVisit ? stories : newHUs) + } + if (isFirstVisit || newEpics.length > 0) { + await syncEpicsToTurso(id, isFirstVisit ? epicData : newEpics) + } + + firstVisit.value.add(id) } catch (e: any) { error.value = e.message } finally { loading.value = false + syncing.value = false } } async function syncHUsToTurso(projectId: number, hus: KappaUserStory[]) { for (const hu of hus) { - await tauriDb.saveWorkItem({ + await tauriDb.saveUserStory({ id: hu.id ?? 0, - project_id: projectId, + initiative_id: projectId, + epic_id: null, code: hu.code ?? null, title: hu.title, description: stripHtml(hu.description || ''), - type: 'hu', - status: hu.status || 'backlog', - priority: hu.priority || 'medium', + acceptance_criteria: hu.acceptance_criteria ?? null, + status: hu.status ?? null, + priority: hu.priority ?? null, + story_points: null, + estimated_hours: null, + actual_hours: null, + assigned_to: null, + created_at: null, + }).catch(() => {}) + } + } + + async function syncEpicsToTurso(projectId: number, epicsData: KappaEpicDevelopment[]) { + for (const epic of epicsData) { + await tauriDb.saveEpic({ + id: epic.id, + initiative_id: projectId, + code: epic.code ?? null, + name: epic.name || epic.title || `Épica ${epic.id}`, + description: epic.description ?? null, + status: epic.status ?? null, + client_taker: null, + stimated_start_date: null, + stimated_end_date: null, + start_date: null, + end_date: null, + created_at: null, + updated_at: null, }).catch(() => {}) } } @@ -92,6 +167,7 @@ export const useWorkItemsStore = defineStore('workitems', () => { return { creating, loading, + syncing, error, userStories, epics,