From daebbf0154a290fb690ed94fca23377e0f739f53 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Wed, 7 Feb 2024 02:48:38 +0000 Subject: [ui] Very first draft of the link grid --- web/app/api/v1/links/route.ts | 36 +++------------------------ web/app/bookmarks/components/AddLink.tsx | 40 ++++++++++++++++++++++++++++++ web/app/bookmarks/components/LinkCard.tsx | 19 ++++++++++++++ web/app/bookmarks/components/LinksGrid.tsx | 21 ++++++++++++++++ web/app/bookmarks/page.tsx | 11 ++++++++ web/app/page.tsx | 16 +++--------- 6 files changed, 99 insertions(+), 44 deletions(-) create mode 100644 web/app/bookmarks/components/AddLink.tsx create mode 100644 web/app/bookmarks/components/LinkCard.tsx create mode 100644 web/app/bookmarks/components/LinksGrid.tsx create mode 100644 web/app/bookmarks/page.tsx (limited to 'web/app') diff --git a/web/app/api/v1/links/route.ts b/web/app/api/v1/links/route.ts index 990b6c02..87541634 100644 --- a/web/app/api/v1/links/route.ts +++ b/web/app/api/v1/links/route.ts @@ -1,6 +1,5 @@ import { authOptions } from "@/lib/auth"; -import { LinkCrawlerQueue } from "@remember/shared/queues"; -import prisma from "@remember/db"; +import { bookmarkLink, getLinks } from "@/lib/services/links"; import { zNewBookmarkedLinkRequestSchema, @@ -30,18 +29,7 @@ export async function POST(request: NextRequest) { ); } - const link = await prisma.bookmarkedLink.create({ - data: { - url: linkRequest.data.url, - userId: session.user.id, - }, - }); - - // Enqueue crawling request - await LinkCrawlerQueue.add("crawl", { - linkId: link.id, - url: link.url, - }); + const link = await bookmarkLink(linkRequest.data.url, session.user.id); let response: ZBookmarkedLink = { ...link }; return NextResponse.json(response, { status: 201 }); @@ -53,24 +41,8 @@ export async function GET() { if (!session) { return new Response(null, { status: 401 }); } - const links = await prisma.bookmarkedLink.findMany({ - where: { - userId: session.user.id, - }, - select: { - id: true, - url: true, - createdAt: true, - details: { - select: { - title: true, - description: true, - imageUrl: true, - favicon: true, - }, - }, - }, - }); + + const links = await getLinks(session.user.id); let response: ZGetLinksResponse = { links }; return NextResponse.json(response); diff --git a/web/app/bookmarks/components/AddLink.tsx b/web/app/bookmarks/components/AddLink.tsx new file mode 100644 index 00000000..54cf9137 --- /dev/null +++ b/web/app/bookmarks/components/AddLink.tsx @@ -0,0 +1,40 @@ +"use client"; + +import APIClient from "@/lib/api"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; + +export default function AddLink() { + const router = useRouter(); + const [link, setLink] = useState(""); + + const bookmarkLink = async () => { + const [_resp, error] = await APIClient.bookmarkLink(link); + if (error) { + alert(error.message); + return; + } + router.refresh(); + }; + + return ( +
+ setLink(val.target.value)} + onKeyUp={async (event) => { + if (event.key == "Enter") { + bookmarkLink(); + setLink(""); + } + }} + className="w-10/12 px-4 py-2 border rounded-md focus:outline-none focus:border-blue-300" + /> + +
+ ); +} diff --git a/web/app/bookmarks/components/LinkCard.tsx b/web/app/bookmarks/components/LinkCard.tsx new file mode 100644 index 00000000..103f97ef --- /dev/null +++ b/web/app/bookmarks/components/LinkCard.tsx @@ -0,0 +1,19 @@ +import { ZBookmarkedLink } from "@/lib/types/api/links"; +import Link from "next/link"; + +export default async function LinkCard({ link }: { link: ZBookmarkedLink }) { + return ( + +
+

+ {link.details?.favicon && ( + // eslint-disable-next-line @next/next/no-img-element + + )} + {link.details?.title ?? link.id} +

+

{link.details?.description ?? link.url}

+
+ + ); +} diff --git a/web/app/bookmarks/components/LinksGrid.tsx b/web/app/bookmarks/components/LinksGrid.tsx new file mode 100644 index 00000000..83aaca80 --- /dev/null +++ b/web/app/bookmarks/components/LinksGrid.tsx @@ -0,0 +1,21 @@ +import { getServerSession } from "next-auth"; +import { redirect } from "next/navigation"; +import { authOptions } from "@/lib/auth"; +import { getLinks } from "@/lib/services/links"; +import LinkCard from "./LinkCard"; + +export default async function LinksGrid() { + const session = await getServerSession(authOptions); + if (!session) { + redirect("/"); + } + const links = await getLinks(session.user.id); + + return ( +
+ {links.map((l) => ( + + ))} +
+ ); +} diff --git a/web/app/bookmarks/page.tsx b/web/app/bookmarks/page.tsx new file mode 100644 index 00000000..f0efa2e4 --- /dev/null +++ b/web/app/bookmarks/page.tsx @@ -0,0 +1,11 @@ +import AddLink from "./components/AddLink"; +import LinksGrid from "./components/LinksGrid"; + +export default async function Bookmarks() { + return ( + <> + + + + ); +} diff --git a/web/app/page.tsx b/web/app/page.tsx index b78fe389..ffc128a5 100644 --- a/web/app/page.tsx +++ b/web/app/page.tsx @@ -1,16 +1,8 @@ -"use client"; - -import { useCallback } from "react"; -import { LoginButton } from "../components/auth/login"; -import { LogoutButton } from "../components/auth/logout"; +import { LoginButton } from "@/components/auth/login"; +import { LogoutButton } from "@/components/auth/logout"; +import Link from "next/link"; export default function Home() { - const addUrl = useCallback(async () => { - await fetch("/api/v1/links", { - method: "POST", - body: JSON.stringify({ url: "https://news.ycombinator.com/news" }), - }); - }, []); return (
@@ -20,7 +12,7 @@ export default function Home() {

- + Bookmarks
); -- cgit v1.2.3-70-g09d2