Files
SIB/frontend/src/stores/route.ts

117 lines
4.2 KiB
TypeScript
Raw Normal View History

2026-02-21 09:53:31 -05:00
/** Pinia store for route management */
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { Route, BusStop } from '@/types'
import { routesService } from '@/services/routesService'
export const useRouteStore = defineStore('route', () => {
const selectedRouteId = ref<string | null>(null)
const selectedRouteName = ref<string | null>(null)
const selectedRouteStops = ref<BusStop[]>([])
const allRoutes = ref<Route[]>([])
const isLoadingRoutes = ref(false)
const isLoadingStops = ref(false)
const error = ref<string | null>(null)
const wasSelectedFromMap = ref(false)
const lastFetched = ref<number>(0) // ⚡ CACHÉ ESTÁTICO RUTAS
const stopsCache = ref<Map<string, { fetchedAt: number, stops: BusStop[] }>>(new Map()) // ⚡ CACHÉ ESTÁTICO PARADAS
2026-02-21 09:53:31 -05:00
const hasSelectedRoute = computed(() => selectedRouteId.value !== null && selectedRouteName.value !== null)
async function loadRoutes(filters?: { originCity?: string, destinationCity?: string }, force = false) {
2026-02-26 12:50:12 -05:00
const CACHE_TIME = 1000 * 60 * 15; // 15 minutos
const now = Date.now();
// Guard: Si ya se están cargando rutas, no iniciar otra petición
if (isLoadingRoutes.value) return;
2026-02-26 12:50:12 -05:00
// Si no forzamos, no hay filtros raros, ya tenemos rutas y aún no expira el caché, omitir llamada
if (!force && !filters && allRoutes.value.length > 0 && (now - lastFetched.value < CACHE_TIME)) {
2026-02-21 09:53:31 -05:00
return
}
isLoadingRoutes.value = true
error.value = null
try {
allRoutes.value = await routesService.getAllRoutes(filters)
2026-02-26 12:50:12 -05:00
if (!filters) lastFetched.value = now; // Solo actualizar timer si es un request general limio
2026-02-21 09:53:31 -05:00
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to load routes'
console.error('Error loading routes:', e)
} finally {
isLoadingRoutes.value = false
}
}
async function loadRouteStops(routeId: string, force = false): Promise<BusStop[]> {
const CACHE_TIME = 1000 * 60 * 15; // 15 minutos
const now = Date.now();
if (stopsCache.value.has(routeId) && !force) {
const cacheEntry = stopsCache.value.get(routeId)!;
if (now - cacheEntry.fetchedAt < CACHE_TIME) {
selectedRouteStops.value = cacheEntry.stops;
return cacheEntry.stops;
}
}
if (isLoadingStops.value) return [];
2026-02-21 09:53:31 -05:00
isLoadingStops.value = true
error.value = null
try {
const stops = await routesService.getRouteStops(routeId)
selectedRouteStops.value = stops
stopsCache.value.set(routeId, { fetchedAt: now, stops })
return stops
2026-02-21 09:53:31 -05:00
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to load route stops'
console.error('Error loading route stops:', e)
selectedRouteStops.value = []
return []
2026-02-21 09:53:31 -05:00
} finally {
isLoadingStops.value = false
}
}
async function selectRoute(routeId: string, routeName: string) {
if (selectedRouteId.value === routeId) return
selectedRouteId.value = routeId
selectedRouteName.value = routeName
selectedRouteStops.value = [] // Limpia para forzar recarga atómica en la vista
2026-02-21 09:53:31 -05:00
}
// Watcher manual para wasSelectedFromMap ya que se cambia en varios sitios
function setWasSelectedFromMap(val: boolean) {
wasSelectedFromMap.value = val
}
2026-02-21 09:53:31 -05:00
function clearSelection() {
selectedRouteId.value = null
selectedRouteName.value = null
selectedRouteStops.value = []
wasSelectedFromMap.value = false
2026-02-21 09:53:31 -05:00
}
return {
selectedRouteId,
selectedRouteName,
selectedRouteStops,
allRoutes,
isLoadingRoutes,
isLoadingStops,
error,
wasSelectedFromMap,
2026-02-21 09:53:31 -05:00
hasSelectedRoute,
loadRoutes,
loadRouteStops,
selectRoute,
setWasSelectedFromMap,
2026-02-21 09:53:31 -05:00
clearSelection,
}
}, {
persist: {
pick: ['selectedRouteId', 'selectedRouteName', 'wasSelectedFromMap', 'allRoutes']
}
2026-02-21 09:53:31 -05:00
})