import React, { useEffect, useMemo, 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"; import { useRouter } from "next/router"; import useAccountStore from "@/store/account"; import toast from "react-hot-toast"; import { useTranslation } from "next-i18next"; interface ExtendedTreeItem extends TreeItem { data: Collection; } const CollectionListing = () => { const { t } = useTranslation(); const { collections, updateCollection } = useCollectionStore(); const { account, updateAccount } = useAccountStore(); const router = useRouter(); const currentPath = router.asPath; const initialTree = useMemo(() => { if (collections.length > 0) { return buildTreeFromCollections( collections, router, account.collectionOrder ); } return undefined; }, [collections, router]); const [tree, setTree] = useState(initialTree); useEffect(() => { setTree(initialTree); }, [initialTree]); useEffect(() => { if (account.username) { if ( (!account.collectionOrder || account.collectionOrder.length === 0) && collections.length > 0 ) updateAccount({ ...account, collectionOrder: collections .filter( (e) => e.parentId === null || !collections.find((i) => i.id === e.parentId) ) // Filter out collections with non-null parentId .map((e) => e.id as number), // Use "as number" to assert that e.id is a number }); else { const newCollectionOrder: number[] = [ ...(account.collectionOrder || []), ]; // Start with collections that are in both account.collectionOrder and collections const existingCollectionIds = collections.map((c) => c.id as number); const filteredCollectionOrder = account.collectionOrder.filter((id) => existingCollectionIds.includes(id) ); // Add new collections that are not in account.collectionOrder and meet the specific conditions collections.forEach((collection) => { if ( !filteredCollectionOrder.includes(collection.id as number) && (!collection.parentId || collection.ownerId === account.id) ) { filteredCollectionOrder.push(collection.id as number); } }); // check if the newCollectionOrder is the same as the old one if ( JSON.stringify(newCollectionOrder) !== JSON.stringify(account.collectionOrder) ) { updateAccount({ ...account, collectionOrder: newCollectionOrder, }); } } } }, [collections]); const onExpand = (movedCollectionId: ItemId) => { setTree((currentTree) => mutateTree(currentTree!, movedCollectionId, { isExpanded: true }) ); }; const onCollapse = (movedCollectionId: ItemId) => { setTree((currentTree) => mutateTree(currentTree as TreeData, movedCollectionId, { isExpanded: false, }) ); }; const onDragEnd = async ( source: TreeSourcePosition, destination: TreeDestinationPosition | undefined ) => { if (!destination || !tree) { return; } if ( source.index === destination.index && source.parentId === destination.parentId ) { return; } const movedCollectionId = Number( tree.items[source.parentId].children[source.index] ); const movedCollection = collections.find((c) => c.id === movedCollectionId); const destinationCollection = collections.find( (c) => c.id === Number(destination.parentId) ); if ( (movedCollection?.ownerId !== account.id && destination.parentId !== source.parentId) || (destinationCollection?.ownerId !== account.id && destination.parentId !== "root") ) { return toast.error(t("cant_change_collection_you_dont_own")); } setTree((currentTree) => moveItemOnTree(currentTree!, source, destination)); const updatedCollectionOrder = [...account.collectionOrder]; if (source.parentId !== destination.parentId) { await updateCollection({ ...movedCollection, parentId: destination.parentId && destination.parentId !== "root" ? Number(destination.parentId) : destination.parentId === "root" ? "root" : null, } as any); } if ( destination.index !== undefined && destination.parentId === source.parentId && source.parentId === "root" ) { updatedCollectionOrder.includes(movedCollectionId) && updatedCollectionOrder.splice(source.index, 1); updatedCollectionOrder.splice(destination.index, 0, movedCollectionId); await updateAccount({ ...account, collectionOrder: updatedCollectionOrder, }); } else if ( destination.index !== undefined && destination.parentId === "root" ) { updatedCollectionOrder.splice(destination.index, 0, movedCollectionId); await updateAccount({ ...account, collectionOrder: updatedCollectionOrder, }); } else if ( source.parentId === "root" && destination.parentId && destination.parentId !== "root" ) { updatedCollectionOrder.splice(source.index, 1); await updateAccount({ ...account, collectionOrder: updatedCollectionOrder, }); } }; if (!tree) { return (
{t("you_have_no_collections")}
); } else return ({collection.name}
{collection.isPublic ? ( ) : undefined}