import { FC, useCallback, useRef, useState } from 'react'; import { FaArrowsAlt, FaCaretDown, FaCaretUp, FaPlus, FaStar, FaTrash } from 'react-icons/fa'; import { ICatalogNode, LocalizeText } from '../../../../api'; import { useCatalog, useCatalogFavorites } from '../../../../hooks'; import { useCatalogAdmin } from '../../CatalogAdminContext'; import { CatalogIconView } from '../catalog-icon/CatalogIconView'; import { CatalogNavigationSetView } from './CatalogNavigationSetView'; export interface CatalogNavigationItemViewProps { node: ICatalogNode; child?: boolean; } export const CatalogNavigationItemView: FC = props => { const { node = null, child = false } = props; const { activateNode = null } = useCatalog(); const catalogAdmin = useCatalogAdmin(); const adminMode = catalogAdmin?.adminMode ?? false; const { isFavoritePage, toggleFavoritePage } = useCatalogFavorites(); const isFav = node ? isFavoritePage(node.pageId) : false; const [ isDragOver, setIsDragOver ] = useState(false); const dragRef = useRef(null); const handleDragStart = useCallback((e: React.DragEvent) => { if(!adminMode) return; e.dataTransfer.setData('text/plain', JSON.stringify({ pageId: node.pageId, parentId: node.parent?.pageId ?? -1 })); e.dataTransfer.effectAllowed = 'move'; }, [ adminMode, node ]); const handleDragOver = useCallback((e: React.DragEvent) => { if(!adminMode) return; e.preventDefault(); e.dataTransfer.dropEffect = 'move'; setIsDragOver(true); }, [ adminMode ]); const handleDragLeave = useCallback(() => { setIsDragOver(false); }, []); const handleDrop = useCallback((e: React.DragEvent) => { if(!adminMode) return; e.preventDefault(); setIsDragOver(false); try { const data = JSON.parse(e.dataTransfer.getData('text/plain')); if(data.pageId && data.pageId !== node.pageId) { // Drop onto a branch = reparent under this node // Drop onto a leaf = reorder as sibling const targetParentId = node.isBranch ? node.pageId : (node.parent?.pageId ?? -1); const targetIndex = node.isBranch ? 0 : (node.parent?.children?.indexOf(node) ?? 0); catalogAdmin?.reorderPage(data.pageId, targetParentId, targetIndex); } } catch(err) { // Invalid drag data } }, [ adminMode, node, catalogAdmin ]); return (
activateNode(node) } onDragLeave={ adminMode ? handleDragLeave : undefined } onDragOver={ adminMode ? handleDragOver : undefined } onDragStart={ adminMode ? handleDragStart : undefined } onDrop={ adminMode ? handleDrop : undefined } > { adminMode && }
{ node.localization } { adminMode &&
{ e.stopPropagation(); catalogAdmin.createPage({ caption: 'New Page', pageLayout: 'default_3x3', minRank: 1, visible: '1', enabled: '1', orderNum: 0, parentId: node.pageId, }); } } /> { e.stopPropagation(); if(confirm(LocalizeText('catalog.admin.delete.page.confirm', [ 'name' ], [ node.localization ]))) { catalogAdmin.deletePage(node.pageId); } } } />
} { !adminMode && node.pageId > 0 && { e.stopPropagation(); toggleFavoritePage(node.pageId); } } /> } { node.isBranch && { node.isOpen ? : } }
{ node.isOpen && node.isBranch && }
); };