aboutsummaryrefslogtreecommitdiffstats
path: root/apps/browser-extension/src/components/ListsSelector.tsx
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-04-23 13:56:35 +0100
committerMohamedBassem <me@mbassem.com>2024-04-23 13:56:35 +0100
commit77b1aba5acc66dfaeb02b08d60d88442336026a6 (patch)
tree950f71d7c868869902e742644697e077db734769 /apps/browser-extension/src/components/ListsSelector.tsx
parent0e260954c13cfedb03e75d3f0db8a2e839fd008d (diff)
downloadkarakeep-77b1aba5acc66dfaeb02b08d60d88442336026a6.tar.zst
feature(extension): Allow adding tags and lists to newly hoarded bookmarks
Diffstat (limited to 'apps/browser-extension/src/components/ListsSelector.tsx')
-rw-r--r--apps/browser-extension/src/components/ListsSelector.tsx107
1 files changed, 107 insertions, 0 deletions
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>
+ );
+}