import { useEffect, useMemo, useRef, useState } from 'react'; import { useWixPatternsRouter } from '../providers/WixPatternsRouterProvider'; import { ICollectionComponentState } from '../state/ICollectionComponentState'; import { useWixPatternsContainer } from '@wix/bex-core/react'; import { CollectionState, RemoveToast } from '@wix/bex-core'; import { useSelector } from '../useSelector'; export function useSyncCollectionOnEntityReturn< T, S extends ICollectionComponentState, >({ cachedState, updateCollection, checkIfViewSynced, getEntityFromRouterState, getCollectionsToUpdate, }: { cachedState?: S; updateCollection: (collectionToUpdate: CollectionState, entity: T) => void; checkIfViewSynced: ( collectionToUpdate: CollectionState, entity: T, ) => Promise; getEntityFromRouterState: (state: { _updatedEntity?: T; _createdEntity?: T; }) => T | undefined; getCollectionsToUpdate?: (state: S, entity: T) => CollectionState[] | null; }) { const container = useWixPatternsContainer(); const router = useWixPatternsRouter(); const timeoutRef = useRef(); const routeState = useSelector(() => router?.currentState); const entity = useMemo( () => (routeState ? getEntityFromRouterState(routeState) : null), [getEntityFromRouterState, routeState], ); const collections = useMemo(() => { if (!cachedState) { return null; } if (!entity) { return [cachedState.toolbar.collection]; } return ( getCollectionsToUpdate?.(cachedState, entity) || [ cachedState.toolbar.collection, ] ); }, [cachedState, entity]); const [currentToast, setCurrentToast] = useState<{ remove: RemoveToast; } | null>(null); const showViewUpdatedToast = () => { const toast = container.showToast?.({ type: 'STANDARD', timeout: 'NONE', message: container.translate( 'cairo.updatedView.collectionPage.toast.desc', ), onCloseClick: () => { setCurrentToast(null); }, biName: 'cairo-collection-page-updated-toast', action: { text: container.translate('cairo.updatedView.collectionPage.toast.cta'), onClick: () => { collections?.forEach((collection) => collection.clearResultAndMoveToStart({ force: true }), ); setCurrentToast(null); }, }, }); if (toast) { setCurrentToast(toast); } }; useEffect(() => { if (entity && collections && router) { collections.forEach((collection) => { updateCollection(collection, entity); }); const timeoutId = window.setTimeout(() => { Promise.all( collections.map((collection) => checkIfViewSynced(collection, entity), ), ).then((results) => { const isViewSynced = results.some(Boolean) && !router.isCollectionStale; if (!isViewSynced) { router.isCollectionStale = true; showViewUpdatedToast(); } }); }, 3000); timeoutRef.current = timeoutId; } else if (router?.isCollectionStale) { showViewUpdatedToast(); } }, [collections, entity]); useEffect(() => { if (!currentToast || !cachedState) { return () => {}; } const removeToast = () => { currentToast?.remove(); setCurrentToast(null); }; const onFetch = () => { removeToast(); if (router) { router.isUsingCache = false; router.isCollectionStale = false; } }; collections?.forEach((collection) => { collection?.emitter.on('fetch', () => { onFetch(); }); }); return () => { collections?.forEach((collection) => { collection?.emitter.off('fetch', () => { onFetch(); }); }); }; }, [currentToast, collections]); useEffect(() => { return () => { if (timeoutRef.current) { window.clearTimeout(timeoutRef.current); } currentToast?.remove(); }; }, [currentToast]); }