feat: note line management

This commit is contained in:
Kirill Siukhin 2025-07-15 15:47:52 +05:00
parent 32b33ae4c4
commit 753fb225e1
2 changed files with 58 additions and 13 deletions

View File

@ -1,23 +1,27 @@
"use server";
import { revalidatePath } from "next/cache";
import { eq } from "drizzle-orm";
import { eq, asc } from "drizzle-orm";
import { db } from "@/lib/db";
import { blocksTable, IBlock } from "@/lib/db/schema";
export async function createBlock(formData: FormData) {
const noteId = formData.get("noteId") as string;
const blocks = await getBlocks(noteId);
const lastBlock = blocks.pop();
const order = lastBlock === undefined ? 1 : lastBlock.order + 1;
await db
.insert(blocksTable)
.values({ noteId });
revalidatePath("/notes/[id]");
.values({ noteId, order });
revalidatePath("/notes/[id]", "page");
}
export async function getBlocks(noteId: string): Promise<IBlock[]> {
return db
.select()
.from(blocksTable)
.where(eq(blocksTable.noteId, noteId));
.where(eq(blocksTable.noteId, noteId))
.orderBy(asc(blocksTable.order));
}
export async function deleteBlock(formData: FormData) {
@ -25,7 +29,7 @@ export async function deleteBlock(formData: FormData) {
await db
.delete(blocksTable)
.where(eq(blocksTable.id, blockId));
revalidatePath("/notes/[id]");
revalidatePath("/notes/[id]", "page");
}
export async function changeLock(formData: FormData) {
@ -35,5 +39,39 @@ export async function changeLock(formData: FormData) {
.update(blocksTable)
.set({ isLocked })
.where(eq(blocksTable.id, blockId));
revalidatePath("/notes/[id]");
revalidatePath("/notes/[id]", "page");
}
export async function addLine(formData: FormData) {
const blockId = formData.get("blockId") as string;
const blocks = await db
.select()
.from(blocksTable)
.where(eq(blocksTable.id, blockId));
if (blocks.length === 0) {
return;
}
const block = blocks[0];
await db
.update(blocksTable)
.set({ lines: [...block.lines, ""] })
.where(eq(blocksTable.id, blockId));
revalidatePath("/notes/[id]", "page");
}
export async function deleteLine(formData: FormData) {
const blockId = formData.get("blockId") as string;
const blocks = await db
.select()
.from(blocksTable)
.where(eq(blocksTable.id, blockId));
if (blocks.length === 0) {
return;
}
const block = blocks[0];
await db
.update(blocksTable)
.set({ lines: block.lines.slice(0, -1) })
.where(eq(blocksTable.id, blockId));
revalidatePath("/notes/[id]", "page");
}

View File

@ -1,5 +1,5 @@
import { ArrowDown, ArrowUp, LockOpen, Lock, Minus, Plus, X } from "lucide-react";
import { changeLock, deleteBlock } from "@/app/actions/blocks";
import { addLine, changeLock, deleteBlock, deleteLine } from "@/app/actions/blocks";
import { IBlock } from "@/lib/db/schema";
import IconOnlyButton from "../ui/IconOnlyButton";
import LineInput from "./LineInput";
@ -20,26 +20,33 @@ export default function Block({ block }: { block: IBlock }) {
))}
<div className="flex items-center mx-2 mt-2">
<div className="flex gap-1 mr-4">
<IconOnlyButton icon={<Plus size={18} />} disabled={block.isLocked} />
<IconOnlyButton icon={<Minus size={18} />} disabled={block.isLocked} />
<form action={addLine}>
<input type="hidden" name="blockId" value={block.id} />
<IconOnlyButton type="submit" icon={<Plus size={18} />} disabled={block.isLocked} />
</form>
<form action={deleteLine}>
<input type="hidden" name="blockId" value={block.id} />
<IconOnlyButton type="submit" icon={<Minus size={18} />} disabled={block.isLocked} />
</form>
</div>
<div className="flex gap-1">
<IconOnlyButton icon={<ArrowUp size={18} />} />
<IconOnlyButton icon={<ArrowDown size={18} />} />
</div>
<div className="flex gap-2 ml-auto">
<form action={deleteBlock}>
<input type="hidden" name="blockId" value={block.id} />
<IconOnlyButton icon={<X size={18} />} type="submit" />
</form>
<form action={changeLock}>
<input type="hidden" name="blockId" value={block.id} />
{!block.isLocked && <input type="hidden" name="isLocked" />}
<IconOnlyButton
type="submit"
alwaysOn={block.isLocked}
icon={block.isLocked ? <Lock size={18} /> : <LockOpen size={18} />}
/>
</form>
<form action={deleteBlock}>
<input type="hidden" name="blockId" value={block.id} />
<IconOnlyButton type="submit" icon={<X size={18} />} />
</form>
</div>
</div>
</div>