import React, { Fragment, useEffect, useState } from 'react'; import cn from 'classnames'; import { theme, Loader } from '@veeqo/ui'; import useDropdown from 'hooks/useDropdown'; import { ViewTreeItem } from 'components/ui/SortableViews/SortableViews'; import composeViewChunks from './composeViewChunks'; import View from './View'; import { ViewType, ViewsClassNames, ViewHandlers, CommonViewPropTypes, } from './types'; import { Col, Container, LeftControls, RightControls, Button, Glyph, SortableViews, Dropdown, Wrap, Tooltip, Info, Text, FixedViews, FixedView, LoaderContainer, } from './styled'; type ViewsPropsType = CommonViewPropTypes & ViewHandlers & { viewsClassName?: string; e2eViewsClassName?: string; viewClassName?: string; e2eViewClassName?: string; views: ViewType[]; fixedViews: ViewType[]; sortedCustomViews: ViewType[]; isLoading: boolean; isSortingDropdownEnabled: boolean; handleCreateCustomView: () => void; // via button handleSortingChange: (treeData: ViewTreeItem[]) => void; }; const generateClassNames = (prefix?: string): ViewsClassNames => ({ container: prefix ? `${prefix}-views-container` : undefined, controls: prefix ? `${prefix}-views-controls` : undefined, createButton: prefix ? `${prefix}-create-view-button` : undefined, reorderButton: prefix ? `${prefix}-reorder-views-button` : undefined, loader: prefix ? `${prefix}-views-loader` : undefined, reorderDropdown: prefix ? `${prefix}-reorder-views-dropdown` : undefined, fixedViews: prefix ? `${prefix}-fixed-views` : undefined, fixedView: prefix ? `${prefix}-fixed-view` : undefined, }); const Views = ({ viewsClassName, e2eViewsClassName, viewClassName, e2eViewClassName, views, fixedViews, sortedCustomViews, activeViewKey, includedFilters, hasUnsavedChanges, pageName, isLoading, isSortingDropdownEnabled = true, onSave, onDelete, handleDuplicateView, handleChangeActiveView, handleCreateCustomView, handleCreateCustomViewWithCurrentFilters, handleSortingChange, handleDiscardUnsavedChanges, handleSaveToCurrentView, handleSetDefault, }: ViewsPropsType) => { const { shouldShowDropdown, toggleShouldShowDropdown, closeDropdown } = useDropdown(); const classNames = generateClassNames(viewsClassName); const e2eClassNames = generateClassNames(e2eViewsClassName); const scrollBehavior = window.customViewsScrollBehavior || 'smooth'; const isSortingDropdownEmpty = ( isSortingDropdownEnabled && (!isLoading && sortedCustomViews.length === 0) ); const isSortingDropdownDisabled = ( isSortingDropdownEnabled && (isLoading || isSortingDropdownEmpty) ); const [chunkIndex, setChunkIndex] = useState(0); const [chunks, setChunks] = useState(composeViewChunks({ views })); const [isNewElementVisible, setIsNewElementVisible] = useState(true); const isShowNextControlEnabled = chunkIndex < chunks.length - 1 || (!isNewElementVisible && chunks.length > 1); const isShowPrevControlEnabled = chunkIndex > 0; const handleUpdateChunks = () => setChunks(composeViewChunks({ views })); const handleChunkIndexChange = (newChunkIndex: number, customChunks = chunks) => { const nextChunkKeys = customChunks[newChunkIndex].map((i) => i.key); const customViewElements = document.querySelectorAll('.veeqo-react-view'); const nextChunkElements = Array.from( customViewElements.values(), ).filter((viewEl) => nextChunkKeys.includes(viewEl.dataset.viewKey || '')); const [firstEl] = nextChunkElements; if (firstEl) firstEl.scrollIntoView({ behavior: scrollBehavior, block: 'nearest', inline: 'start' }); setChunkIndex(newChunkIndex); setIsNewElementVisible(true); }; useEffect(() => { setChunks(composeViewChunks({ views })); // eslint-disable-next-line }, [activeViewKey]); useEffect(() => { const newChunks = composeViewChunks({ views }); setChunks(newChunks); const lastChunkIndex = newChunks.length - 1; const isNewViewAdded = newChunks.length > chunks.length || ( newChunks.length === chunks.length && newChunks[lastChunkIndex].length > chunks[lastChunkIndex].length ); const isNewViewNotCopy = views.length > 0 ? !views[views.length - 1].label.includes('copy') : true; if (isNewViewAdded && isNewViewNotCopy) { handleChunkIndexChange(lastChunkIndex, newChunks); } if (!isNewViewNotCopy) setIsNewElementVisible(false); // eslint-disable-next-line }, [views]); const handleShowNextChunk = () => ( isShowNextControlEnabled && !isLoading ? handleChunkIndexChange(chunkIndex + 1 === chunks.length ? chunkIndex : chunkIndex + 1) : null ); const handleShowPrevChunk = () => ( isShowPrevControlEnabled && !isLoading ? handleChunkIndexChange(chunkIndex - 1) : null ); const getView = (view: ViewType) => ( ); return ( {!isLoading ? ( <> {fixedViews.map(getView)} {sortedCustomViews.map(getView)} ) : ( )} Fixed views {fixedViews.map((view) => ( ))} Fixed views cannot be edited / deleted ({ id: view.key, isDefault: view.default, ...view, }))} onChange={handleSortingChange} /> ); }; export default Views;