From e0999f701cd1834c3d940113cd8dd5247c5fe95f Mon Sep 17 00:00:00 2001
From: Mohamed Bassem <me@mbassem.com>
Date: Fri, 19 Apr 2024 00:09:27 +0100
Subject: feature: Nested lists (#110). Fixes #62

* feature: Add support for nested lists

* prevent moving the parent to a subtree
---
 apps/web/components/dashboard/sidebar/AllLists.tsx | 79 ++++++++++++++++------
 1 file changed, 57 insertions(+), 22 deletions(-)

(limited to 'apps/web/components/dashboard/sidebar/AllLists.tsx')

diff --git a/apps/web/components/dashboard/sidebar/AllLists.tsx b/apps/web/components/dashboard/sidebar/AllLists.tsx
index 6ab42851..b1c6ddb2 100644
--- a/apps/web/components/dashboard/sidebar/AllLists.tsx
+++ b/apps/web/components/dashboard/sidebar/AllLists.tsx
@@ -1,12 +1,18 @@
 "use client";
 
+import { useCallback } from "react";
 import Link from "next/link";
-import { api } from "@/lib/trpc";
-import { Plus } from "lucide-react";
+import { usePathname } from "next/navigation";
+import { Button } from "@/components/ui/button";
+import { CollapsibleTriggerTriangle } from "@/components/ui/collapsible";
+import { MoreHorizontal, Plus } from "lucide-react";
 
 import type { ZBookmarkList } from "@hoarder/shared/types/lists";
+import { ZBookmarkListTreeNode } from "@hoarder/shared/utils/listUtils";
 
-import NewListModal, { useNewListModal } from "./NewListModal";
+import { CollapsibleBookmarkLists } from "../lists/CollapsibleBookmarkLists";
+import { EditListModal } from "../lists/EditListModal";
+import { ListOptions } from "../lists/ListOptions";
 import SidebarItem from "./SidebarItem";
 
 export default function AllLists({
@@ -14,21 +20,20 @@ export default function AllLists({
 }: {
   initialData: { lists: ZBookmarkList[] };
 }) {
-  let { data: lists } = api.lists.list.useQuery(undefined, {
-    initialData,
-  });
-  // TODO: This seems to be a bug in react query
-  lists ||= initialData;
-  const { setOpen } = useNewListModal();
-
+  const pathName = usePathname();
+  const isNodeOpen = useCallback(
+    (node: ZBookmarkListTreeNode) => pathName.includes(node.item.id),
+    [pathName],
+  );
   return (
     <ul className="max-h-full gap-y-2 overflow-auto text-sm font-medium">
-      <NewListModal />
       <li className="flex justify-between pb-2 font-bold">
         <p>Lists</p>
-        <Link href="#" onClick={() => setOpen(true)}>
-          <Plus />
-        </Link>
+        <EditListModal>
+          <Link href="#">
+            <Plus />
+          </Link>
+        </EditListModal>
       </li>
       <SidebarItem
         logo={<span className="text-lg">📋</span>}
@@ -48,15 +53,45 @@ export default function AllLists({
         path={`/dashboard/archive`}
         className="py-0.5"
       />
-      {lists.lists.map((l) => (
-        <SidebarItem
-          key={l.id}
-          logo={<span className="text-lg"> {l.icon}</span>}
-          name={l.name}
-          path={`/dashboard/lists/${l.id}`}
-          className="py-0.5"
+
+      {
+        <CollapsibleBookmarkLists
+          initialData={initialData.lists}
+          isOpenFunc={isNodeOpen}
+          render={({ item: node, level, open }) => (
+            <SidebarItem
+              collapseButton={
+                node.children.length > 0 && (
+                  <CollapsibleTriggerTriangle
+                    className="absolute left-0 top-1/2 size-2 -translate-y-1/2"
+                    open={open}
+                  />
+                )
+              }
+              logo={
+                <span className="flex">
+                  <span className="text-lg"> {node.item.icon}</span>
+                </span>
+              }
+              name={node.item.name}
+              path={`/dashboard/lists/${node.item.id}`}
+              right={
+                <ListOptions list={node.item}>
+                  <Button
+                    size="none"
+                    variant="ghost"
+                    className="invisible group-hover:visible"
+                  >
+                    <MoreHorizontal className="size-4" />
+                  </Button>
+                </ListOptions>
+              }
+              className="group py-0.5"
+              style={{ marginLeft: `${level * 1}rem` }}
+            />
+          )}
         />
-      ))}
+      }
     </ul>
   );
 }
-- 
cgit v1.2.3-70-g09d2

