import React, { useEffect, useState } from "react"; import Tree, { mutateTree, moveItemOnTree, RenderItemParams, TreeItem, TreeData, ItemId, TreeSourcePosition, TreeDestinationPosition, } from "@atlaskit/tree"; import useCollectionStore from "@/store/collections"; import { Collection } from "@prisma/client"; import Link from "next/link"; import { CollectionIncludingMembersAndLinkCount } from "@/types/global"; interface ExtendedTreeItem extends TreeItem { data: Collection; } const DragDropWithNestingTree = () => { const [tree, setTree] = useState(); const { collections } = useCollectionStore(); useEffect(() => { const initialTree = buildTreeFromCollections(collections); collections[0] && setTree(initialTree); }, [collections]); const onExpand = (itemId: ItemId) => { if (tree) { setTree((currentTree) => mutateTree(currentTree!, itemId, { isExpanded: true }) ); } }; const onCollapse = (itemId: ItemId) => { if (tree) { setTree((currentTree) => mutateTree(currentTree as TreeData, itemId, { isExpanded: false }) ); } }; const onDragEnd = ( source: TreeSourcePosition, destination: TreeDestinationPosition | undefined ) => { if (!destination || !tree) { return; } setTree((currentTree) => moveItemOnTree(currentTree!, source, destination)); }; if (!tree) { return
Loading...
; } return ( ); }; export default DragDropWithNestingTree; const renderItem = ({ item, onExpand, onCollapse, provided, }: RenderItemParams) => { const collection = item.data; return (
{Icon(item as ExtendedTreeItem, onExpand, onCollapse)}

{collection.name}

{collection.isPublic ? ( ) : undefined}
{collection._count?.links}
); }; const Icon = ( item: ExtendedTreeItem, onExpand: (id: ItemId) => void, onCollapse: (id: ItemId) => void ) => { if (item.children && item.children.length > 0) { return item.isExpanded ? ( ) : ( ); } // return ; return <>; }; const buildTreeFromCollections = ( collections: CollectionIncludingMembersAndLinkCount[] ): TreeData => { const items: { [key: string]: ExtendedTreeItem } = collections.reduce( (acc: any, collection) => { acc[collection.id as number] = { id: collection.id, children: [], hasChildren: false, isExpanded: false, data: { id: collection.id, name: collection.name, description: collection.description, color: collection.color, isPublic: collection.isPublic, ownerId: collection.ownerId, createdAt: collection.createdAt, updatedAt: collection.updatedAt, _count: { links: collection._count?.links, }, }, }; return acc; }, {} ); collections.forEach((collection) => { const parentId = collection.parentId; if (parentId && items[parentId] && collection.id) { items[parentId].children.push(collection.id); items[parentId].hasChildren = true; } }); const rootId = "root"; items[rootId] = { id: rootId, children: (collections .filter((c) => c.parentId === null) .map((c) => c.id) || "") as unknown as string[], hasChildren: true, isExpanded: true, data: { name: "Root" } as Collection, }; return { rootId, items }; };