diff --git a/src/app/(editor)/layout.tsx b/src/app/(editor)/layout.tsx deleted file mode 100644 index e2e6109..0000000 --- a/src/app/(editor)/layout.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import Header from "@/components/Header"; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - <> -
- {children} - - ); -} diff --git a/src/app/(noneditor)/layout.tsx b/src/app/(noneditor)/layout.tsx deleted file mode 100644 index 311c52a..0000000 --- a/src/app/(noneditor)/layout.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import Header from "@/components/Header"; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - <> -
-
- {children} -
- - ); -} diff --git a/src/app/(noneditor)/about/page.tsx b/src/app/about/page.tsx similarity index 100% rename from src/app/(noneditor)/about/page.tsx rename to src/app/about/page.tsx diff --git a/src/app/(noneditor)/auth/page.tsx b/src/app/auth/page.tsx similarity index 100% rename from src/app/(noneditor)/auth/page.tsx rename to src/app/auth/page.tsx diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 0a82250..11099cd 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,6 @@ import { Metadata } from "next"; import { Noto_Sans_Mono } from "next/font/google"; +import Header from "@/components/Header"; import "./globals.css"; const notoSansMono = Noto_Sans_Mono({ @@ -20,7 +21,10 @@ export default function RootLayout({ return ( - {children} +
+
+ {children} +
); diff --git a/src/app/(noneditor)/notes/new/page.tsx b/src/app/notes/new/page.tsx similarity index 100% rename from src/app/(noneditor)/notes/new/page.tsx rename to src/app/notes/new/page.tsx diff --git a/src/app/(noneditor)/notes/page.tsx b/src/app/notes/page.tsx similarity index 68% rename from src/app/(noneditor)/notes/page.tsx rename to src/app/notes/page.tsx index 18a3cb6..d396fca 100644 --- a/src/app/(noneditor)/notes/page.tsx +++ b/src/app/notes/page.tsx @@ -1,5 +1,7 @@ import { Metadata } from "next"; +import { redirect } from "next/navigation"; import { getNotes } from "@/lib/notes"; +import { getAuth } from "@/lib/auth"; import NoteCard from "@/components/ui/NoteCard"; export const metadata: Metadata = { @@ -8,11 +10,16 @@ export const metadata: Metadata = { }; export default async function Notes() { - const notes = await getNotes(); + const auth = await getAuth(); + if (!auth) { + redirect("/auth"); + } + + const notes = await getNotes(auth.id); return ( <> -

Notes

+

Notes of {auth.username}:

{notes ? ( notes.length > 0 ? ( notes.map((note) => ) diff --git a/src/app/(editor)/page.tsx b/src/app/page.tsx similarity index 100% rename from src/app/(editor)/page.tsx rename to src/app/page.tsx diff --git a/src/components/Header.tsx b/src/components/Header.tsx index e87d96e..3de09a0 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,10 +1,10 @@ import Link from "next/link"; -import { ArrowRightFromLine, CircleQuestionMark, List, Plus, UserRound, UserRoundMinus } from "lucide-react"; +import { CircleQuestionMark, List, Plus, UserRound, UserRoundMinus } from "lucide-react"; import { logOut } from "@/app/actions"; import { getAuth } from "@/lib/auth"; import HeaderButton from "./ui/HeaderButton"; -export default async function Header({ allowExport = false }: { allowExport?: boolean }) { +export default async function Header() { const auth = await getAuth(); return ( @@ -13,19 +13,16 @@ export default async function Header({ allowExport = false }: { allowExport?: bo -
- {auth && ( - <> + {auth && ( +
} /> } /> - - )} - {allowExport && } />} -
+
+ )}
diff --git a/src/components/editor/Editor.tsx b/src/components/editor/Editor.tsx index dce59c7..0c925de 100644 --- a/src/components/editor/Editor.tsx +++ b/src/components/editor/Editor.tsx @@ -1,7 +1,7 @@ "use client"; import { useReducer } from "react"; -import { Plus } from "lucide-react"; +import { Copy, Plus } from "lucide-react"; import { editorReducer } from "@/lib/editorReducer"; import IconOnlyButton from "../ui/IconOnlyButton"; import Block from "./Block"; @@ -23,11 +23,18 @@ export default function Editor() { dispatch({ type: "add_block" }); } + const handleCopy = () => { + dispatch({ type: "copy" }); + } + return (
{state.map((block) => )} - } /> +
+ } /> + } title="Copy note to clipboard" /> +
); } diff --git a/src/components/ui/NoteCard.tsx b/src/components/ui/NoteCard.tsx index 27e3bdc..b0c2ac4 100644 --- a/src/components/ui/NoteCard.tsx +++ b/src/components/ui/NoteCard.tsx @@ -5,6 +5,15 @@ import { notesTable } from "@/lib/db/schema"; import { deleteNote } from "@/lib/notes"; import IconOnlyButton from "./IconOnlyButton"; +function makeTimestamp(date: Date) { + const day = date.getDate(); + const month = date.getMonth() + 1; + const year = date.getFullYear(); + const hours = date.getHours(); + const minutes = date.getMinutes(); + return `${day}.${month}.${year} ${hours}:${minutes}`; +} + export default function NoteCard({ note }: { note: typeof notesTable.$inferSelect }) { const handleDeleteNote = async () => { "use server"; @@ -13,11 +22,11 @@ export default function NoteCard({ note }: { note: typeof notesTable.$inferSelec } return ( -
- +
+

{note.name}

- Creation date: {note.creationTime.toString()} - Last time edited: {note.lastEdited.toString()} + Last time edited: {makeTimestamp(note.lastEdited)} + Creation date: {makeTimestamp(note.creationTime)} } onClick={handleDeleteNote} />
diff --git a/src/lib/editorReducer.ts b/src/lib/editorReducer.ts index 8cd7004..c1ec579 100644 --- a/src/lib/editorReducer.ts +++ b/src/lib/editorReducer.ts @@ -14,6 +14,7 @@ type EditorState = IBlock[]; export type Action = | { type: "add_block" } + | { type: "copy" } | { type: "delete_block", blockId: string } | { type: "add_line", blockId: string } | { type: "delete_line", blockId: string } @@ -36,6 +37,21 @@ export function editorReducer(state: EditorState, action: Action): EditorState { })), } ]; + + case "copy": + let copyText = ""; + + state.forEach((block) => { + if (block.tag !== "") { + copyText += `[${block.tag}]\n`; + } + + block.lines.forEach((line) => copyText += line.text + "\n") + copyText += "\n"; + }); + + navigator.clipboard.writeText(copyText); + return state; case "delete_block": return state.filter((block) => block.id !== action.blockId); diff --git a/src/lib/notes.ts b/src/lib/notes.ts index 7a095f3..0ee1727 100644 --- a/src/lib/notes.ts +++ b/src/lib/notes.ts @@ -1,17 +1,13 @@ -import { eq } from "drizzle-orm"; +import { desc, eq } from "drizzle-orm"; import { notesTable } from "./db/schema"; import { getAuth } from "./auth"; import { db } from "./db"; -export async function getNotes() { - const auth = await getAuth(); - if (!auth) { - return null; - } - +export async function getNotes(authorId: string) { return db.select() .from(notesTable) - .where(eq(notesTable.authorId, auth.id)); + .where(eq(notesTable.authorId, authorId)) + .orderBy(desc(notesTable.lastEdited)); } export async function createNote() {