This commit is contained in:
		| @@ -0,0 +1,7 @@ | ||||
| -- CreateTable | ||||
| CREATE TABLE "Clipboard" ( | ||||
|     "id" SERIAL NOT NULL, | ||||
|     "content" TEXT NOT NULL, | ||||
|  | ||||
|     CONSTRAINT "Clipboard_pkey" PRIMARY KEY ("id") | ||||
| ); | ||||
| @@ -30,3 +30,8 @@ model User { | ||||
|     username String @unique | ||||
|     password String | ||||
| } | ||||
|  | ||||
| model Clipboard { | ||||
|     id      Int    @id @default(autoincrement()) | ||||
|     content String @db.Text | ||||
| } | ||||
|   | ||||
							
								
								
									
										46
									
								
								src/app/clipboard/ClipboardComponent.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/app/clipboard/ClipboardComponent.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -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<NodeJS.Timeout | null>( | ||||
|     null | ||||
|   ); | ||||
|  | ||||
|   const contentChanged = (content: string) => { | ||||
|     setClipboardContent(content); | ||||
|     if (typingTimeout) { | ||||
|       clearTimeout(typingTimeout); | ||||
|     } | ||||
|     const timeout = setTimeout(async () => { | ||||
|       await updateClipboard(content); | ||||
|     }, 500); | ||||
|     setTypingTimeout(timeout); | ||||
|   }; | ||||
|  | ||||
|   return ( | ||||
|     <> | ||||
|       <textarea | ||||
|         style={{ | ||||
|           width: "100%", | ||||
|           resize: "none", | ||||
|           borderStyle: "none", | ||||
|           backgroundColor: "#333", | ||||
|           height: "20rem", | ||||
|           maxHeight: "80vh", | ||||
|           color: "#eee", | ||||
|         }} | ||||
|         onChange={(e) => contentChanged(e.target.value)} | ||||
|         onBlur={async (e) => { | ||||
|           await updateClipboard(e.target.value); | ||||
|         }} | ||||
|         value={clipboardContent} | ||||
|       ></textarea> | ||||
|     </> | ||||
|   ); | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/app/clipboard/action.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/app/clipboard/action.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -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<string> { | ||||
|   const prisma = new PrismaClient(); | ||||
|   const clipboard = await prisma.clipboard.findUnique({ | ||||
|     where: { id: 1 }, | ||||
|   }); | ||||
|   return clipboard?.content || ""; | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/app/clipboard/page.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/app/clipboard/page.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| "use server"; | ||||
|  | ||||
| import { getClipboard } from "./action"; | ||||
| import ClipboardComponent from "./ClipboardComponent"; | ||||
|  | ||||
| export default async function ClipboardPage() { | ||||
|   const clipboard = await getClipboard(); | ||||
|   return ( | ||||
|     <> | ||||
|       <ClipboardComponent initialContent={clipboard} /> | ||||
|     </> | ||||
|   ); | ||||
| } | ||||
| @@ -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 ( | ||||
|     <html lang="en"> | ||||
|       <body> | ||||
| @@ -28,7 +31,7 @@ export default function RootLayout({ | ||||
|         > | ||||
|           <Title /> | ||||
|  | ||||
|           <Navbar /> | ||||
|           <Navbar isLoggedIn={isLoggedIn} /> | ||||
|           <div | ||||
|             className={bodyFont.className} | ||||
|             style={{ | ||||
|   | ||||
| @@ -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)} | ||||
|   | ||||
| @@ -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 === "/") { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user