import { createContext, JSX } from 'solid-js'; import { createStore } from "solid-js/store"; import OlFeature from 'ol/Feature'; import { BusinessDataStore } from "../businessData"; import { Stop } from '../types'; import { PositionedPanel } from '../utils'; type ByStopIdMapFeatures = Record; export interface SearchStore { getSearchText: () => string; setSearchText: (text: string, businessDataStore: BusinessDataStore) => Promise; getFoundStops: () => Stop[]; setFoundStops: (stops: Stop[]) => void; getDisplayedPanelId: () => number; setDisplayedPanelId: (panelId: number) => void; getPanels: () => PositionedPanel[]; setPanels: (panels: PositionedPanel[]) => void; getHighlightedStop: () => Stop | undefined; setHighlightedStop: (stop: Stop) => void; resetHighlightedStop: () => void; enableMap: (enable: boolean) => void; isMapEnabled: () => boolean; getMapFeature: (stopId: number) => OlFeature | undefined; getAllMapFeatures: () => ByStopIdMapFeatures; setMapFeature: (stopId: number, feature: OlFeature) => void; }; export const SearchContext = createContext(); export function SearchProvider(props: { children: JSX.Element }) { const searchTextDelayMs = 1500; type Store = { searchText: string; searchPromise: Promise | undefined; foundStops: Stop[]; displayedPanelId: number; panels: PositionedPanel[]; highlightedStop: Stop | undefined; mapEnabled: boolean; mapFeatures: ByStopIdMapFeatures; }; const [store, setStore] = createStore({ searchText: "", searchPromise: undefined, foundStops: [], displayedPanelId: 0, panels: [], highlightedStop: undefined, // mapEnabled: false, mapFeatures: {}, }); const getSearchText = (): string => { return store.searchText; } const debounce = async (fn: (...args: any[]) => Promise, delayMs: number) => { let timerId: number; return new Promise((...args) => { clearTimeout(timerId); timerId = setTimeout(fn, delayMs, ...args); }); } const setSearchText = async (text: string, businessDataStore: BusinessDataStore): Promise => { setStore('searchText', text); if (store.searchPromise === undefined) { const { searchStopByName } = businessDataStore; const promise: Promise = debounce(async (onSuccess: () => void) => { console.log(`Fetching data for "${store.searchText}" stop name`); const stopsById = await searchStopByName(store.searchText); console.log("stopsById=", stopsById); setFoundStops(Object.values(stopsById)); onSuccess(); }, searchTextDelayMs).then(() => { setStore('searchPromise', undefined); }); setStore('searchPromise', promise); } } const getFoundStops = (): Stop[] => { return store.foundStops; } const setFoundStops = (stops: Stop[]): void => { setStore('foundStops', stops); } const getDisplayedPanelId = (): number => { return store.displayedPanelId; } const setDisplayedPanelId = (panelId: number): void => { setStore('displayedPanelId', panelId); } const getPanels = (): PositionedPanel[] => { return store.panels; } const setPanels = (panels: PositionedPanel[]): void => { setStore('panels', panels); } const getHighlightedStop = (): Stop | undefined => { return store.highlightedStop; } const setHighlightedStop = (stop: Stop): void => { setStore('highlightedStop', stop); } const resetHighlightedStop = (): void => { setStore('highlightedStop', undefined); } const enableMap = (enable: boolean): void => { setStore("mapEnabled", enable); } const isMapEnabled = (): boolean => { return store.mapEnabled; } const getAllMapFeatures = (): ByStopIdMapFeatures => { return store.mapFeatures; } const getMapFeature = (stopId: number): OlFeature | undefined => { return store.mapFeatures[stopId]; } const setMapFeature = (stopId: number, feature: OlFeature): void => { setStore('mapFeatures', stopId, feature); }; return ( {props.children} ); }