cache inteligente: Turso primero, luego KAPPA con deteccion de cambios

This commit is contained in:
2026-05-27 18:12:33 -05:00
parent 7c52a32877
commit e905fa5712
+88 -12
View File
@@ -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<string | null>(null)
const firstVisit = ref<Set<number>>(new Set())
const userStories = ref<KappaUserStory[]>([])
const epics = ref<KappaEpicDevelopment[]>([])
@@ -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,