aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx12
-rw-r--r--apps/web/components/dashboard/bookmarks/ManageListsModal.tsx (renamed from apps/web/components/dashboard/bookmarks/AddToListModal.tsx)91
-rw-r--r--apps/web/components/dashboard/lists/BookmarkListSelector.tsx7
3 files changed, 95 insertions, 15 deletions
diff --git a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
index 6f07107b..e5f38eae 100644
--- a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
+++ b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
@@ -33,9 +33,9 @@ import {
import { useRemoveBookmarkFromList } from "@hoarder/shared-react/hooks//lists";
import { useBookmarkGridContext } from "@hoarder/shared-react/hooks/bookmark-grid-context";
-import { useAddToListModal } from "./AddToListModal";
import { BookmarkedTextEditor } from "./BookmarkedTextEditor";
import { ArchivedActionIcon, FavouritedActionIcon } from "./icons";
+import { useManageListsModal } from "./ManageListsModal";
import { useTagModel } from "./TagModal";
export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
@@ -46,8 +46,8 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
const { setOpen: setTagModalIsOpen, content: tagModal } =
useTagModel(bookmark);
- const { setOpen: setAddToListModalOpen, content: addToListModal } =
- useAddToListModal(bookmark.id);
+ const { setOpen: setManageListsModalOpen, content: manageListsModal } =
+ useManageListsModal(bookmark.id);
const [isTextEditorOpen, setTextEditorOpen] = useState(false);
@@ -99,7 +99,7 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
return (
<>
{tagModal}
- {addToListModal}
+ {manageListsModal}
<BookmarkedTextEditor
bookmark={bookmark}
open={isTextEditorOpen}
@@ -171,9 +171,9 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
<span>Edit Tags</span>
</DropdownMenuItem>
- <DropdownMenuItem onClick={() => setAddToListModalOpen(true)}>
+ <DropdownMenuItem onClick={() => setManageListsModalOpen(true)}>
<List className="mr-2 size-4" />
- <span>Add to List</span>
+ <span>Manage Lists</span>
</DropdownMenuItem>
{listId && (
diff --git a/apps/web/components/dashboard/bookmarks/AddToListModal.tsx b/apps/web/components/dashboard/bookmarks/ManageListsModal.tsx
index 3b8a6700..a906aee8 100644
--- a/apps/web/components/dashboard/bookmarks/AddToListModal.tsx
+++ b/apps/web/components/dashboard/bookmarks/ManageListsModal.tsx
@@ -17,15 +17,21 @@ import {
FormMessage,
} from "@/components/ui/form";
import { toast } from "@/components/ui/use-toast";
+import { api } from "@/lib/trpc";
import { zodResolver } from "@hookform/resolvers/zod";
+import { X } from "lucide-react";
import { useForm } from "react-hook-form";
import { z } from "zod";
-import { useAddBookmarkToList } from "@hoarder/shared-react/hooks/lists";
+import {
+ useAddBookmarkToList,
+ useBookmarkLists,
+ useRemoveBookmarkFromList,
+} from "@hoarder/shared-react/hooks/lists";
import { BookmarkListSelector } from "../lists/BookmarkListSelector";
-export default function AddToListModal({
+export default function ManageListsModal({
bookmarkId,
open,
setOpen,
@@ -41,15 +47,50 @@ export default function AddToListModal({
});
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
+ defaultValues: {
+ listId: undefined,
+ },
});
+ const { data: allLists } = useBookmarkLists(undefined, { enabled: open });
+
+ const { data: alreadyInList } = api.lists.getListsOfBookmark.useQuery(
+ {
+ bookmarkId,
+ },
+ { enabled: open },
+ );
+
const { mutate: addToList, isPending: isAddingToListPending } =
useAddBookmarkToList({
onSuccess: () => {
toast({
description: "List has been updated!",
});
- setOpen(false);
+ form.resetField("listId");
+ },
+ onError: (e) => {
+ if (e.data?.code == "BAD_REQUEST") {
+ toast({
+ variant: "destructive",
+ description: e.message,
+ });
+ } else {
+ toast({
+ variant: "destructive",
+ title: "Something went wrong",
+ });
+ }
+ },
+ });
+
+ const { mutate: deleteFromList, isPending: isDeleteFromListPending } =
+ useRemoveBookmarkFromList({
+ onSuccess: () => {
+ toast({
+ description: "List has been updated!",
+ });
+ form.resetField("listId");
},
onError: (e) => {
if (e.data?.code == "BAD_REQUEST") {
@@ -79,10 +120,38 @@ export default function AddToListModal({
})}
>
<DialogHeader>
- <DialogTitle>Add to List</DialogTitle>
+ <DialogTitle>Manage Lists</DialogTitle>
</DialogHeader>
+ {allLists && (
+ <ul className="flex flex-col gap-2 pb-2 pt-4">
+ {alreadyInList?.lists.map((list) => (
+ <li
+ key={list.id}
+ className="flex items-center justify-between rounded-lg border border-border bg-background px-2 py-1 text-foreground"
+ >
+ <p>
+ {allLists
+ .getPathById(list.id)!
+ .map((l) => `${l.icon} ${l.name}`)
+ .join(" / ")}
+ </p>
+ <ActionButton
+ type="button"
+ variant="ghost"
+ size="sm"
+ loading={isDeleteFromListPending}
+ onClick={() =>
+ deleteFromList({ bookmarkId, listId: list.id })
+ }
+ >
+ <X className="size-4" />
+ </ActionButton>
+ </li>
+ ))}
+ </ul>
+ )}
- <div className="py-4">
+ <div className="pb-4">
<FormField
control={form.control}
name="listId"
@@ -90,7 +159,13 @@ export default function AddToListModal({
return (
<FormItem>
<FormControl>
- <BookmarkListSelector onChange={field.onChange} />
+ <BookmarkListSelector
+ value={field.value}
+ hideBookmarkIds={alreadyInList?.lists.map(
+ (l) => l.id,
+ )}
+ onChange={field.onChange}
+ />
</FormControl>
<FormMessage />
</FormItem>
@@ -119,14 +194,14 @@ export default function AddToListModal({
);
}
-export function useAddToListModal(bookmarkId: string) {
+export function useManageListsModal(bookmarkId: string) {
const [open, setOpen] = useState(false);
return {
open,
setOpen,
content: (
- <AddToListModal bookmarkId={bookmarkId} open={open} setOpen={setOpen} />
+ <ManageListsModal bookmarkId={bookmarkId} open={open} setOpen={setOpen} />
),
};
}
diff --git a/apps/web/components/dashboard/lists/BookmarkListSelector.tsx b/apps/web/components/dashboard/lists/BookmarkListSelector.tsx
index fdae1c17..144297cf 100644
--- a/apps/web/components/dashboard/lists/BookmarkListSelector.tsx
+++ b/apps/web/components/dashboard/lists/BookmarkListSelector.tsx
@@ -14,12 +14,14 @@ export function BookmarkListSelector({
value,
onChange,
hideSubtreeOf,
+ hideBookmarkIds = [],
placeholder = "Select a list",
}: {
value?: string | null;
onChange: (value: string) => void;
placeholder?: string;
hideSubtreeOf?: string;
+ hideBookmarkIds?: string[];
}) {
const { data, isPending: isFetchingListsPending } = useBookmarkLists();
let { allPaths } = data ?? {};
@@ -29,6 +31,9 @@ export function BookmarkListSelector({
}
allPaths = allPaths?.filter((path) => {
+ if (hideBookmarkIds.includes(path[path.length - 1].id)) {
+ return false;
+ }
if (!hideSubtreeOf) {
return true;
}
@@ -36,7 +41,7 @@ export function BookmarkListSelector({
});
return (
- <Select onValueChange={onChange} value={value ?? undefined}>
+ <Select onValueChange={onChange} value={value ?? ""}>
<SelectTrigger className="w-full">
<SelectValue placeholder={placeholder} />
</SelectTrigger>