import { createContext, useContext, useEffect, useState } from 'react'; import { useCache } from './cache'; import type { WidgetProps } from './index'; type UseQueryOptions = { cache: boolean; cacheKey?: string; }; export function useQuery(endpoint: string | undefined, options: UseQueryOptions = { cache: true }) { const [cache, setCache] = useCache(); const [result, setResult] = useState(undefined); const [fetching, setFetching] = useState(false); const [error, setError] = useState(undefined); useEffect(() => { let abortController: AbortController | undefined = undefined; async function handleQuery() { if (typeof endpoint === 'undefined') { return; } const cacheKey = options.cacheKey ?? endpoint; if (options.cache && cacheKey in cache._query) { setResult(cache._query[cacheKey] as Result); return; } abortController = new AbortController(); setFetching(true); try { const url = new URL(endpoint, `${window.location.protocol}//${window.location.host}`); const response = await fetch(url.href, { signal: abortController.signal }); if (!response.ok || response.status !== 200) { throw new Error('Failed to fetch sections'); } const data = await response.json(); setResult(data); setError(undefined); if (cache) { setCache(prev => ({ ...prev, _query: { ...prev._query, [cacheKey]: data, }, })); } } catch (e: unknown) { if (!(e instanceof Error)) { e = new Error(String(e)); } if ((e as Error).name === 'AbortError') { return; } setError(e as Error); console.error(e); } finally { setFetching(false); } } void handleQuery(); return () => { if (abortController) { abortController.abort(); } }; }, [endpoint]); function clear() { setResult(undefined); setFetching(false); setError(undefined); } return { data: result, isFetching: fetching, error, clear }; } type WidgetPropsContextValue = WidgetProps & { hide: () => void; show: () => void; }; const WidgetPropsContext = createContext(undefined); export const WidgetPropsProvider = WidgetPropsContext.Provider; export function useWidgetProps() { return useContext(WidgetPropsContext) as WidgetPropsContextValue; }