diff --git a/app/(app)/saved/_client.tsx b/app/(app)/saved/_client.tsx index f6c41607..f6e0c4ec 100644 --- a/app/(app)/saved/_client.tsx +++ b/app/(app)/saved/_client.tsx @@ -8,10 +8,11 @@ import ArticleLoading from "@/components/ArticlePreview/ArticleLoading"; const SavedPosts = () => { const { - data: bookmarks, + data: bookmarksData, refetch, status: bookmarkStatus, - } = api.post.myBookmarks.useQuery(); + } = api.post.myBookmarks.useQuery({}); + const bookmarks = bookmarksData?.bookmarks || []; const { mutate: bookmark } = api.post.bookmark.useMutation({ onSettled() { diff --git a/components/ArticlePreview/ArticlePreview.tsx b/components/ArticlePreview/ArticlePreview.tsx index 65f59525..71c2009c 100644 --- a/components/ArticlePreview/ArticlePreview.tsx +++ b/components/ArticlePreview/ArticlePreview.tsx @@ -17,6 +17,7 @@ import { } from "@headlessui/react"; import { api } from "@/server/trpc/react"; import { signIn, useSession } from "next-auth/react"; +import { toast } from "sonner"; type ButtonOptions = { label: string; @@ -55,8 +56,12 @@ const ArticlePreview: NextPage = ({ bookmarkedInitialState = false, }) => { const [bookmarked, setIsBookmarked] = useState(bookmarkedInitialState); + const howManySavedToShow = 3; + const { data: bookmarksData, refetch } = api.post.myBookmarks.useQuery({ + limit: howManySavedToShow, + }); const { data: session } = useSession(); - + const bookmarks = bookmarksData?.bookmarks; const dateTime = Temporal.Instant.from(new Date(date).toISOString()); const readableDate = dateTime.toLocaleString(["en-IE"], { year: "numeric", @@ -69,6 +74,13 @@ const ArticlePreview: NextPage = ({ onSettled() { setIsBookmarked((isBookmarked) => !isBookmarked); }, + onSuccess: () => { + refetch(); + }, + onError: (error) => { + toast.error("Failed to update bookmark"); + Sentry.captureException(error); + }, }); const bookmarkPost = async (postId: string, setBookmarked = true) => { diff --git a/components/SideBar/SideBarSavedPosts.tsx b/components/SideBar/SideBarSavedPosts.tsx index 43969bfd..54c4b1f4 100644 --- a/components/SideBar/SideBarSavedPosts.tsx +++ b/components/SideBar/SideBarSavedPosts.tsx @@ -6,14 +6,14 @@ import SideBarSavedArticlePreview from "./SideBarSavedArticlePreview"; import Link from "next/link"; export default React.memo(function SideBarSavedPosts() { - let { data: bookmarks } = api.post.myBookmarks.useQuery(); - const { status: bookmarkStatus } = api.post.myBookmarks.useQuery(); - const howManySavedToShow = 3; - const totalNumberSaved = bookmarks?.length; + const { data: bookmarksData, status: bookmarkStatus } = + api.post.myBookmarks.useQuery({ + limit: howManySavedToShow, + }); - // @TODO query the backend to get the last 3 instead of slice - if (bookmarks) bookmarks = bookmarks.slice(0, howManySavedToShow); + const totalNumberSaved = bookmarksData?.totalCount || 0; + const bookmarks = bookmarksData?.bookmarks || []; return (
diff --git a/schema/post.ts b/schema/post.ts index 99576ea1..224e8940 100644 --- a/schema/post.ts +++ b/schema/post.ts @@ -76,3 +76,7 @@ export const GetSinglePostSchema = z.object({ export const GetByIdSchema = z.object({ id: z.string(), }); + +export const GetLimitSidePosts = z.object({ + limit: z.number().optional(), +}); diff --git a/server/api/router/post.ts b/server/api/router/post.ts index b2792a77..8a41482b 100644 --- a/server/api/router/post.ts +++ b/server/api/router/post.ts @@ -11,6 +11,7 @@ import { LikePostSchema, BookmarkPostSchema, GetByIdSchema, + GetLimitSidePosts, } from "../../../schema/post"; import { removeMarkdown } from "../../../utils/removeMarkdown"; import { bookmark, like, post, post_tag, tag, user } from "@/server/db/schema"; @@ -438,37 +439,51 @@ export const postRouter = createTRPCRouter({ return currentPost; }), - myBookmarks: protectedProcedure.query(async ({ ctx }) => { - const response = await ctx.db.query.bookmark.findMany({ - columns: { - id: true, - }, - where: (bookmarks, { eq }) => eq(bookmarks.userId, ctx.session.user.id), - with: { - post: { - columns: { - id: true, - title: true, - excerpt: true, - updatedAt: true, - published: true, - readTimeMins: true, - slug: true, - }, - with: { - user: { - columns: { - name: true, - username: true, - image: true, + myBookmarks: protectedProcedure + .input(GetLimitSidePosts) + .query(async ({ ctx, input }) => { + const limit = input?.limit ?? undefined; + + const response = await ctx.db.query.bookmark.findMany({ + columns: { + id: true, + }, + where: (bookmarks, { eq }) => eq(bookmarks.userId, ctx.session.user.id), + with: { + post: { + columns: { + id: true, + title: true, + excerpt: true, + updatedAt: true, + published: true, + readTimeMins: true, + slug: true, + }, + with: { + user: { + columns: { + name: true, + username: true, + image: true, + }, }, }, }, }, - }, - orderBy: (bookmarks, { desc }) => [desc(bookmarks.id)], - }); + orderBy: (bookmarks, { desc }) => [desc(bookmarks.id)], + }); - return response.map(({ id, post }) => ({ bookmarkId: id, ...post })); - }), + const totalCount = response.length; + + const bookmarksResponse = response.slice(0, limit || response.length); + + return { + totalCount, + bookmarks: bookmarksResponse.map(({ id, post }) => ({ + bookmarkId: id, + ...post, + })), + }; + }), });