This commit is contained in:
parent
f28c2defc4
commit
edc575b153
@ -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 === "/") {
|
||||
|
Loading…
x
Reference in New Issue
Block a user