import deepmerge from 'deepmerge' import * as React from 'react' import {deepmergeArrayIdMerge} from '../../../../../utils/helper' import {IJaenSectionItem} from '../../../types' import {findSection} from '../../../utils' import {useAppSelector} from '../../redux' import {useJaenPageContext} from '../page' import {useJaenSectionContext} from './context' export function useSectionData( sectionName: string, options?: {forceUpdate?: boolean} ) { const {forceUpdate = false} = options || {} const jaenSection = useJaenSectionContext() const sectionPath = React.useMemo( () => (jaenSection?.path || []).concat({ fieldName: sectionName, sectionId: jaenSection?.id }), [] ) const {jaenPage} = useJaenPageContext() if (!jaenPage.id) { throw new Error( 'JaenPage id is undefined! connectField must be used within a JaenPage' ) } const staticSection = React.useMemo( () => findSection(jaenPage.sections || [], sectionPath), [jaenPage.sections, sectionPath] ) const dynamicSection = useAppSelector( state => findSection( state.internal.pages.nodes[jaenPage.id]?.sections || [], sectionPath ), (l, r) => { if (forceUpdate) { return false } if (!l && !r) { return true } if (!l || !r) { return false } const shouldUpdate = JSON.stringify(Object.keys(l.items)) !== JSON.stringify(Object.keys(r.items)) if (shouldUpdate) { return false } for (let i = 0; i < l.items.length; i++) { const lItem = l.items[i] const rItem = r.items[i] if (lItem.deleted || rItem.deleted) { return false } } return true } ) const section = React.useMemo(() => { const mergedSection = deepmerge(staticSection || {}, dynamicSection || {}, { arrayMerge: deepmergeArrayIdMerge }) const sectionItemsDict: { [id: string]: IJaenSectionItem } = {} mergedSection?.items?.forEach(item => { sectionItemsDict[item.id] = item }) const orderedSectionItems: IJaenSectionItem[] = [] let ptrHead = mergedSection?.ptrHead let i = 0 while (ptrHead && i < 50) { const item = sectionItemsDict[ptrHead] if (!item) { throw new Error(`ptrHead ${ptrHead} is not found in section items!`) } i++ ptrHead = item.ptrNext if (item.deleted) { continue } orderedSectionItems.push(item) } mergedSection.items = orderedSectionItems return mergedSection }, [staticSection, dynamicSection]) return { data: section, sectionPath } }