import React, { useCallback, useState, FC, useEffect, memo, } from 'react'; import nodePath from 'path'; import { useTranslation } from 'react-i18next'; import { ItemNode } from './ItemNode'; import { IPageHasId } from '~/interfaces/page'; import { useSWRxPageChildren } from '../../../stores/page-listing'; import { usePageId } from '../../../stores/context'; import ClosableTextInput, { AlertInfo, AlertType } from '../../Common/ClosableTextInput'; import PageItemControl from '../../Common/Dropdown/PageItemControl'; interface ItemProps { itemNode: ItemNode isOpen?: boolean } // Utility to mark target const markTarget = (children: ItemNode[], targetId: string): void => { children.forEach((node) => { if (node.page._id === targetId) { node.page.isTarget = true; } return node; }); return; }; type ItemControlProps = { page: Partial onClickDeleteButtonHandler?(): void onClickPlusButtonHandler?(): void } const ItemControl: FC = memo((props: ItemControlProps) => { const onClickPlusButton = () => { if (props.onClickPlusButtonHandler == null) { return; } props.onClickPlusButtonHandler(); }; const onClickDeleteButton = () => { if (props.onClickDeleteButtonHandler == null) { return; } props.onClickDeleteButtonHandler(); }; if (props.page == null) { return <>; } return ( <> ); }); const ItemCount: FC = () => { return ( <> {/* TODO: consider to show the number of children pages */} ); }; const Item: FC = (props: ItemProps) => { const { t } = useTranslation(); const { itemNode, isOpen: _isOpen = false } = props; const { page, children } = itemNode; const [currentChildren, setCurrentChildren] = useState(children); const [isOpen, setIsOpen] = useState(_isOpen); const [isNewPageInputShown, setNewPageInputShown] = useState(false); const { data: targetId } = usePageId(); const { data, error } = useSWRxPageChildren(isOpen ? page._id : null); const hasChildren = useCallback((): boolean => { return currentChildren != null && currentChildren.length > 0; }, [currentChildren]); const onClickLoadChildren = useCallback(async() => { setIsOpen(!isOpen); }, [isOpen]); const onClickDeleteButtonHandler = useCallback(() => { console.log('Show delete modal'); }, []); const inputValidator = (title: string | null): AlertInfo | null => { if (title == null || title === '') { return { type: AlertType.ERROR, message: t('Page title is required'), }; } return null; }; // TODO: go to create page page const onPressEnterHandler = () => { console.log('Enter key was pressed!'); }; // didMount useEffect(() => { if (hasChildren()) setIsOpen(true); }, []); /* * Make sure itemNode.children and currentChildren are synced */ useEffect(() => { if (children.length > currentChildren.length) { markTarget(children, targetId); setCurrentChildren(children); } }, []); /* * When swr fetch succeeded */ useEffect(() => { if (isOpen && error == null && data != null) { const newChildren = ItemNode.generateNodesFromPages(data.children); markTarget(newChildren, targetId); setCurrentChildren(newChildren); } }, [data]); // TODO: improve style const opacityStyle = { opacity: 1.0 }; if (page.isTarget) opacityStyle.opacity = 0.7; const buttonClass = isOpen ? 'rotate' : ''; return (

{nodePath.basename(page.path as string) || '/'}

{ setNewPageInputShown(true) }} />
{ setNewPageInputShown(false) }} onPressEnter={onPressEnterHandler} inputValidator={inputValidator} /> { isOpen && hasChildren() && currentChildren.map(node => ( )) }
); }; export default Item;