searchSlice.ts4.6 KBView on GitHub
import type { CedarStore } from '@/modules/store/CedarStoreTypes';
import type { StateCreator } from 'zustand';

export interface ActiveFilter {
  id: string;
  type: string;
  value: string;
  display: string;
}

export interface SearchState {
  value: string;
  highlight: string;
  folder: string;
  isLoading: boolean;
  isAISearching: boolean;
  activeFilters: ActiveFilter[];
}

export interface SearchSlice extends SearchState {
  setValue: (value: string) => void;
  setHighlight: (highlight: string) => void;
  setFolder: (folder: string) => void;
  setIsLoading: (isLoading: boolean) => void;
  setIsAISearching: (isAISearching: boolean) => void;
  setSearchState: (state: Partial<SearchState>) => void;
  resetSearchState: () => void;

  // Filter management
  addFilter: (filter: ActiveFilter) => void;
  removeFilter: (filterId: string) => void;
  clearAllFilters: () => void;
  setActiveFilters: (filters: ActiveFilter[]) => void;
}

const initialSearchState: SearchState = {
  value: '',
  highlight: '',
  folder: '',
  isLoading: false,
  isAISearching: false,
  activeFilters: [],
};

const ACTIVE_FILTERS_KEY=[redacted];

export const createSearchSlice: StateCreator<
  CedarStore,
  [['zustand/immer', never], ['zustand/devtools', never]],
  [],
  SearchSlice
> = (set) => ({
  ...initialSearchState,

  setValue: (value) =>
    set(
      (state) => {
        state.value = value;
      },
      false,
      'search/setValue',
    ),

  setHighlight: (highlight) =>
    set(
      (state) => {
        state.highlight = highlight;
      },
      false,
      'search/setHighlight',
    ),

  setFolder: (folder) =>
    set(
      (state) => {
        state.folder = folder;
      },
      false,
      'search/setFolder',
    ),

  setIsLoading: (isLoading) =>
    set(
      (state) => {
        state.isLoading = isLoading;
      },
      false,
      'search/setIsLoading',
    ),

  setIsAISearching: (isAISearching) =>
    set(
      (state) => {
        state.isAISearching = isAISearching;
      },
      false,
      'search/setIsAISearching',
    ),

  setSearchState: (partialState) =>
    set(
      (state) => {
        Object.assign(state, partialState);
      },
      false,
      'search/setSearchState',
    ),

  resetSearchState: () =>
    set(
      (state) => {
        state.value = initialSearchState.value;
        state.highlight = initialSearchState.highlight;
        state.folder = initialSearchState.folder;
        state.isLoading = initialSearchState.isLoading;
        state.isAISearching = initialSearchState.isAISearching;
        state.activeFilters = initialSearchState.activeFilters;
      },
      false,
      'search/reset',
    ),

  // Filter management
  addFilter: (filter) =>
    set(
      (state) => {
        // Replace existing filter of the same type
        state.activeFilters = [
          ...state.activeFilters.filter((f) => f.type !== filter.type),
          filter,
        ];
        try {
          localStorage.setItem(ACTIVE_FILTERS_KEY, JSON.stringify(state.activeFilters));
        } catch (error) {
          console.error('Failed to save filters:', error);
        }
      },
      false,
      'search/addFilter',
    ),

  removeFilter: (filterId) =>
    set(
      (state) => {
        state.activeFilters = state.activeFilters.filter((f) => f.id !== filterId);
        try {
          localStorage.setItem(ACTIVE_FILTERS_KEY, JSON.stringify(state.activeFilters));
        } catch (error) {
          console.error('Failed to save filters:', error);
        }
      },
      false,
      'search/removeFilter',
    ),

  clearAllFilters: () =>
    set(
      (state) => {
        state.activeFilters = [];
        state.value = '';
        state.highlight = '';
        try {
          localStorage.removeItem(ACTIVE_FILTERS_KEY);
        } catch (error) {
          console.error('Failed to clear filters:', error);
        }
      },
      false,
      'search/clearAllFilters',
    ),

  setActiveFilters: (filters) =>
    set(
      (state) => {
        state.activeFilters = filters;
        try {
          localStorage.setItem(ACTIVE_FILTERS_KEY, JSON.stringify(filters));
        } catch (error) {
          console.error('Failed to save filters:', error);
        }
      },
      false,
      'search/setActiveFilters',
    ),
});

// Helper function to load filters from localStorage
export const loadFiltersFromStorage = (): ActiveFilter[] => {
  try {
    const saved = localStorage.getItem(ACTIVE_FILTERS_KEY);
    return saved ? JSON.parse(saved) : [];
  } catch (error) {
    console.error('Failed to load active filters:', error);
    return [];
  }
};