feat: add line saves
This commit is contained in:
parent
5da589c331
commit
ed28943b54
@ -89,7 +89,6 @@ export async function moveUp(formData: FormData) {
|
||||
const block = await getBlock(blockId);
|
||||
if (!block) return;
|
||||
|
||||
// Найти блок, который перед текущим
|
||||
const siblings = await getBlocks(block.noteId);
|
||||
const currentIndex = siblings.findIndex((b) => b.id === block.id);
|
||||
if (currentIndex <= 0) return;
|
||||
@ -136,3 +135,18 @@ export async function moveDown(formData: FormData) {
|
||||
|
||||
revalidatePath("/notes/[id]", "page");
|
||||
}
|
||||
|
||||
export async function setLines(blockId: string, lines: string[]) {
|
||||
console.log(lines)
|
||||
await db
|
||||
.update(blocksTable)
|
||||
.set({ lines })
|
||||
.where(eq(blocksTable.id, blockId));
|
||||
}
|
||||
|
||||
export async function setTag(blockId: string, tag: string) {
|
||||
await db
|
||||
.update(blocksTable)
|
||||
.set({ tag })
|
||||
.where(eq(blocksTable.id, blockId));
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import { revalidatePath } from "next/cache";
|
||||
import { redirect } from "next/navigation";
|
||||
import { desc, eq, and } from "drizzle-orm";
|
||||
import { blocksTable, INote, notesTable, usersTable } from "@/lib/db/schema";
|
||||
import { db } from "@/lib/db";
|
||||
import { requireAuth } from "./auth";
|
||||
import { db } from "@/lib/db";
|
||||
|
||||
export async function createNote() {
|
||||
const user = await requireAuth();
|
||||
@ -45,3 +45,11 @@ export async function deleteNote(formData: FormData) {
|
||||
.where(and(eq(notesTable.id, noteId), eq(notesTable.authorId, user.id)));
|
||||
revalidatePath("/notes");
|
||||
}
|
||||
|
||||
export async function setTitle(noteId: string, title: string) {
|
||||
await db
|
||||
.update(notesTable)
|
||||
.set({ title })
|
||||
.where(eq(notesTable.id, noteId));
|
||||
revalidatePath("/notes/[id]", "page");
|
||||
}
|
||||
|
@ -1,10 +1,24 @@
|
||||
import { ChangeEvent, useState } from "react";
|
||||
import { ArrowDown, ArrowUp, LockOpen, Lock, Minus, Plus, X } from "lucide-react";
|
||||
import { addLine, changeLock, deleteBlock, deleteLine, moveDown, moveUp } from "@/app/actions/blocks";
|
||||
import { addLine, changeLock, deleteBlock, deleteLine, moveDown, moveUp, setLines } from "@/app/actions/blocks";
|
||||
import { useDebounce } from "@/lib/hooks/useDebounce";
|
||||
import { IBlock } from "@/lib/db/schema";
|
||||
import IconOnlyButton from "../ui/IconOnlyButton";
|
||||
import LineInput from "./LineInput";
|
||||
|
||||
export default function Block({ block }: { block: IBlock }) {
|
||||
const [lines, setLinesState] = useState(block.lines);
|
||||
|
||||
useDebounce(() => {
|
||||
setLines(block.id, lines);
|
||||
}, [lines]);
|
||||
|
||||
const lineChangeHandler = (i: number, e: ChangeEvent<HTMLInputElement>) => {
|
||||
const newLines = [...lines];
|
||||
newLines[i] = e.target.value;
|
||||
setLinesState(newLines);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<div className="border-2 border-neutral-800 rounded-lg p-3 w-full">
|
||||
@ -16,7 +30,7 @@ export default function Block({ block }: { block: IBlock }) {
|
||||
disabled={block.isLocked}
|
||||
/>
|
||||
{block.lines.map((line, i) => (
|
||||
<LineInput key={i} defaultValue={line} disabled={block.isLocked} />
|
||||
<LineInput key={i} defaultValue={line} disabled={block.isLocked} onChange={(e) => lineChangeHandler(i, e)} />
|
||||
))}
|
||||
<div className="flex items-center mx-2 mt-2">
|
||||
<div className="flex gap-1 mr-4">
|
||||
|
@ -1,11 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Copy, Plus } from "lucide-react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { IBlock, INote } from "@/lib/db/schema";
|
||||
import { createBlock } from "@/app/actions/blocks";
|
||||
import IconOnlyButton from "../ui/IconOnlyButton";
|
||||
import Block from "./Block";
|
||||
import { useDebounce } from "@/lib/hooks/useDebounce";
|
||||
import { setTitle } from "@/app/actions/notes";
|
||||
|
||||
const defaultNoteId = uuidv4();
|
||||
|
||||
@ -35,6 +38,8 @@ export default function Editor({
|
||||
note?: INote;
|
||||
blocks?: IBlock[];
|
||||
}) {
|
||||
const [title, setTitleState] = useState(note.title);
|
||||
|
||||
const copyHandler = () => {
|
||||
let copyText = "";
|
||||
blocks.forEach((block) => {
|
||||
@ -46,11 +51,16 @@ export default function Editor({
|
||||
navigator.clipboard.writeText(copyText);
|
||||
}
|
||||
|
||||
useDebounce(() => {
|
||||
setTitle(note.id, title);
|
||||
}, [title]);
|
||||
|
||||
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"
|
||||
defaultValue={note.title}
|
||||
onChange={(e) => setTitleState(e.target.value)}
|
||||
value={title}
|
||||
/>
|
||||
{blocks.map((block) => <Block key={block.id} block={block} /> )}
|
||||
<div className="flex gap-2">
|
||||
|
@ -1,10 +1,15 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useEffect } from "react";
|
||||
import { DependencyList, useEffect, useState } from "react";
|
||||
|
||||
export function useDebounce(callback: () => void, deps: DependencyList) {
|
||||
const [isFirstTime, setIsFirstTime] = useState(true);
|
||||
|
||||
// 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);
|
||||
if (isFirstTime) {
|
||||
setIsFirstTime(false);
|
||||
} else {
|
||||
const timeout = setTimeout(callback, 1000);
|
||||
return () => clearTimeout(timeout);
|
||||
}
|
||||
}, deps);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user