diff --git a/prisma/migrations/20250407220501_add_clipboard/migration.sql b/prisma/migrations/20250407220501_add_clipboard/migration.sql new file mode 100644 index 0000000..9b5c7c0 --- /dev/null +++ b/prisma/migrations/20250407220501_add_clipboard/migration.sql @@ -0,0 +1,7 @@ +-- CreateTable +CREATE TABLE "Clipboard" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + + CONSTRAINT "Clipboard_pkey" PRIMARY KEY ("id") +); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 4110afc..2d8e3b8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -30,3 +30,8 @@ model User { username String @unique password String } + +model Clipboard { + id Int @id @default(autoincrement()) + content String @db.Text +} diff --git a/src/app/clipboard/ClipboardComponent.tsx b/src/app/clipboard/ClipboardComponent.tsx new file mode 100644 index 0000000..4ab541c --- /dev/null +++ b/src/app/clipboard/ClipboardComponent.tsx @@ -0,0 +1,46 @@ +"use client"; +import { useState } from "react"; +import { updateClipboard } from "./action"; + +export default function ClipboardComponent({ + initialContent, +}: { + initialContent: string; +}) { + const [clipboardContent, setClipboardContent] = useState(initialContent); + const [typingTimeout, setTypingTimeout] = useState( + null + ); + + const contentChanged = (content: string) => { + setClipboardContent(content); + if (typingTimeout) { + clearTimeout(typingTimeout); + } + const timeout = setTimeout(async () => { + await updateClipboard(content); + }, 500); + setTypingTimeout(timeout); + }; + + return ( + <> + + + ); +} diff --git a/src/app/clipboard/action.ts b/src/app/clipboard/action.ts new file mode 100644 index 0000000..4d503de --- /dev/null +++ b/src/app/clipboard/action.ts @@ -0,0 +1,19 @@ +"use server"; + +import { PrismaClient } from "@prisma/client"; + +export async function updateClipboard(content: string) { + const prisma = new PrismaClient(); + await prisma.clipboard.upsert({ + where: { id: 1 }, + update: { content }, + create: { content }, + }); +} +export async function getClipboard(): Promise { + const prisma = new PrismaClient(); + const clipboard = await prisma.clipboard.findUnique({ + where: { id: 1 }, + }); + return clipboard?.content || ""; +} diff --git a/src/app/clipboard/page.tsx b/src/app/clipboard/page.tsx new file mode 100644 index 0000000..901041d --- /dev/null +++ b/src/app/clipboard/page.tsx @@ -0,0 +1,13 @@ +"use server"; + +import { getClipboard } from "./action"; +import ClipboardComponent from "./ClipboardComponent"; + +export default async function ClipboardPage() { + const clipboard = await getClipboard(); + return ( + <> + + + ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 81c5a9e..1466788 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -4,17 +4,20 @@ import Title from "@/components/Title"; import Navbar from "@/components/Navbar"; import { bodyFont } from "@/components/fonts"; import Link from "next/link"; +import { auth } from "@/auth"; export const metadata: Metadata = { title: "nrx.sh", description: "naresh's site", }; -export default function RootLayout({ +export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { + const isLoggedIn = (await auth())?.user != null; + return ( @@ -28,7 +31,7 @@ export default function RootLayout({ > - <Navbar /> + <Navbar isLoggedIn={isLoggedIn} /> <div className={bodyFont.className} style={{ diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 8c50a2b..b318dd5 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -4,6 +4,7 @@ import { useState } from "react"; import React from "react"; import { navBarFont } from "./fonts"; import { + ADMIN_PAGES, PAGES, Pages, pathNameFromSelectedPage, @@ -11,7 +12,7 @@ import { } from "./pages"; import { usePathname, useRouter } from "next/navigation"; -export default function Navbar() { +export default function Navbar({ isLoggedIn }: { isLoggedIn: boolean }) { const [hoveredPage, setHoveredPage] = useState<Pages | null>(null); const pathName = usePathname(); @@ -41,7 +42,10 @@ export default function Navbar() { justifyContent: "center", }} > - {PAGES.map((page, index) => ( + {PAGES.filter((p) => { + if (!isLoggedIn && ADMIN_PAGES.includes(p)) return false; + return true; + }).map((page, index) => ( <React.Fragment key={page}> <div style={navbarItem(page)} diff --git a/src/components/pages.ts b/src/components/pages.ts index 64abd08..4bc2699 100644 --- a/src/components/pages.ts +++ b/src/components/pages.ts @@ -1,5 +1,6 @@ -export type Pages = "home" | "about" | "links" | "contact" | "blog"; -export const PAGES: Pages[] = ["home", "about", "blog", "links", "contact"]; +export type Pages = "home" | "about" | "links" | "contact" | "blog" | "clipboard"; +export const PAGES: Pages[] = ["home", "about", "blog", "links", "contact", "clipboard"]; +export const ADMIN_PAGES: Pages[] = ["clipboard"] export function selectedPageFromPathName(pathName: string): Pages { if (pathName === "/") {