95 lines
2.8 KiB
JavaScript

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 <SvodContext.Provider value={value}>{children}</SvodContext.Provider>;
};
export const useSvod = () => {
const context = useContext(SvodContext);
if (!context) throw new Error('useSvod must be used within SvodProvider');
return context;
};