import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import { SummaryApi } from '../../api/summary'; const SvodContext = createContext(null); const DEFAULT_SHEET_VALUES = ['MAIN', 'FORM_1', 'FORM_2', 'FORM_3', 'FORM_4']; const createDefaultFilters = () => ({ year: new Date().getFullYear(), selectedOrganizations: [], search: '', }); const createInitialFilters = (sheetValues) => Object.fromEntries(sheetValues.map((sheet) => [sheet, createDefaultFilters()])); const createCacheKey = (year, organizationIds) => JSON.stringify([year, organizationIds.map(String).sort()]); const getSheetCache = (cache, sheet) => { if (!cache.has(sheet)) cache.set(sheet, new Map()); return cache.get(sheet); }; export const SvodProvider = ({ children, summaryNumber = 1, sheetValues = DEFAULT_SHEET_VALUES }) => { const [filtersBySheet, setFiltersBySheet] = useState(() => createInitialFilters(sheetValues)); const summaryCacheRef = useRef(new Map()); useEffect( () => () => { summaryCacheRef.current.clear(); }, [], ); const getSheetFilters = useCallback((sheet) => filtersBySheet[sheet] || createDefaultFilters(), [filtersBySheet]); const updateSheetFilters = useCallback((sheet, changes) => { setFiltersBySheet((currentFilters) => ({ ...currentFilters, [sheet]: { ...(currentFilters[sheet] || createDefaultFilters()), ...changes, }, })); }, []); const getSummary = useCallback( (sheet, year, organizationIds = []) => { const sheetCache = getSheetCache(summaryCacheRef.current, sheet); const cacheKey = createCacheKey(year, organizationIds); const cachedRequest = sheetCache.get(cacheKey); if (cachedRequest) return cachedRequest; const request = SummaryApi.get(summaryNumber, sheet, year, organizationIds) .then((response) => { if (sheetCache.get(cacheKey) === request) { sheetCache.set(cacheKey, Promise.resolve(response)); } return response; }) .catch((error) => { if (sheetCache.get(cacheKey) === request) { sheetCache.delete(cacheKey); } throw error; }); sheetCache.set(cacheKey, request); return request; }, [summaryNumber], ); const invalidateSummary = useCallback((sheet, year, organizationIds = []) => { summaryCacheRef.current.get(sheet)?.delete(createCacheKey(year, organizationIds)); }, []); const value = useMemo( () => ({ getSheetFilters, updateSheetFilters, getSummary, invalidateSummary, }), [getSheetFilters, getSummary, invalidateSummary, updateSheetFilters], ); return {children}; }; export const useSvod = () => { const context = useContext(SvodContext); if (!context) throw new Error('useSvod must be used within SvodProvider'); return context; };