-
- {state.blocks.map((block) =>
)}
+
+
+ {blocks.map((block) =>
)}
-
} />
+
createBlock(note)} icon={} />
} title="Copy note to clipboard" />
diff --git a/src/components/ui/NoteCard.tsx b/src/components/ui/NoteCard.tsx
index b0c2ac4..5964a03 100644
--- a/src/components/ui/NoteCard.tsx
+++ b/src/components/ui/NoteCard.tsx
@@ -1,8 +1,7 @@
import Link from "next/link";
-import { revalidatePath } from "next/cache";
import { X } from "lucide-react";
-import { notesTable } from "@/lib/db/schema";
-import { deleteNote } from "@/lib/notes";
+import { INote } from "@/lib/db/schema";
+import { deleteNote } from "@/app/actions/notes";
import IconOnlyButton from "./IconOnlyButton";
function makeTimestamp(date: Date) {
@@ -14,21 +13,20 @@ function makeTimestamp(date: Date) {
return `${day}.${month}.${year} ${hours}:${minutes}`;
}
-export default function NoteCard({ note }: { note: typeof notesTable.$inferSelect }) {
- const handleDeleteNote = async () => {
+export default function NoteCard({ note }: { note: INote }) {
+ const handleDelete = async () => {
"use server";
await deleteNote(note.id);
- revalidatePath("/notes");
}
return (
-
{note.name}
+ {note.title}
Last time edited: {makeTimestamp(note.lastEdited)}
Creation date: {makeTimestamp(note.creationTime)}
- } onClick={handleDeleteNote} />
+ } onClick={handleDelete} />
);
}
diff --git a/src/lib/db/schema.ts b/src/lib/db/schema.ts
index fa05a09..90b8da4 100644
--- a/src/lib/db/schema.ts
+++ b/src/lib/db/schema.ts
@@ -1,4 +1,4 @@
-import { pgTable, json, varchar, timestamp, uuid } from "drizzle-orm/pg-core";
+import { pgTable, varchar, timestamp, uuid, boolean, integer, json } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
export const usersTable = pgTable("users", {
@@ -13,10 +13,10 @@ export const usersRelations = relations(usersTable, ({ many }) => ({
export const notesTable = pgTable("notes", {
id: uuid().primaryKey().defaultRandom(),
- name: varchar({ length: 50 }).notNull().default("Untitled"),
+ title: varchar({ length: 50 }).notNull().default("Untitled"),
creationTime: timestamp().notNull().defaultNow(),
lastEdited: timestamp().notNull().defaultNow(),
- authorId: uuid(),
+ authorId: uuid().notNull(),
});
export const notesRelations = relations(notesTable, ({ one }) => ({
@@ -29,8 +29,10 @@ export const notesRelations = relations(notesTable, ({ one }) => ({
export const blocksTable = pgTable("blocks", {
id: uuid().primaryKey().defaultRandom(),
tag: varchar({ length: 100 }).notNull().default(""),
- lines: json().notNull().default([]),
- noteId: uuid(),
+ lines: json().notNull().default(["", "", "", ""]).$type
(),
+ isLocked: boolean().notNull().default(false),
+ order: integer().notNull().default(1),
+ noteId: uuid().notNull(),
});
export const blocksRelations = relations(blocksTable, ({ one }) => ({
@@ -39,3 +41,7 @@ export const blocksRelations = relations(blocksTable, ({ one }) => ({
references: [notesTable.id],
}),
}));
+
+export type IUser = typeof usersTable.$inferSelect;
+export type INote = typeof notesTable.$inferSelect;
+export type IBlock = typeof blocksTable.$inferSelect;
diff --git a/src/lib/editorReducer.ts b/src/lib/editorReducer.ts
deleted file mode 100644
index 62be492..0000000
--- a/src/lib/editorReducer.ts
+++ /dev/null
@@ -1,192 +0,0 @@
-import { v4 as uuidv4 } from "uuid";
-
-export type ILine = {
- id: string;
- text: string;
-};
-
-export type IBlock = {
- id: string;
- tag: string;
- locked: boolean;
- lines: ILine[];
-};
-
-type EditorState = {
- title: string;
- blocks: IBlock[];
-};
-
-export type Action =
- | { type: "add_block" }
- | { type: "copy" }
- | { type: "delete_block", blockId: string }
- | { type: "add_line", blockId: string }
- | { type: "delete_line", blockId: string }
- | { type: "update_title", title: string }
- | { type: "update_line_text"; blockId: string; lineId: string; text: string }
- | { type: "update_tag"; blockId: string; tag: string }
- | { type: "move_block_up", blockId: string }
- | { type: "move_block_down", blockId: string }
- | { type: "toggle_lock", blockId: string };
-
-export function editorReducer(state: EditorState, action: Action): EditorState {
- switch (action.type) {
- case "update_title":
- return {
- ...state,
- title: action.title,
- };
-
- case "add_block":
- return {
- ...state,
- blocks: [
- ...state.blocks,
- {
- id: uuidv4(),
- tag: "",
- locked: false,
- lines: Array.from({ length: 4 }, () => ({
- id: uuidv4(),
- text: "",
- })),
- }
- ]
- };
-
- case "copy":
- let copyText = "";
-
- state.blocks.forEach((block) => {
- if (block.tag !== "") {
- copyText += `[${block.tag}]\n`;
- }
-
- block.lines.forEach((line) => {
- if (line.text !== "") {
- copyText += line.text + "\n";
- }
- })
- copyText += "\n";
- });
-
- navigator.clipboard.writeText(copyText);
- return state;
-
- case "delete_block":
- return {
- ...state,
- blocks: state.blocks.filter((block) => block.id !== action.blockId),
- };
-
- case "add_line":
- return {
- ...state,
- blocks: state.blocks.map((block) => {
- if (block.id === action.blockId) {
- return {
- ...block,
- lines: [...block.lines, { id: uuidv4(), text: "" }],
- };
- } else {
- return block;
- }
- }),
- };
-
- case "delete_line":
- return {
- ...state,
- blocks: state.blocks.map((block) => {
- if (block.id === action.blockId && block.lines.length > 0) {
- return {
- ...block,
- lines: block.lines.slice(0, -1),
- };
- } else {
- return block;
- }
- }),
- };
-
- case "update_line_text":
- return {
- ...state,
- blocks: state.blocks.map((block) => {
- if (block.id === action.blockId) {
- return {
- ...block,
- lines: block.lines.map((line) => {
- if (line.id === action.lineId) {
- return {
- ...line,
- text: action.text,
- };
- } else {
- return line;
- }
- }),
- };
- } else {
- return block;
- }
- }),
- };
-
- case "update_tag":
- return {
- ...state,
- blocks: state.blocks.map((block) => {
- if (block.id === action.blockId) {
- return {
- ...block,
- tag: action.tag,
- };
- } else {
- return block;
- }
- }),
- };
-
- case "move_block_up": {
- const index = state.blocks.findIndex((b) => b.id === action.blockId);
- if (index <= 0) return state;
- const newBlocks = [...state.blocks];
- [newBlocks[index - 1], newBlocks[index]] = [newBlocks[index], newBlocks[index - 1]];
- return {
- ...state,
- blocks: newBlocks,
- };
- }
-
- case "move_block_down": {
- const index = state.blocks.findIndex((b) => b.id === action.blockId);
- if (index === state.blocks.length - 1) return state;
- const newBlocks = [...state.blocks];
- [newBlocks[index], newBlocks[index + 1]] = [newBlocks[index + 1], newBlocks[index]];
- return {
- ...state,
- blocks: newBlocks,
- };
- }
-
- case "toggle_lock":
- return {
- ...state,
- blocks: state.blocks.map((block) => {
- if (block.id === action.blockId) {
- return {
- ...block,
- locked: !block.locked,
- };
- } else {
- return block;
- }
- }),
- };
-
- default:
- return state;
- }
-}
diff --git a/src/lib/hooks/useDebounce.ts b/src/lib/hooks/useDebounce.ts
new file mode 100644
index 0000000..db9fd2f
--- /dev/null
+++ b/src/lib/hooks/useDebounce.ts
@@ -0,0 +1,9 @@
+import { useEffect } from "react";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export function useDebounce(callback: () => void, deps: any[]) {
+ useEffect(() => {
+ const timeout = setTimeout(callback, 1000);
+ return () => clearTimeout(timeout);
+ }, deps);
+}