Add application codebase: PDF annotation for e-Court
Next.js 14 + Drizzle/PostgreSQL + SSE realtime sync — highlight,
freehand, comment, bookmark + ฟีเจอร์ต่อยอด F1–F19 (edit/move, undo/redo,
shapes, redaction, export PDF/CSV, reply, resolve, search, summary,
textbox, stamp, version history)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-10 14:29:40 +07:00
|
|
|
import { asc, eq, inArray } from "drizzle-orm";
|
|
|
|
|
import { notFound } from "next/navigation";
|
|
|
|
|
|
|
|
|
|
import { db } from "@/db";
|
|
|
|
|
import {
|
|
|
|
|
annotationReplies,
|
|
|
|
|
annotations,
|
|
|
|
|
bookmarks,
|
|
|
|
|
files,
|
|
|
|
|
toAnnotationDTO,
|
|
|
|
|
toBookmarkDTO,
|
|
|
|
|
toReplyDTO,
|
|
|
|
|
} from "@/db/schema";
|
|
|
|
|
import PDFViewer from "@/components/pdf/PDFViewer";
|
2026-09-15 15:10:27 +07:00
|
|
|
import DebugConsole from "@/components/DebugConsole"; // TEMP-DEBUG (ลบพร้อมไฟล์)
|
Add application codebase: PDF annotation for e-Court
Next.js 14 + Drizzle/PostgreSQL + SSE realtime sync — highlight,
freehand, comment, bookmark + ฟีเจอร์ต่อยอด F1–F19 (edit/move, undo/redo,
shapes, redaction, export PDF/CSV, reply, resolve, search, summary,
textbox, stamp, version history)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-10 14:29:40 +07:00
|
|
|
|
|
|
|
|
const UUID_RE =
|
|
|
|
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
|
|
|
|
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
|
|
|
|
|
|
export default async function AnnotatePage({
|
|
|
|
|
params,
|
|
|
|
|
}: {
|
|
|
|
|
params: { id: string };
|
|
|
|
|
}) {
|
|
|
|
|
const { id } = params;
|
|
|
|
|
if (!UUID_RE.test(id)) notFound();
|
|
|
|
|
|
|
|
|
|
const [file] = await db.select().from(files).where(eq(files.id, id));
|
|
|
|
|
if (!file) notFound();
|
|
|
|
|
|
|
|
|
|
const [annotationRows, bookmarkRows] = await Promise.all([
|
|
|
|
|
db
|
|
|
|
|
.select()
|
|
|
|
|
.from(annotations)
|
|
|
|
|
.where(eq(annotations.fileId, id))
|
|
|
|
|
.orderBy(asc(annotations.createdAt)),
|
|
|
|
|
db
|
|
|
|
|
.select()
|
|
|
|
|
.from(bookmarks)
|
|
|
|
|
.where(eq(bookmarks.fileId, id))
|
|
|
|
|
.orderBy(asc(bookmarks.createdAt)),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
// replies ของทุก comment ในไฟล์นี้ (F9) — แม่ถูก CASCADE ไปแล้ว row ก็หายตาม
|
|
|
|
|
const annotationIds = annotationRows.map((r) => r.id);
|
|
|
|
|
const replyRows = annotationIds.length
|
|
|
|
|
? await db
|
|
|
|
|
.select()
|
|
|
|
|
.from(annotationReplies)
|
|
|
|
|
.where(inArray(annotationReplies.annotationId, annotationIds))
|
|
|
|
|
.orderBy(asc(annotationReplies.createdAt))
|
|
|
|
|
: [];
|
|
|
|
|
|
|
|
|
|
return (
|
2026-09-15 15:10:27 +07:00
|
|
|
<>
|
|
|
|
|
{/* TEMP-DEBUG: อ่าน log บนจอ iPad ผ่าน Eruda เมื่อเปิดหน้าพร้อม ?debug */}
|
|
|
|
|
<DebugConsole />
|
|
|
|
|
<PDFViewer
|
Add application codebase: PDF annotation for e-Court
Next.js 14 + Drizzle/PostgreSQL + SSE realtime sync — highlight,
freehand, comment, bookmark + ฟีเจอร์ต่อยอด F1–F19 (edit/move, undo/redo,
shapes, redaction, export PDF/CSV, reply, resolve, search, summary,
textbox, stamp, version history)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-10 14:29:40 +07:00
|
|
|
file={{ id: file.id, title: file.title, pdfUrl: file.pdfUrl }}
|
|
|
|
|
initialAnnotations={annotationRows.map(toAnnotationDTO)}
|
|
|
|
|
initialBookmarks={bookmarkRows.map(toBookmarkDTO)}
|
|
|
|
|
initialReplies={replyRows.map(toReplyDTO)}
|
2026-09-15 15:10:27 +07:00
|
|
|
/>
|
|
|
|
|
</>
|
Add application codebase: PDF annotation for e-Court
Next.js 14 + Drizzle/PostgreSQL + SSE realtime sync — highlight,
freehand, comment, bookmark + ฟีเจอร์ต่อยอด F1–F19 (edit/move, undo/redo,
shapes, redaction, export PDF/CSV, reply, resolve, search, summary,
textbox, stamp, version history)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-10 14:29:40 +07:00
|
|
|
);
|
|
|
|
|
}
|