fix: start database fix
This commit is contained in:
parent
917e460a96
commit
7d76ec1974
55
package-lock.json
generated
55
package-lock.json
generated
@ -1046,9 +1046,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/core": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz",
|
||||
"integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==",
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
|
||||
"integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@ -1083,9 +1083,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.30.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.30.1.tgz",
|
||||
"integrity": "sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==",
|
||||
"version": "9.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz",
|
||||
"integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -1119,19 +1119,6 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
|
||||
"integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
||||
@ -1669,16 +1656,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "0.2.11",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz",
|
||||
"integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==",
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
|
||||
"integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/core": "^1.4.3",
|
||||
"@emnapi/runtime": "^1.4.3",
|
||||
"@tybys/wasm-util": "^0.9.0"
|
||||
"@tybys/wasm-util": "^0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
@ -2179,9 +2166,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tybys/wasm-util": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz",
|
||||
"integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==",
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz",
|
||||
"integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
@ -2239,9 +2226,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.19.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.6.tgz",
|
||||
"integrity": "sha512-uYssdp9z5zH5GQ0L4zEJ2ZuavYsJwkozjiUzCRfGtaaQcyjAMJ34aP8idv61QlqTozu6kudyr6JMq9Chf09dfA==",
|
||||
"version": "20.19.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.7.tgz",
|
||||
"integrity": "sha512-1GM9z6BJOv86qkPvzh2i6VW5+VVrXxCLknfmTkWEqz+6DqosiY28XUWCTmBcJ0ACzKqx/iwdIREfo1fwExIlkA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -3943,9 +3930,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.30.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.30.1.tgz",
|
||||
"integrity": "sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==",
|
||||
"version": "9.31.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz",
|
||||
"integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -3953,9 +3940,9 @@
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.21.0",
|
||||
"@eslint/config-helpers": "^0.3.0",
|
||||
"@eslint/core": "^0.14.0",
|
||||
"@eslint/core": "^0.15.0",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "9.30.1",
|
||||
"@eslint/js": "9.31.0",
|
||||
"@eslint/plugin-kit": "^0.3.1",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
|
@ -1,10 +1,8 @@
|
||||
"use server";
|
||||
|
||||
import { cookies } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "@/lib/db";
|
||||
import { cookies } from "next/headers";
|
||||
import { usersTable } from "@/lib/db/schema";
|
||||
import { db } from "@/lib/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import jwt from "jsonwebtoken";
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
@ -82,6 +80,29 @@ export async function register(_prevState: unknown, formData: FormData) {
|
||||
redirect("/notes");
|
||||
}
|
||||
|
||||
export async function getAuth() {
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get("session")?.value;
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const decodedToken = jwt.decode(token) as jwt.JwtPayload;
|
||||
const username = decodedToken.sub;
|
||||
if (!username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const users = await db.select()
|
||||
.from(usersTable)
|
||||
.where(eq(usersTable.username, username));
|
||||
if (users.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return users[0];
|
||||
}
|
||||
|
||||
export async function logOut() {
|
||||
const cookieStore = await cookies();
|
||||
cookieStore.delete("session");
|
||||
|
@ -1,42 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { blocksTable, IBlock, INote } from "@/lib/db/schema";
|
||||
import { db } from "@/lib/db";
|
||||
|
||||
export async function createBlock(note: INote) {
|
||||
await db
|
||||
.insert(blocksTable)
|
||||
.values({ noteId: note.id });
|
||||
|
||||
revalidatePath("/blocks/[id]");
|
||||
}
|
||||
|
||||
export async function getBlocks(note: INote) {
|
||||
return db.select()
|
||||
.from(blocksTable)
|
||||
.where(and(eq(blocksTable.noteId, note.id)));
|
||||
}
|
||||
|
||||
export async function updateBlockTag(block: IBlock, newTag: string) {
|
||||
await db
|
||||
.update(blocksTable)
|
||||
.set({ tag: newTag })
|
||||
.where(eq(blocksTable.id, block.id));
|
||||
}
|
||||
|
||||
export async function deleteBlock(block: IBlock) {
|
||||
await db.delete(blocksTable)
|
||||
.where(and(eq(blocksTable.id, block.id)));
|
||||
|
||||
revalidatePath("/blocks/[id]");
|
||||
}
|
||||
|
||||
export async function switchLock(block: IBlock) {
|
||||
await db.update(blocksTable)
|
||||
.set({ isLocked: !block.isLocked })
|
||||
.where(and(eq(blocksTable.id, block.id)));
|
||||
|
||||
revalidatePath("/blocks/[id]");
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import { redirect } from "next/navigation";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { validate as uuidValidate } from "uuid";
|
||||
import { notesTable } from "@/lib/db/schema";
|
||||
import { getAuth } from "@/lib/auth";
|
||||
import { eq, and, desc } from "drizzle-orm";
|
||||
import { db } from "@/lib/db";
|
||||
|
||||
export async function createNote() {
|
||||
const auth = await getAuth();
|
||||
if (!auth) {
|
||||
redirect("/auth");
|
||||
}
|
||||
|
||||
const notes = await db
|
||||
.insert(notesTable)
|
||||
.values({ authorId: auth.id })
|
||||
.returning({ id: notesTable.id });
|
||||
|
||||
redirect(`/notes/${notes[0].id}`);
|
||||
}
|
||||
|
||||
export async function getNotes(authorId: string) {
|
||||
return db.select()
|
||||
.from(notesTable)
|
||||
.where(eq(notesTable.authorId, authorId))
|
||||
.orderBy(desc(notesTable.lastEdited));
|
||||
}
|
||||
|
||||
export async function getNote(noteId: string) {
|
||||
if (!uuidValidate(noteId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const auth = await getAuth();
|
||||
if (!auth) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const notes = await db.select()
|
||||
.from(notesTable)
|
||||
.where(and(eq(notesTable.id, noteId), eq(notesTable.authorId, auth.id)));
|
||||
|
||||
if (notes.length === 0) {
|
||||
return null;
|
||||
} else {
|
||||
return notes[0];
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteNote(noteId: string) {
|
||||
if (!uuidValidate(noteId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const auth = await getAuth();
|
||||
if (!auth) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await db.delete(notesTable).where(eq(notesTable.id, noteId));
|
||||
revalidatePath("/notes");
|
||||
}
|
||||
|
||||
export async function updateTitle(noteId: string, title: string) {
|
||||
await db
|
||||
.update(notesTable)
|
||||
.set({ title })
|
||||
.where(eq(notesTable.id, noteId));
|
||||
}
|
@ -1,34 +1,18 @@
|
||||
import { Metadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getBlocks } from "@/app/actions/blocks";
|
||||
import { getNote } from "@/app/actions/notes";
|
||||
import Editor from "@/components/editor/Editor";
|
||||
|
||||
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise<Metadata> {
|
||||
const { id } = await params;
|
||||
const note = await getNote(id);
|
||||
if (!note) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return { title: note.title };
|
||||
return { title: id };
|
||||
}
|
||||
|
||||
export default async function Note({ params }: { params: Promise<{ id: string }> }) {
|
||||
const { id } = await params;
|
||||
const note = await getNote(id);
|
||||
if (!note) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const blocks = await getBlocks(note);
|
||||
if (!blocks) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex justify-center">
|
||||
<Editor note={note} blocks={blocks} />
|
||||
{id}
|
||||
<Editor />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
import { Metadata } from "next";
|
||||
import { redirect } from "next/navigation";
|
||||
import { getNotes } from "@/app/actions/notes";
|
||||
import { getAuth } from "@/lib/auth";
|
||||
import NoteCard from "@/components/ui/NoteCard";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Notes - Rhyme",
|
||||
@ -10,25 +6,10 @@ export const metadata: Metadata = {
|
||||
};
|
||||
|
||||
export default async function Notes() {
|
||||
const auth = await getAuth();
|
||||
if (!auth) {
|
||||
redirect("/auth");
|
||||
}
|
||||
|
||||
const notes = await getNotes(auth.id);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className="font-bold text-xl mb-4">Notes of {auth.username}:</h1>
|
||||
{notes ? (
|
||||
notes.length > 0 ? (
|
||||
notes.map((note) => <NoteCard key={note.id} note={note} />)
|
||||
) : (
|
||||
<span>You don't have any saved notes!</span>
|
||||
)
|
||||
) : (
|
||||
<span>Failed to get notes! Please, try again.</span>
|
||||
)}
|
||||
<h1 className="font-bold text-xl mb-4">Notes of (username):</h1>
|
||||
{/* notes */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
import Link from "next/link";
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAuth } from "@/lib/auth";
|
||||
import { getAuth } from "@/app/actions/auth";
|
||||
import Editor from "@/components/editor/Editor";
|
||||
|
||||
export default async function Home() {
|
||||
const auth = await getAuth();
|
||||
|
||||
if (auth) {
|
||||
redirect("/notes");
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { CircleQuestionMark, List, Plus, UserRound, UserRoundMinus } from "lucide-react";
|
||||
import { createNote } from "@/app/actions/notes";
|
||||
import { logOut } from "@/app/actions/auth";
|
||||
import { getAuth } from "@/lib/auth";
|
||||
import { getAuth } from "@/app/actions/auth";
|
||||
import HeaderButton from "./ui/HeaderButton";
|
||||
|
||||
export default async function Header() {
|
||||
@ -16,7 +14,7 @@ export default async function Header() {
|
||||
|
||||
{auth && (
|
||||
<div className="flex gap-2">
|
||||
<HeaderButton onClick={createNote} title="new" icon={<Plus size={20} />} />
|
||||
<HeaderButton title="new" icon={<Plus size={20} />} />
|
||||
<Link href="/notes">
|
||||
<HeaderButton title="list" icon={<List size={20} />} />
|
||||
</Link>
|
||||
@ -28,7 +26,7 @@ export default async function Header() {
|
||||
<HeaderButton title="about" icon={<CircleQuestionMark size={20} />} />
|
||||
</Link>
|
||||
{auth ? (
|
||||
<HeaderButton onClick={logOut} title="log out" icon={<UserRoundMinus size={20} />} />
|
||||
<HeaderButton title="log out" icon={<UserRoundMinus size={20} />} />
|
||||
) : (
|
||||
<Link href="/auth">
|
||||
<HeaderButton title="login" icon={<UserRound size={20} />} />
|
||||
|
@ -1,37 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import { ChangeEvent } from "react";
|
||||
import { ArrowDown, ArrowUp, Lock, LockOpen, Minus, Plus, X } from "lucide-react";
|
||||
import { IBlock } from "@/lib/db/schema";
|
||||
import { switchLock, deleteBlock } from "@/app/actions/blocks";
|
||||
import { ArrowDown, ArrowUp, LockOpen, Minus, Plus, X } from "lucide-react";
|
||||
import IconOnlyButton from "../ui/IconOnlyButton";
|
||||
import LineInput from "./LineInput";
|
||||
|
||||
export default function Block({ block }: { block: IBlock }) {
|
||||
const handleAddLine = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
const handleDeleteLine = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
const handleTagUpdate = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
const handleLineUpdate = (e: ChangeEvent<HTMLInputElement>, line: string) => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
const handleBlockUp = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
const handleBlockDown = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
export default function Block() {
|
||||
return (
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<div className="border-2 border-neutral-800 rounded-lg p-3 w-full">
|
||||
@ -39,34 +12,20 @@ export default function Block({ block }: { block: IBlock }) {
|
||||
type="text"
|
||||
placeholder="enter tag..."
|
||||
className="w-full focus:outline-none"
|
||||
defaultValue={block.tag}
|
||||
disabled={block.isLocked}
|
||||
onChange={handleTagUpdate}
|
||||
/>
|
||||
{block.lines.map((line, i) => (
|
||||
<LineInput
|
||||
key={i}
|
||||
defaultValue={line}
|
||||
disabled={block.isLocked}
|
||||
onChange={(e) => handleLineUpdate(e, line)}
|
||||
/>
|
||||
))}
|
||||
<LineInput />
|
||||
<div className="flex items-center mx-2 mt-2">
|
||||
<div className="flex gap-1 mr-4">
|
||||
<IconOnlyButton onClick={handleAddLine} icon={<Plus size={18} />} />
|
||||
<IconOnlyButton onClick={handleDeleteLine} icon={<Minus size={18} />} />
|
||||
<IconOnlyButton icon={<Plus size={18} />} />
|
||||
<IconOnlyButton icon={<Minus size={18} />} />
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
<IconOnlyButton onClick={handleBlockUp} icon={<ArrowUp size={18} />} />
|
||||
<IconOnlyButton onClick={handleBlockDown} icon={<ArrowDown size={18} />} />
|
||||
<IconOnlyButton icon={<ArrowUp size={18} />} />
|
||||
<IconOnlyButton icon={<ArrowDown size={18} />} />
|
||||
</div>
|
||||
<div className="flex gap-2 ml-auto">
|
||||
<IconOnlyButton onClick={() => deleteBlock(block)} icon={<X size={18} />} />
|
||||
<IconOnlyButton
|
||||
onClick={() => switchLock(block)}
|
||||
icon={block.isLocked ? <Lock size={18} /> : <LockOpen size={18} />}
|
||||
alwaysOn={block.isLocked}
|
||||
/>
|
||||
<IconOnlyButton icon={<X size={18} />} />
|
||||
<IconOnlyButton icon={<LockOpen size={18} />} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,70 +1,17 @@
|
||||
"use client";
|
||||
|
||||
import { ChangeEvent, useState } from "react";
|
||||
import { Copy, Plus } from "lucide-react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { createBlock } from "@/app/actions/blocks";
|
||||
import { IBlock, INote } from "@/lib/db/schema";
|
||||
import IconOnlyButton from "../ui/IconOnlyButton";
|
||||
import Block from "./Block";
|
||||
|
||||
interface EditorProps {
|
||||
note? : INote;
|
||||
blocks? : IBlock[];
|
||||
}
|
||||
|
||||
const defaultNoteId = uuidv4();
|
||||
|
||||
const defaultNote: INote = {
|
||||
id: defaultNoteId,
|
||||
title: "Untitled",
|
||||
creationTime: new Date(),
|
||||
lastEdited: new Date(),
|
||||
authorId: uuidv4(),
|
||||
};
|
||||
|
||||
const defaultBlocks: IBlock[] = [
|
||||
{
|
||||
id: uuidv4(),
|
||||
tag: "",
|
||||
order: 1,
|
||||
isLocked: false,
|
||||
noteId: defaultNoteId,
|
||||
lines: ["", "", "", ""],
|
||||
},
|
||||
];
|
||||
|
||||
export default function Editor({ note = defaultNote, blocks = defaultBlocks }: EditorProps) {
|
||||
const [title, setTitle] = useState(note.title);
|
||||
|
||||
const handleUpdateTitle = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setTitle(e.target.value);
|
||||
}
|
||||
|
||||
const handleCopy = () => {
|
||||
let copyString = "";
|
||||
|
||||
blocks.forEach((block) => {
|
||||
if (block.tag !== "") {
|
||||
copyString += `[${block.tag}]`;
|
||||
}
|
||||
copyString += block.lines + "\n";
|
||||
});
|
||||
|
||||
navigator.clipboard.writeText(copyString);
|
||||
}
|
||||
|
||||
export default function Editor() {
|
||||
return (
|
||||
<div className="flex flex-col items-center max-w-2xl w-full gap-4">
|
||||
<input
|
||||
className="font-bold text-xl w-full text-center focus:outline-none"
|
||||
value={title}
|
||||
onChange={handleUpdateTitle}
|
||||
/>
|
||||
{blocks.map((block) => <Block key={block.id} block={block} /> )}
|
||||
<input className="font-bold text-xl w-full text-center focus:outline-none" />
|
||||
<Block />
|
||||
<div className="flex gap-2">
|
||||
<IconOnlyButton onClick={() => createBlock(note)} icon={<Plus size={24} />} />
|
||||
<IconOnlyButton onClick={handleCopy} icon={<Copy size={24} />} title="Copy note to clipboard" />
|
||||
<IconOnlyButton icon={<Plus size={24} />} />
|
||||
<IconOnlyButton icon={<Copy size={24} />} title="Copy note to clipboard" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { X } from "lucide-react";
|
||||
import { INote } from "@/lib/db/schema";
|
||||
import { deleteNote } from "@/app/actions/notes";
|
||||
import IconOnlyButton from "./IconOnlyButton";
|
||||
|
||||
function makeTimestamp(date: Date) {
|
||||
@ -14,11 +13,6 @@ function makeTimestamp(date: Date) {
|
||||
}
|
||||
|
||||
export default function NoteCard({ note }: { note: INote }) {
|
||||
const handleDelete = async () => {
|
||||
"use server";
|
||||
await deleteNote(note.id);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center mb-3 gap-4">
|
||||
<Link href={`/notes/${note.id}`} className="flex flex-col border border-neutral-500 py-3 px-4 rounded-lg hover:bg-neutral-800 w-full">
|
||||
@ -26,7 +20,7 @@ export default function NoteCard({ note }: { note: INote }) {
|
||||
<i className="text-neutral-400 text-sm">Last time edited: {makeTimestamp(note.lastEdited)}</i>
|
||||
<i className="text-neutral-400 text-sm">Creation date: {makeTimestamp(note.creationTime)}</i>
|
||||
</Link>
|
||||
<IconOnlyButton icon={<X size={24} />} onClick={handleDelete} />
|
||||
<IconOnlyButton icon={<X size={24} />} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
import { cookies } from "next/headers";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { usersTable } from "./db/schema";
|
||||
import { db } from "./db";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
export async function getAuth() {
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get("session")?.value;
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const decodedToken = jwt.decode(token) as jwt.JwtPayload;
|
||||
const username = decodedToken.sub;
|
||||
if (!username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const users = await db.select()
|
||||
.from(usersTable)
|
||||
.where(eq(usersTable.username, username));
|
||||
if (users.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return users[0];
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useEffect } from "react";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
Loading…
x
Reference in New Issue
Block a user