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 [];
}
};