add clipboard
All checks were successful
Build / build (push) Successful in 3m28s

This commit is contained in:
Nareshkumar Rao 2025-04-08 00:23:36 +02:00
parent f28c2defc4
commit edc575b153
8 changed files with 104 additions and 6 deletions

View File

@ -0,0 +1,7 @@
-- CreateTable
CREATE TABLE "Clipboard" (
"id" SERIAL NOT NULL,
"content" TEXT NOT NULL,
CONSTRAINT "Clipboard_pkey" PRIMARY KEY ("id")
);

View File

@ -30,3 +30,8 @@ model User {
username String @unique
password String
}
model Clipboard {
id Int @id @default(autoincrement())
content String @db.Text
}

View 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>
</>
);
}

View 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 || "";
}

View 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} />
</>
);
}

View File

@ -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={{

View File

@ -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)}

View File

@ -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 === "/") {