aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-02-09 15:32:04 +0000
committerMohamedBassem <me@mbassem.com>2024-02-09 15:32:04 +0000
commit4fae8f04f546d2b3f6053870d93385fa36af4742 (patch)
treefbf91f3c3c3d2bd85e9e4cfc8200d275a78fb700 /packages
parentb25f17509e704eb41523bf455a33804cabf8aaca (diff)
downloadkarakeep-4fae8f04f546d2b3f6053870d93385fa36af4742.tar.zst
[ui] Adding the favourites and archive pages
Diffstat (limited to 'packages')
-rw-r--r--packages/web/app/api/v1/bookmarks/route.ts12
-rw-r--r--packages/web/app/dashboard/bookmarks/archive/page.tsx5
-rw-r--r--packages/web/app/dashboard/bookmarks/components/Bookmarks.tsx38
-rw-r--r--packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx16
-rw-r--r--packages/web/app/dashboard/bookmarks/favourites/page.tsx5
-rw-r--r--packages/web/app/dashboard/bookmarks/layout.tsx23
-rw-r--r--packages/web/app/dashboard/bookmarks/page.tsx21
-rw-r--r--packages/web/app/dashboard/components/Sidebar.tsx39
-rw-r--r--packages/web/app/dashboard/components/SidebarItem.tsx30
-rw-r--r--packages/web/app/dashboard/layout.tsx13
-rw-r--r--packages/web/lib/services/bookmarks.ts13
-rw-r--r--packages/web/lib/types/api/bookmarks.ts7
12 files changed, 160 insertions, 62 deletions
diff --git a/packages/web/app/api/v1/bookmarks/route.ts b/packages/web/app/api/v1/bookmarks/route.ts
index a78535cc..98e01080 100644
--- a/packages/web/app/api/v1/bookmarks/route.ts
+++ b/packages/web/app/api/v1/bookmarks/route.ts
@@ -5,6 +5,7 @@ import {
zNewBookmarkRequestSchema,
ZGetBookmarksResponse,
ZBookmark,
+ zGetBookmarksRequestSchema,
} from "@/lib/types/api/bookmarks";
import { getServerSession } from "next-auth";
import { NextRequest, NextResponse } from "next/server";
@@ -33,14 +34,21 @@ export async function POST(request: NextRequest) {
return NextResponse.json(response, { status: 201 });
}
-export async function GET() {
+export async function GET(request: NextRequest) {
// TODO: We probably should be using an API key here instead of the session;
const session = await getServerSession(authOptions);
if (!session) {
return new Response(null, { status: 401 });
}
- const bookmarks = await getBookmarks(session.user.id);
+ const query = request.nextUrl.searchParams;
+ const params = zGetBookmarksRequestSchema.safeParse(query);
+
+ if (!params.success) {
+ return new Response(null, { status: 400 });
+ }
+
+ const bookmarks = await getBookmarks(session.user.id, params.data);
const response: ZGetBookmarksResponse = { bookmarks };
return NextResponse.json(response);
diff --git a/packages/web/app/dashboard/bookmarks/archive/page.tsx b/packages/web/app/dashboard/bookmarks/archive/page.tsx
new file mode 100644
index 00000000..0d105fbd
--- /dev/null
+++ b/packages/web/app/dashboard/bookmarks/archive/page.tsx
@@ -0,0 +1,5 @@
+import Bookmarks from "../components/Bookmarks";
+
+export default async function ArchivedBookmarkPage() {
+ return <Bookmarks title="Archive" archived={true} favourited={false} />;
+}
diff --git a/packages/web/app/dashboard/bookmarks/components/Bookmarks.tsx b/packages/web/app/dashboard/bookmarks/components/Bookmarks.tsx
new file mode 100644
index 00000000..6a9ffe1b
--- /dev/null
+++ b/packages/web/app/dashboard/bookmarks/components/Bookmarks.tsx
@@ -0,0 +1,38 @@
+import { redirect } from "next/navigation";
+import BookmarksGrid from "./BookmarksGrid";
+import { authOptions } from "@/lib/auth";
+import { getServerSession } from "next-auth";
+import { getBookmarks } from "@/lib/services/bookmarks";
+import { ZGetBookmarksRequest } from "@/lib/types/api/bookmarks";
+
+export default async function Bookmarks({
+ favourited,
+ archived,
+ title,
+}: ZGetBookmarksRequest & { title: string }) {
+ const session = await getServerSession(authOptions);
+ if (!session) {
+ redirect("/");
+ }
+ const bookmarks = await getBookmarks(session.user.id, {
+ favourited,
+ archived,
+ });
+
+ if (bookmarks.length == 0) {
+ // TODO: This needs to be polished
+ return (
+ <>
+ <div className="container pb-4 text-2xl">{title}</div>
+ <div className="container">No bookmarks</div>
+ </>
+ );
+ }
+
+ return (
+ <>
+ <div className="container pb-4 text-2xl">{title}</div>
+ <BookmarksGrid bookmarks={bookmarks} />
+ </>
+ );
+}
diff --git a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx
index f52ef910..11845ca3 100644
--- a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx
+++ b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx
@@ -1,7 +1,3 @@
-import { getServerSession } from "next-auth";
-import { redirect } from "next/navigation";
-import { authOptions } from "@/lib/auth";
-import { getBookmarks } from "@/lib/services/bookmarks";
import LinkCard from "./LinkCard";
import { ZBookmark } from "@/lib/types/api/bookmarks";
@@ -12,13 +8,11 @@ function renderBookmark(bookmark: ZBookmark) {
}
}
-export default async function BookmarksGrid() {
- const session = await getServerSession(authOptions);
- if (!session) {
- redirect("/");
- }
- const bookmarks = await getBookmarks(session.user.id);
-
+export default function BookmarksGrid({
+ bookmarks,
+}: {
+ bookmarks: ZBookmark[];
+}) {
return (
<div className="container grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{bookmarks.map((b) => renderBookmark(b))}
diff --git a/packages/web/app/dashboard/bookmarks/favourites/page.tsx b/packages/web/app/dashboard/bookmarks/favourites/page.tsx
new file mode 100644
index 00000000..990b087d
--- /dev/null
+++ b/packages/web/app/dashboard/bookmarks/favourites/page.tsx
@@ -0,0 +1,5 @@
+import Bookmarks from "../components/Bookmarks";
+
+export default async function FavouritesBookmarkPage() {
+ return <Bookmarks title="Favourites" archived={false} favourited={true} />;
+}
diff --git a/packages/web/app/dashboard/bookmarks/layout.tsx b/packages/web/app/dashboard/bookmarks/layout.tsx
new file mode 100644
index 00000000..14f7bb40
--- /dev/null
+++ b/packages/web/app/dashboard/bookmarks/layout.tsx
@@ -0,0 +1,23 @@
+import React from "react";
+import AddLink from "./components/AddLink";
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Remember - Bookmarks",
+};
+
+export default function BookmarksLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ return (
+ <div className="flex flex-col">
+ <div>
+ <AddLink />
+ </div>
+ <hr />
+ <div className="mt-4">{children}</div>
+ </div>
+ );
+}
diff --git a/packages/web/app/dashboard/bookmarks/page.tsx b/packages/web/app/dashboard/bookmarks/page.tsx
index b9eabfe8..3d125fad 100644
--- a/packages/web/app/dashboard/bookmarks/page.tsx
+++ b/packages/web/app/dashboard/bookmarks/page.tsx
@@ -1,20 +1,5 @@
-import AddLink from "./components/AddLink";
-import BookmarksGrid from "./components/BookmarksGrid";
-import type { Metadata } from "next";
+import Bookmarks from "./components/Bookmarks";
-export const metadata: Metadata = {
- title: "Remember - Bookmarks",
-};
-
-export default async function Bookmarks() {
- return (
- <div className="flex flex-col">
- <div>
- <AddLink />
- </div>
- <div>
- <BookmarksGrid />
- </div>
- </div>
- );
+export default async function BookmarksPage() {
+ return <Bookmarks title="Bookmarks" archived={false} favourited={false} />;
}
diff --git a/packages/web/app/dashboard/components/Sidebar.tsx b/packages/web/app/dashboard/components/Sidebar.tsx
index c2abe1e1..3b4e1649 100644
--- a/packages/web/app/dashboard/components/Sidebar.tsx
+++ b/packages/web/app/dashboard/components/Sidebar.tsx
@@ -2,27 +2,8 @@ import { Button } from "@/components/ui/button";
import { authOptions } from "@/lib/auth";
import { Archive, MoreHorizontal, Star, Tag, Home, Brain } from "lucide-react";
import { getServerSession } from "next-auth";
-import Link from "next/link";
import { redirect } from "next/navigation";
-
-function SidebarItem({
- name,
- logo,
- path,
-}: {
- name: string;
- logo: React.ReactNode;
- path: string;
-}) {
- return (
- <li className="rounded-lg px-3 py-2 hover:bg-slate-100">
- <Link href={path} className="flex w-full space-x-2">
- {logo}
- <span className="my-auto"> {name} </span>
- </Link>
- </li>
- );
-}
+import SidebarItem from "./SidebarItem";
export default async function Sidebar() {
const session = await getServerSession(authOptions);
@@ -39,9 +20,21 @@ export default async function Sidebar() {
<hr />
<div>
<ul className="mt-5 space-y-2 text-sm font-medium">
- <SidebarItem logo={<Home />} name="Home" path="#" />
- <SidebarItem logo={<Star />} name="Favourites" path="#" />
- <SidebarItem logo={<Archive />} name="Archived" path="#" />
+ <SidebarItem
+ logo={<Home />}
+ name="Home"
+ path="/dashboard/bookmarks"
+ />
+ <SidebarItem
+ logo={<Star />}
+ name="Favourites"
+ path="/dashboard/bookmarks/favourites"
+ />
+ <SidebarItem
+ logo={<Archive />}
+ name="Archive"
+ path="/dashboard/bookmarks/archive"
+ />
<SidebarItem logo={<Tag />} name="Tags" path="#" />
</ul>
</div>
diff --git a/packages/web/app/dashboard/components/SidebarItem.tsx b/packages/web/app/dashboard/components/SidebarItem.tsx
new file mode 100644
index 00000000..e6a00d72
--- /dev/null
+++ b/packages/web/app/dashboard/components/SidebarItem.tsx
@@ -0,0 +1,30 @@
+"use client";
+
+import { cn } from "@/lib/utils";
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+
+export default function SidebarItem({
+ name,
+ logo,
+ path,
+}: {
+ name: string;
+ logo: React.ReactNode;
+ path: string;
+}) {
+ const currentPath = usePathname();
+ return (
+ <li
+ className={cn(
+ "rounded-lg hover:bg-slate-100",
+ path == currentPath ? "bg-slate-100" : "",
+ )}
+ >
+ <Link href={path} className="flex w-full space-x-2 px-3 py-2">
+ {logo}
+ <span className="my-auto"> {name} </span>
+ </Link>
+ </li>
+ );
+}
diff --git a/packages/web/app/dashboard/layout.tsx b/packages/web/app/dashboard/layout.tsx
index 220949c7..87c88a4b 100644
--- a/packages/web/app/dashboard/layout.tsx
+++ b/packages/web/app/dashboard/layout.tsx
@@ -1,15 +1,16 @@
-import Bookmarks from "@/app/dashboard/bookmarks/page";
-import Sidebar from "@/app/dashboard/components/Sidebar";
+import Sidebar from "./components/Sidebar";
-export default async function Dashboard() {
+export default async function Dashboard({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
return (
<div className="flex h-screen w-screen">
<div className="flex-none">
<Sidebar />
</div>
- <div className="flex-1 bg-gray-100">
- <Bookmarks />
- </div>
+ <div className="flex-1 bg-gray-100">{children}</div>
</div>
);
}
diff --git a/packages/web/lib/services/bookmarks.ts b/packages/web/lib/services/bookmarks.ts
index 3c9929bc..3231e4d3 100644
--- a/packages/web/lib/services/bookmarks.ts
+++ b/packages/web/lib/services/bookmarks.ts
@@ -1,6 +1,10 @@
import { LinkCrawlerQueue } from "@remember/shared/queues";
import prisma from "@remember/db";
-import { ZBookmark, ZBookmarkContent } from "@/lib/types/api/bookmarks";
+import {
+ ZBookmark,
+ ZBookmarkContent,
+ ZGetBookmarksRequest,
+} from "@/lib/types/api/bookmarks";
const defaultBookmarkFields = {
id: true,
@@ -80,11 +84,16 @@ export async function bookmarkLink(url: string, userId: string) {
return toZodSchema(bookmark);
}
-export async function getBookmarks(userId: string) {
+export async function getBookmarks(
+ userId: string,
+ { favourited, archived }: ZGetBookmarksRequest,
+) {
return (
await prisma.bookmark.findMany({
where: {
userId,
+ archived,
+ favourited,
},
select: defaultBookmarkFields,
})
diff --git a/packages/web/lib/types/api/bookmarks.ts b/packages/web/lib/types/api/bookmarks.ts
index 485fbfab..c4aec646 100644
--- a/packages/web/lib/types/api/bookmarks.ts
+++ b/packages/web/lib/types/api/bookmarks.ts
@@ -31,6 +31,13 @@ export const zNewBookmarkRequestSchema = zBookmarkContentSchema;
export type ZNewBookmarkRequest = z.infer<typeof zNewBookmarkRequestSchema>;
// GET /v1/bookmarks
+
+export const zGetBookmarksRequestSchema = z.object({
+ archived: z.boolean().default(false),
+ favourited: z.boolean().default(false),
+});
+export type ZGetBookmarksRequest = z.infer<typeof zGetBookmarksRequestSchema>;
+
export const zGetBookmarksResponseSchema = z.object({
bookmarks: z.array(zBookmarkSchema),
});