diff options
| author | MohamedBassem <me@mbassem.com> | 2024-04-23 13:56:35 +0100 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-04-23 13:56:35 +0100 |
| commit | 77b1aba5acc66dfaeb02b08d60d88442336026a6 (patch) | |
| tree | 950f71d7c868869902e742644697e077db734769 /apps/browser-extension/src/components/ListsSelector.tsx | |
| parent | 0e260954c13cfedb03e75d3f0db8a2e839fd008d (diff) | |
| download | karakeep-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.tsx | 107 |
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'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> + ); +} |
