diff options
| author | MohamedBassem <me@mbassem.com> | 2024-02-08 15:14:23 +0000 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-02-08 15:15:21 +0000 |
| commit | 80bb8a108f29331cdb2f2695f6801beee104dc89 (patch) | |
| tree | b1ae2a512963a9c916c4bfed71f7633f508de131 /web/app | |
| parent | 333429adbaaa592cc96b480a5228f0e3f1de4cc2 (diff) | |
| download | karakeep-80bb8a108f29331cdb2f2695f6801beee104dc89.tar.zst | |
[refactor] Move the different packages to the package subdir
Diffstat (limited to 'web/app')
| -rw-r--r-- | web/app/api/auth/[...nextauth]/route.tsx | 3 | ||||
| -rw-r--r-- | web/app/api/v1/links/[linkId]/route.ts | 32 | ||||
| -rw-r--r-- | web/app/api/v1/links/route.ts | 49 | ||||
| -rw-r--r-- | web/app/dashboard/bookmarks/components/AddLink.tsx | 67 | ||||
| -rw-r--r-- | web/app/dashboard/bookmarks/components/LinkCard.tsx | 96 | ||||
| -rw-r--r-- | web/app/dashboard/bookmarks/components/LinksGrid.tsx | 21 | ||||
| -rw-r--r-- | web/app/dashboard/bookmarks/page.tsx | 20 | ||||
| -rw-r--r-- | web/app/dashboard/components/Sidebar.tsx | 56 | ||||
| -rw-r--r-- | web/app/dashboard/layout.tsx | 15 | ||||
| -rw-r--r-- | web/app/favicon.ico | bin | 25931 -> 0 bytes | |||
| -rw-r--r-- | web/app/globals.css | 76 | ||||
| -rw-r--r-- | web/app/layout.tsx | 27 | ||||
| -rw-r--r-- | web/app/page.tsx | 19 |
13 files changed, 0 insertions, 481 deletions
diff --git a/web/app/api/auth/[...nextauth]/route.tsx b/web/app/api/auth/[...nextauth]/route.tsx deleted file mode 100644 index e722926b..00000000 --- a/web/app/api/auth/[...nextauth]/route.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { authHandler } from "@/lib/auth"; - -export { authHandler as GET, authHandler as POST }; diff --git a/web/app/api/v1/links/[linkId]/route.ts b/web/app/api/v1/links/[linkId]/route.ts deleted file mode 100644 index 39449d6d..00000000 --- a/web/app/api/v1/links/[linkId]/route.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { authOptions } from "@/lib/auth"; -import { unbookmarkLink } from "@/lib/services/links"; -import { Prisma } from "@remember/db"; - -import { getServerSession } from "next-auth"; -import { NextRequest } from "next/server"; - -export async function DELETE( - _request: NextRequest, - { params }: { params: { linkId: string } }, -) { - // 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 }); - } - - try { - await unbookmarkLink(params.linkId, session.user.id); - } catch (e: unknown) { - if ( - e instanceof Prisma.PrismaClientKnownRequestError && - e.code === "P2025" // RecordNotFound - ) { - return new Response(null, { status: 404 }); - } else { - throw e; - } - } - - return new Response(null, { status: 201 }); -} diff --git a/web/app/api/v1/links/route.ts b/web/app/api/v1/links/route.ts deleted file mode 100644 index 87541634..00000000 --- a/web/app/api/v1/links/route.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { authOptions } from "@/lib/auth"; -import { bookmarkLink, getLinks } from "@/lib/services/links"; - -import { - zNewBookmarkedLinkRequestSchema, - ZGetLinksResponse, - ZBookmarkedLink, -} from "@/lib/types/api/links"; -import { getServerSession } from "next-auth"; -import { NextRequest, NextResponse } from "next/server"; - -export async function POST(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 linkRequest = zNewBookmarkedLinkRequestSchema.safeParse( - await request.json(), - ); - - if (!linkRequest.success) { - return NextResponse.json( - { - error: linkRequest.error.toString(), - }, - { status: 400 }, - ); - } - - const link = await bookmarkLink(linkRequest.data.url, session.user.id); - - let response: ZBookmarkedLink = { ...link }; - return NextResponse.json(response, { status: 201 }); -} - -export async function GET() { - // 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 links = await getLinks(session.user.id); - - let response: ZGetLinksResponse = { links }; - return NextResponse.json(response); -} diff --git a/web/app/dashboard/bookmarks/components/AddLink.tsx b/web/app/dashboard/bookmarks/components/AddLink.tsx deleted file mode 100644 index fb77786c..00000000 --- a/web/app/dashboard/bookmarks/components/AddLink.tsx +++ /dev/null @@ -1,67 +0,0 @@ -"use client"; - -import { Button } from "@/components/ui/button"; -import { Form, FormControl, FormField, FormItem } from "@/components/ui/form"; -import { Input } from "@/components/ui/input"; -import APIClient from "@/lib/api"; -import { Plus } from "lucide-react"; -import { useRouter } from "next/navigation"; -import { useForm, SubmitErrorHandler } from "react-hook-form"; -import { z } from "zod"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { toast } from "@/components/ui/use-toast"; - -const formSchema = z.object({ - url: z.string().url({ message: "The link must be a valid URL" }), -}); - -export default function AddLink() { - const router = useRouter(); - - const form = useForm<z.infer<typeof formSchema>>({ - resolver: zodResolver(formSchema), - }); - - async function onSubmit(value: z.infer<typeof formSchema>) { - const [_resp, error] = await APIClient.bookmarkLink(value.url); - if (error) { - toast({ description: error.message, variant: "destructive" }); - return; - } - router.refresh(); - } - - const onError: SubmitErrorHandler<z.infer<typeof formSchema>> = (errors) => { - toast({ - description: Object.values(errors) - .map((v) => v.message) - .join("\n"), - variant: "destructive", - }); - }; - - return ( - <Form {...form}> - <form onSubmit={form.handleSubmit(onSubmit, onError)}> - <div className="py-4 container flex w-full items-center space-x-2"> - <FormField - control={form.control} - name="url" - render={({ field }) => { - return ( - <FormItem className="flex-1"> - <FormControl> - <Input type="text" placeholder="Link" {...field} /> - </FormControl> - </FormItem> - ); - }} - /> - <Button type="submit"> - <Plus /> - </Button> - </div> - </form> - </Form> - ); -} diff --git a/web/app/dashboard/bookmarks/components/LinkCard.tsx b/web/app/dashboard/bookmarks/components/LinkCard.tsx deleted file mode 100644 index da59d9da..00000000 --- a/web/app/dashboard/bookmarks/components/LinkCard.tsx +++ /dev/null @@ -1,96 +0,0 @@ -"use client"; - -import { Badge } from "@/components/ui/badge"; -import { Button } from "@/components/ui/button"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; -import { - ImageCard, - ImageCardBody, - ImageCardFooter, - ImageCardTitle, -} from "@/components/ui/imageCard"; -import { useToast } from "@/components/ui/use-toast"; -import APIClient from "@/lib/api"; -import { ZBookmarkedLink } from "@/lib/types/api/links"; -import { MoreHorizontal, Trash2 } from "lucide-react"; -import Link from "next/link"; -import { useRouter } from "next/navigation"; - -export function LinkOptions({ linkId }: { linkId: string }) { - const { toast } = useToast(); - const router = useRouter(); - - const unbookmarkLink = async () => { - let [_, error] = await APIClient.unbookmarkLink(linkId); - - if (error) { - toast({ - variant: "destructive", - title: "Something went wrong", - description: "There was a problem with your request.", - }); - } else { - toast({ - description: "The link has been deleted!", - }); - } - - router.refresh(); - }; - return ( - <DropdownMenu> - <DropdownMenuTrigger asChild> - <Button variant="ghost"> - <MoreHorizontal /> - </Button> - </DropdownMenuTrigger> - <DropdownMenuContent className="w-fit"> - <DropdownMenuItem className="text-destructive" onClick={unbookmarkLink}> - <Trash2 className="mr-2 h-4 w-4" /> - <span>Delete</span> - </DropdownMenuItem> - </DropdownMenuContent> - </DropdownMenu> - ); -} - -export default function LinkCard({ link }: { link: ZBookmarkedLink }) { - const parsedUrl = new URL(link.url); - - return ( - <ImageCard - className={ - "bg-gray-50 duration-300 ease-in border border-grey-100 hover:transition-all hover:border-blue-300" - } - image={link.details?.imageUrl ?? undefined} - > - <ImageCardTitle> - <Link className="line-clamp-3" href={link.url}> - {link.details?.title ?? parsedUrl.host} - </Link> - </ImageCardTitle> - <ImageCardBody className="py-2 overflow-clip"> - {link.tags.map((t) => ( - <Badge variant="default" className="bg-gray-300 text-gray-500" key={t.id}> - #{t.name} - </Badge> - ))} - </ImageCardBody> - <ImageCardFooter> - <div className="flex justify-between text-gray-500"> - <div className="my-auto"> - <Link className="line-clamp-1 hover:text-black" href={link.url}> - {parsedUrl.host} - </Link> - </div> - <LinkOptions linkId={link.id} /> - </div> - </ImageCardFooter> - </ImageCard> - ); -} diff --git a/web/app/dashboard/bookmarks/components/LinksGrid.tsx b/web/app/dashboard/bookmarks/components/LinksGrid.tsx deleted file mode 100644 index 66f0d766..00000000 --- a/web/app/dashboard/bookmarks/components/LinksGrid.tsx +++ /dev/null @@ -1,21 +0,0 @@ -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 ( - <div className="container grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4"> - {links.map((l) => ( - <LinkCard key={l.id} link={l} /> - ))} - </div> - ); -} diff --git a/web/app/dashboard/bookmarks/page.tsx b/web/app/dashboard/bookmarks/page.tsx deleted file mode 100644 index b4158893..00000000 --- a/web/app/dashboard/bookmarks/page.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import AddLink from "./components/AddLink"; -import LinksGrid from "./components/LinksGrid"; -import type { Metadata } from "next"; - -export const metadata: Metadata = { - title: "Remember - Bookmarks", -}; - -export default async function Bookmarks() { - return ( - <div className="flex flex-col"> - <div> - <AddLink /> - </div> - <div> - <LinksGrid /> - </div> - </div> - ); -} diff --git a/web/app/dashboard/components/Sidebar.tsx b/web/app/dashboard/components/Sidebar.tsx deleted file mode 100644 index 0ed87daf..00000000 --- a/web/app/dashboard/components/Sidebar.tsx +++ /dev/null @@ -1,56 +0,0 @@ -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> - ); -} - -export default async function Sidebar() { - const session = await getServerSession(authOptions); - if (!session) { - redirect("/"); - } - - return ( - <aside className="flex flex-col h-full w-60 border-r p-4"> - <div className="flex px-1 mb-5 items-center rounded-lg text-slate-900"> - <Brain /> - <span className="ml-2 text-base font-semibold">Remember</span> - </div> - <hr /> - <div> - <ul className="space-y-2 mt-5 text-sm font-medium"> - <SidebarItem logo={<Home />} name="Home" path="#" /> - <SidebarItem logo={<Star />} name="Favourites" path="#" /> - <SidebarItem logo={<Archive />} name="Archived" path="#" /> - <SidebarItem logo={<Tag />} name="Tags" path="#" /> - </ul> - </div> - <div className="mt-auto flex justify-between"> - <div className="my-auto"> {session.user.name} </div> - <Button variant="ghost" className="h-10 w-30"> - <MoreHorizontal /> - </Button> - </div> - </aside> - ); -} diff --git a/web/app/dashboard/layout.tsx b/web/app/dashboard/layout.tsx deleted file mode 100644 index 9b21271e..00000000 --- a/web/app/dashboard/layout.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import Bookmarks from "@/app/dashboard/bookmarks/page"; -import Sidebar from "@/app/dashboard/components/Sidebar"; - -export default async function Dashboard() { - return ( - <div className="flex w-screen h-screen"> - <div className="flex-none"> - <Sidebar /> - </div> - <div className="flex-1 bg-gray-100"> - <Bookmarks /> - </div> - </div> - ); -} diff --git a/web/app/favicon.ico b/web/app/favicon.ico Binary files differdeleted file mode 100644 index 718d6fea..00000000 --- a/web/app/favicon.ico +++ /dev/null diff --git a/web/app/globals.css b/web/app/globals.css deleted file mode 100644 index 8abdb15c..00000000 --- a/web/app/globals.css +++ /dev/null @@ -1,76 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; - - --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; - - --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; - - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; - - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; - - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; - - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 222.2 84% 4.9%; - - --radius: 0.5rem; - } - - .dark { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; - - --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; - - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; - - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 11.2%; - - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; - - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; - - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; - - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; - - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - --ring: 212.7 26.8% 83.9%; - } -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} diff --git a/web/app/layout.tsx b/web/app/layout.tsx deleted file mode 100644 index a2d34046..00000000 --- a/web/app/layout.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import type { Metadata } from "next"; -import { Inter } from "next/font/google"; -import "./globals.css"; -import React from "react"; -import { Toaster } from "@/components/ui/toaster"; - -const inter = Inter({ subsets: ["latin"] }); - -export const metadata: Metadata = { - title: "Remember", - description: "Your AI powered second brain", -}; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - <html lang="en"> - <body className={inter.className}> - {children} - <Toaster /> - </body> - </html> - ); -} diff --git a/web/app/page.tsx b/web/app/page.tsx deleted file mode 100644 index ffc128a5..00000000 --- a/web/app/page.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { LoginButton } from "@/components/auth/login"; -import { LogoutButton } from "@/components/auth/logout"; -import Link from "next/link"; - -export default function Home() { - return ( - <main className="flex min-h-screen flex-col items-center justify-between p-24"> - <div> - <LoginButton /> - <br /> - <br /> - <LogoutButton /> - <br /> - <br /> - <Link href="/bookmarks">Bookmarks</Link> - </div> - </main> - ); -} |
