From 77b1aba5acc66dfaeb02b08d60d88442336026a6 Mon Sep 17 00:00:00 2001
From: MohamedBassem <me@mbassem.com>
Date: Tue, 23 Apr 2024 13:56:35 +0100
Subject: feature(extension): Allow adding tags and lists to newly hoarded
 bookmarks

---
 .../src/components/ListsSelector.tsx               | 107 +++++++++++++++++++++
 1 file changed, 107 insertions(+)
 create mode 100644 apps/browser-extension/src/components/ListsSelector.tsx

(limited to 'apps/browser-extension/src/components/ListsSelector.tsx')

diff --git a/apps/browser-extension/src/components/ListsSelector.tsx b/apps/browser-extension/src/components/ListsSelector.tsx
new file mode 100644
index 00000000..adddf4b4
--- /dev/null
+++ b/apps/browser-extension/src/components/ListsSelector.tsx
@@ -0,0 +1,107 @@
+import * as React from "react";
+import { useSet } from "@uidotdev/usehooks";
+import { Check, ChevronsUpDown } from "lucide-react";
+
+import {
+  useAddBookmarkToList,
+  useBookmarkLists,
+  useRemoveBookmarkFromList,
+} from "@hoarder/shared-react/hooks/lists";
+
+import { cn } from "../utils/css";
+import { api } from "../utils/trpc";
+import { Button } from "./ui/button";
+import {
+  Command,
+  CommandEmpty,
+  CommandGroup,
+  CommandInput,
+  CommandItem,
+  CommandList,
+} from "./ui/command";
+import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
+
+export function ListsSelector({ bookmarkId }: { bookmarkId: string }) {
+  const currentlyUpdating = useSet<string>();
+  const [open, setOpen] = React.useState(false);
+
+  const { mutate: addToList } = useAddBookmarkToList();
+  const { mutate: removeFromList } = useRemoveBookmarkFromList();
+  const { data: existingLists } = api.lists.getListsOfBookmark.useQuery({
+    bookmarkId,
+  });
+
+  const { data: allLists } = useBookmarkLists();
+
+  const existingListIds = new Set(existingLists?.lists.map((list) => list.id));
+
+  const toggleList = (listId: string) => {
+    currentlyUpdating.add(listId);
+    if (existingListIds.has(listId)) {
+      removeFromList(
+        { bookmarkId, listId },
+        {
+          onSettled: (_resp, _err, req) => currentlyUpdating.delete(req.listId),
+        },
+      );
+    } else {
+      addToList(
+        { bookmarkId, listId },
+        {
+          onSettled: (_resp, _err, req) => currentlyUpdating.delete(req.listId),
+        },
+      );
+    }
+  };
+
+  return (
+    <Popover open={open} onOpenChange={setOpen}>
+      <PopoverTrigger asChild>
+        <Button
+          variant="outline"
+          role="combobox"
+          aria-expanded={open}
+          className="justify-between"
+        >
+          Add to List...
+          <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+        </Button>
+      </PopoverTrigger>
+      <PopoverContent className="w-[200px] p-0">
+        <Command>
+          <CommandInput placeholder="Search Lists ..." />
+          <CommandList>
+            <CommandEmpty>You don&apos;t have any lists.</CommandEmpty>
+            <CommandGroup>
+              {allLists?.allPaths.map((path) => {
+                const lastItem = path[path.length - 1];
+
+                return (
+                  <CommandItem
+                    key={lastItem.id}
+                    value={lastItem.id}
+                    keywords={[lastItem.name, lastItem.icon]}
+                    onSelect={toggleList}
+                    disabled={currentlyUpdating.has(lastItem.id)}
+                  >
+                    <Check
+                      className={cn(
+                        "mr-2 size-4",
+                        existingListIds.has(lastItem.id)
+                          ? "opacity-100"
+                          : "opacity-0",
+                      )}
+                    />
+                    {path
+                      .map((item) => `${item.icon} ${item.name}`)
+                      .join(" / ")}
+                  </CommandItem>
+                );
+              })}
+            </CommandGroup>
+          </CommandList>
+        </Command>
+      </PopoverContent>
+    </Popover>
+  );
+}
-- 
cgit v1.2.3-70-g09d2

