95 lines
2.8 KiB
JavaScript
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;
|
|
};
|