cache inteligente: Turso primero, luego KAPPA con deteccion de cambios
This commit is contained in:
+88
-12
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user