searchStore.js 2.32 KB
import { writable, derived, get } from 'svelte/store';
import { initSearchIndex, search, isIndexReady } from '$lib/services/search';

// Estado del buscador
export const query = writable('');
export const results = writable([]);
export const isLoading = writable(false);
export const indexLoaded = writable(false);
export const error = writable(null);
export const selectedIndex = writable(-1);
export const filterType = writable('todos'); // todos, entidad, objeto_gasto, rubro, finfun

// Estado derivado: si está mostrando resultados
export const showResults = derived(
  [query, results, indexLoaded],
  ([$query, $results, $indexLoaded]) => $indexLoaded && $query.length >= 2
);

/**
 * Inicializa el índice de búsqueda
 */
export async function initIndex() {
  if (isIndexReady()) {
    indexLoaded.set(true);
    return;
  }

  isLoading.set(true);
  error.set(null);

  try {
    await initSearchIndex();
    indexLoaded.set(true);
  } catch (e) {
    error.set('Error al cargar el índice de búsqueda');
    console.error(e);
  } finally {
    isLoading.set(false);
  }
}

/**
 * Realiza la búsqueda
 */
export function performSearch(searchQuery, filter = null) {
  query.set(searchQuery);
  selectedIndex.set(-1);

  if (searchQuery.length < 2) {
    results.set([]);
    return;
  }

  let searchResults = search(searchQuery, 30);

  // Filtrar por tipo si no es "todos"
  const currentFilter = filter !== null ? filter : get(filterType);
  if (currentFilter !== 'todos') {
    searchResults = searchResults.filter(r => r.tipo === currentFilter);
  }

  // Limitar resultados
  results.set(searchResults.slice(0, 15));
}

/**
 * Limpia la búsqueda
 */
export function clearSearch() {
  query.set('');
  results.set([]);
  selectedIndex.set(-1);
}

/**
 * Cambia el filtro de tipo
 */
export function setFilter(type) {
  filterType.set(type);
  // Re-ejecutar búsqueda con el nuevo filtro
  const currentQuery = get(query);
  if (currentQuery.length >= 2) {
    performSearch(currentQuery, type);
  }
}

/**
 * Navegación por teclado
 */
export function navigateResults(direction, totalResults) {
  selectedIndex.update(current => {
    if (direction === 'down') {
      return current < totalResults - 1 ? current + 1 : 0;
    } else if (direction === 'up') {
      return current > 0 ? current - 1 : totalResults - 1;
    }
    return current;
  });
}