import { useEffect } from 'react'; import { useSearchParams } from 'react-router-dom'; import { useRecoilCallback } from 'recoil'; import { useFindManyObjects } from '@/metadata/hooks/useFindManyObjects'; import { PaginatedObjectTypeResults } from '@/metadata/types/PaginatedObjectTypeResults'; import { assertNotNull } from '~/utils/assert'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { useView } from '../hooks/useView'; import { useViewGetStates } from '../hooks/useViewGetStates'; import { availableFieldDefinitionsScopedState } from '../states/availableFieldDefinitionsScopedState'; import { availableFilterDefinitionsScopedState } from '../states/availableFilterDefinitionsScopedState'; import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState'; import { onViewFieldsChangeScopedState } from '../states/onViewFieldsChangeScopedState'; import { onViewFiltersChangeScopedState } from '../states/onViewFiltersChangeScopedState'; import { onViewSortsChangeScopedState } from '../states/onViewSortsChangeScopedState'; import { savedViewFieldsScopedFamilyState } from '../states/savedViewFieldsScopedFamilyState'; import { savedViewFiltersScopedFamilyState } from '../states/savedViewFiltersScopedFamilyState'; import { savedViewSortsScopedFamilyState } from '../states/savedViewSortsScopedFamilyState'; import { viewsScopedState } from '../states/viewsScopedState'; import { View } from '../types/View'; import { ViewField } from '../types/ViewField'; import { ViewFilter } from '../types/ViewFilter'; import { ViewSort } from '../types/ViewSort'; export const ViewBarEffect = () => { const { scopeId: viewScopeId, setCurrentViewFields, setSavedViewFields, setCurrentViewFilters, setSavedViewFilters, setCurrentViewSorts, setSavedViewSorts, currentViewId, setViews, loadView, changeViewInUrl, setCurrentViewId, } = useView(); const [searchParams] = useSearchParams(); const currentViewIdFromUrl = searchParams.get('view'); const { viewType, viewObjectId } = useViewGetStates(viewScopeId); useFindManyObjects({ objectNamePlural: 'viewsV2', filter: { type: { eq: viewType }, objectId: { eq: viewObjectId } }, onCompleted: useRecoilCallback( ({ snapshot }) => async (data: PaginatedObjectTypeResults) => { const nextViews = data.edges.map((view) => ({ id: view.node.id, name: view.node.name, objectId: view.node.objectId, })); const views = snapshot .getLoadable(viewsScopedState({ scopeId: viewScopeId })) .getValue(); if (!isDeeplyEqual(views, nextViews)) setViews(nextViews); if (!nextViews.length) return; if (!currentViewIdFromUrl) return changeViewInUrl(nextViews[0].id); }, ), }); useFindManyObjects({ skip: !currentViewId, objectNamePlural: 'viewFieldsV2', filter: { viewId: { eq: currentViewId } }, onCompleted: useRecoilCallback( ({ snapshot }) => async (data: PaginatedObjectTypeResults) => { const availableFields = snapshot .getLoadable( availableFieldDefinitionsScopedState({ scopeId: viewScopeId }), ) .getValue(); const onViewFieldsChange = snapshot .getLoadable( onViewFieldsChangeScopedState({ scopeId: viewScopeId }), ) .getValue(); if (!availableFields || !currentViewId) { return; } const savedViewFields = snapshot .getLoadable( savedViewFieldsScopedFamilyState({ scopeId: viewScopeId, familyKey: currentViewId, }), ) .getValue(); const queriedViewFields = data.edges .map((viewField) => viewField.node) .filter(assertNotNull); if (!isDeeplyEqual(savedViewFields, queriedViewFields)) { setCurrentViewFields?.(queriedViewFields); setSavedViewFields?.(queriedViewFields); onViewFieldsChange?.(queriedViewFields); } }, ), }); useFindManyObjects({ skip: !currentViewId, objectNamePlural: 'viewFiltersV2', filter: { viewId: { eq: currentViewId } }, onCompleted: useRecoilCallback( ({ snapshot }) => async (data: PaginatedObjectTypeResults>) => { const availableFilterDefinitions = snapshot .getLoadable( availableFilterDefinitionsScopedState({ scopeId: viewScopeId }), ) .getValue(); if (!availableFilterDefinitions || !currentViewId) { return; } const savedViewFilters = snapshot .getLoadable( savedViewFiltersScopedFamilyState({ scopeId: viewScopeId, familyKey: currentViewId, }), ) .getValue(); const onViewFiltersChange = snapshot .getLoadable( onViewFiltersChangeScopedState({ scopeId: viewScopeId }), ) .getValue(); const queriedViewFilters = data.edges .map(({ node }) => { const availableFilterDefinition = availableFilterDefinitions.find( (filterDefinition) => filterDefinition.fieldId === node.fieldId, ); if (!availableFilterDefinition) return null; return { ...node, displayValue: node.displayValue ?? node.value, definition: availableFilterDefinition, }; }) .filter(assertNotNull); if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) { setSavedViewFilters?.(queriedViewFilters); setCurrentViewFilters?.(queriedViewFilters); onViewFiltersChange?.(queriedViewFilters); } }, ), }); useFindManyObjects({ skip: !currentViewId, objectNamePlural: 'viewSortsV2', filter: { viewId: { eq: currentViewId } }, onCompleted: useRecoilCallback( ({ snapshot }) => async (data: PaginatedObjectTypeResults>) => { const availableSortDefinitions = snapshot .getLoadable( availableSortDefinitionsScopedState({ scopeId: viewScopeId }), ) .getValue(); if (!availableSortDefinitions || !currentViewId) { return; } const savedViewSorts = snapshot .getLoadable( savedViewSortsScopedFamilyState({ scopeId: viewScopeId, familyKey: currentViewId, }), ) .getValue(); const onViewSortsChange = snapshot .getLoadable(onViewSortsChangeScopedState({ scopeId: viewScopeId })) .getValue(); const queriedViewSorts = data.edges .map(({ node }) => { const availableSortDefinition = availableSortDefinitions.find( (sort) => sort.fieldId === node.fieldId, ); if (!availableSortDefinition) return null; return { id: node.id, fieldId: node.fieldId, direction: node.direction, definition: availableSortDefinition, }; }) .filter(assertNotNull); if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) { setSavedViewSorts?.(queriedViewSorts); setCurrentViewSorts?.(queriedViewSorts); onViewSortsChange?.(queriedViewSorts); } }, ), }); useEffect(() => { if (!currentViewIdFromUrl) return; loadView(currentViewIdFromUrl); }, [currentViewIdFromUrl, loadView, setCurrentViewId]); return <>; };