Files
inq-roi-simulador-web/src/store/simulation-store.ts

77 lines
2.8 KiB
TypeScript

import { create } from 'zustand'
import { v4 as uuidv4 } from 'uuid'
import type { SimulationResult } from '@/domain/types'
import { simulationRepo } from '@/persistence/repositories'
// Excepción arquitectónica documentada: simulation-store importa process-store en una dirección
// para suscribirse a cambios de datos y invalidar resultados. No existe dependencia inversa.
import { useProcessStore } from '@/store/process-store'
interface SimulationState {
resultActual: SimulationResult | null // resultado del escenario actual
resultAutomated: SimulationResult | null // resultado del escenario automatizado
lastSimulatedAt: Date | null // timestamp de la última simulación exitosa
isRunning: boolean
error: string | null
selectedActivityId: string | null
// Persiste ambos resultados en IndexedDB y actualiza el estado en memoria.
// REGLA: los dos resultados siempre se guardan y actualizan en conjunto.
persistResults: (processId: string, actual: SimulationResult, automated: SimulationResult) => Promise<void>
setRunning: (running: boolean) => void
setError: (error: string | null) => void
selectActivity: (bpmnElementId: string | null) => void
// Invalida AMBOS resultados a null. Se llama cuando cambian datos del proceso.
invalidateResults: () => void
reset: () => void
}
export const useSimulationStore = create<SimulationState>((set) => ({
resultActual: null,
resultAutomated: null,
lastSimulatedAt: null,
isRunning: false,
error: null,
selectedActivityId: null,
persistResults: async (processId, actual, automated) => {
await simulationRepo.save({
id: uuidv4(),
processId,
executedAt: Date.now(),
result: actual,
resultAutomated: automated,
})
set({ resultActual: actual, resultAutomated: automated, lastSimulatedAt: new Date(), error: null })
},
setRunning: (isRunning) => set({ isRunning }),
setError: (error) => set({ error }),
selectActivity: (selectedActivityId) => set({ selectedActivityId }),
invalidateResults: () =>
set({ resultActual: null, resultAutomated: null, lastSimulatedAt: null }),
reset: () =>
set({
resultActual: null,
resultAutomated: null,
lastSimulatedAt: null,
isRunning: false,
error: null,
selectedActivityId: null,
}),
}))
// Suscripción reactiva: cualquier cambio en activities o currentProcess del process-store
// invalida los resultados para garantizar que nunca haya resultados "viejos" visibles.
// La comparación por referencia de Zustand asegura que solo fires en cambios reales.
useProcessStore.subscribe((state, prevState) => {
if (
state.activities !== prevState.activities ||
state.currentProcess !== prevState.currentProcess
) {
useSimulationStore.getState().invalidateResults()
}
})