-
- e-Court Documents Versioning
- {phase !== "signed-out" && phase !== "checking" && username ? (
- /* จอแคบ: username ย้ายไป title/aria-label — ไม่กินพื้นที่แถบหัวจนตัวชื่อแอป wrap 3-4 บรรทัด */
-
- ) : null}
-
-
- {/* FR-17 — banner auto-save error ยกไว้เหนือ toggle (เดิมซ่อนอยู่ใน SaveControls ของแท็บ
- versioning): auto-save รันทุกแท็บ การเขียนค่าทดสอบของแท็บ template ก็ทำให้ dirty ได้
- จึงต้องเห็น error แม้อยู่อีกแท็บ */}
- {(phase === "untracked" || phase === "tracking") && autoSaveError ? (
-
{autoSaveError}
- ) : null}
-
- {/* toggle แท็บ — แสดงเฉพาะ phase ที่เข้าถึงเอกสารแล้ว (checking/signed-out ยังไม่มีอะไรให้จัดการ)
- ปิดทั้งสองปุ่มระหว่าง flow ที่เขียนเอกสาร: saving/starting ของ versioning (กัน progress หาย
- กลาง flow — handler อยู่ที่ component นี้ flow ยังรันจนจบ แค่หน้าตา), saveBusy ของบันทึก
- local/ปิดเอกสาร และ templateBusy ที่ panel รายงานผ่าน onBusyChange — กันเครื่องมือ template
- แข่งแก้เอกสารกลาง stamp/capture ของ versionFlow หรือกลับกัน (panel unmount แล้ว promise
- ของ service ก็ยังเขียนเอกสารต่อ ต้องปิดทางสลับตั้งแต่ต้น) */}
- {(phase === "untracked" || phase === "tracking") && (
-
-
-
-
- )}
-
- {phase === "checking" ? (
-
-
- {bootError ? (
- void detect()}
- >
- ลองใหม่
-
- }
- >
- {bootError}
-
- ) : null}
-
- ) : null}
-
- {phase === "signed-out" ? (
-
-
เข้าสู่ระบบเพื่อเริ่มใช้งาน versioning
-
- ใช้บัญชีของ realm word-versioning — หน้าต่าง login จะเปิดแยกต่างหาก
-
-
- {loginError ?
{loginError} : null}
-
- ) : null}
-
- {phase === "untracked" && activeTab === "versioning" ? (
-
-
เอกสารนี้ยังไม่ได้ติดตาม version
-
- กดปุ่มด้านล่างเพื่อเริ่ม track — ระบบจะ stamp metadata ลงไฟล์และอัปโหลดเป็น version 1
- (ไฟล์ที่สร้างจากเว็บ portal จะถูกตรวจพบและข้ามขั้นตอนนี้อัตโนมัติ)
-
- {documentTemplateId ? (
-
- ไฟล์นี้เป็นไฟล์ร่างจาก template — กดเริ่มติดตามแล้วระบบจะผูกเอกสารกับ template ต้นทาง
- และ sync ค่า fields ให้อัตโนมัติ
-
- ) : null}
-
-
void handleSaveOnly()}
- onSaveAndClose={() => void handleSaveAndClose()}
- />
- {starting && progressMessage ? : null}
- {flowError ? {flowError} : null}
-
- ) : null}
-
- {phase === "tracking" && activeTab === "versioning" ? (
- /* ห้ามใส่ items-start — ลูกทุกตัวจะหดตามเนื้อหา (MessageBar/history list ไม่เต็มความกว้าง pane) */
-
- {/* กลุ่มข้อความสถานะ */}
- {hasUncommitted ? (
-
- มีการแก้ไขที่ยังไม่ถูกบันทึกเป็นเวอร์ชันใหม่ — กด Save & Version เพื่อบันทึกเป็น version ใหม่
-
- ) : null}
-
- {flowWarning ?
{flowWarning} : null}
- {flowSuccess ?
{flowSuccess} : null}
- {flowError ?
{flowError} : null}
-
- {/* กลุ่ม action บันทึก — ปุ่มหลักเต็มความกว้างแถบ (action เด่นที่สุดของทั้งแอป) + progress + local save
- icon ใช้ commit ไม่ใช่ floppy — แยกจากปุ่ม "บันทึก" (local save) ที่ความหมายต่างกัน */}
-
-
- {saving && progressMessage ? : null}
- void handleSaveOnly()}
- onSaveAndClose={() => void handleSaveAndClose()}
- />
-
-
- {/* ink-soft (ไม่ใช่ ink-faint 2.6:1) — tracking id คือ identifier ที่ผู้ใช้อาจต้องอ่าน/คัดลอกตอนแจ้งปัญหา */}
-
tracking id: {documentId?.slice(0, 8)}…
-
-
void handleDownload(version, "pdf")}
- onDownload={(version) => void handleDownload(version)}
- onRetry={() => documentId && void refreshHistory(documentId)}
- />
-
- ) : null}
-
- {/* แท็บเครื่องมือ Template — state ทั้งหมดอยู่ใน panel เอง (snapshot ชั่วคราวของเอกสาร
- สลับแท็บแล้ว unmount = ทิ้งค่าทิ้งโดยตั้งใจ) */}
- {(phase === "untracked" || phase === "tracking") && activeTab === "template" ? (
-
- ) : null}
-
- {/* dialog ทั้งสองเป็นของ flow versioning — render เฉพาะแท็บ versioning (ตอน dialog เปิด
- overlay fixed inset-0 + Tab trap อยู่แล้ว ปุ่ม toggle แตะไม่ได้ จึงไม่มี path ที่ dialog
- เปิดค้างขณะสลับแท็บ) */}
- {(phase === "untracked" || phase === "tracking") && activeTab === "versioning" ? (
- <>
- {/* กดยืนยันแล้วปิด dialog ทันที — progress/ผลลัพธ์แสดงที่ pane (dialog ค้าง = บังผลลัพธ์
- + เสี่ยงกดยืนยันซ้ำสร้าง version ซ้ำ; busy ใน dialog เหลือเป็น defense ชั่วขณะก่อน re-render) */}
-
{
- setConfirmOpen(false);
- void handleSaveAndVersion(message);
- }}
- {...(closeSupported
- ? {
- onConfirmClose: (message: string) => {
- setConfirmOpen(false);
- void handleSaveAndVersion(message, true);
- },
- }
- : {})}
- onDismiss={() => setConfirmOpen(false)}
- />
-
- {/* FR-13 — Start Versioning ใช้ dialog เดียวกัน: ยืนยัน + พิมพ์ commit message ของ v1 ก่อนเริ่ม track */}
- {
- setStartConfirmOpen(false);
- void handleStartVersioning(message);
- }}
- onDismiss={() => setStartConfirmOpen(false)}
- />
- >
- ) : null}
-
- );
-};
-
-export default TaskpaneApp;
diff --git a/components/wordaddin/TemplateToolsPanel.tsx b/components/wordaddin/TemplateToolsPanel.tsx
deleted file mode 100644
index 3267edf..0000000
--- a/components/wordaddin/TemplateToolsPanel.tsx
+++ /dev/null
@@ -1,411 +0,0 @@
-"use client";
-
-import { useEffect, useMemo, useState } from "react";
-import { CornerDownLeft, Crosshair, FilePlus, LoaderCircle, PenLine, ScanSearch, WrapText } from "lucide-react";
-
-import {
- applyTestValues,
- insertBreakAtSelection,
- insertParagraphAtSelection,
- listContentControls,
- selectContentControl,
- supportsAllContentControlTypes,
- type ScannedField,
-} from "@/wordaddin/services/templateService";
-import { getErrorMessage } from "@/wordaddin/services/errors";
-
-import { MessageBar } from "./MessageBar";
-
-/**
- * แท็บ "เครื่องมือ Template" (แท็บที่สองของ taskpane) — เครื่องมือช่วยทำ template
- * สำหรับคนออกแบบเอกสาร ใช้ได้ทั้ง phase untracked และ tracking เพราะไม่แตะ backend/tracking:
- * 1. สแกน Content Controls ทั้งเอกสาร + เตือน tag ว่าง/ซ้ำ + กระโดดไปเลือกช่อง
- * 2. กรอกค่าทดสอบทุกช่องแล้วเขียนกลับเข้าเอกสารจริง (ดูผลจัดหน้า/ตัดบรรทัดทันที
- * โดยไม่ต้อง render ผ่าน /api/template/render)
- * 3. แทรกย่อหน้า/ตัวแบ่งบรรทัด/ตัวแบ่งหน้าที่ cursor ตอนจัดโครงสร้าง
- *
- * state ทั้งหมดถือภายใน — เป็น snapshot ชั่วคราวของเอกสาร: สลับแท็บแล้ว unmount = ทิ้ง
- * ค่าทิ้งโดยตั้งใจ (เก็บไว้ก็ stale เสียเองเมื่อผู้ใช้แก้เอกสารระหว่างนั้น)
- */
-
-const BTN_PRIMARY =
- "focus-ring inline-flex items-center gap-1.5 rounded-md bg-primary px-4 py-2.5 text-sm font-medium text-white transition hover:-translate-y-px hover:bg-primary-hover hover:shadow-btn-glow disabled:pointer-events-none disabled:opacity-50";
-const BTN_SECONDARY =
- "focus-ring inline-flex items-center gap-1.5 rounded-md border border-line bg-white px-3 py-1.5 text-sm text-ink transition hover:border-primary hover:text-primary disabled:pointer-events-none disabled:opacity-50";
-/** px-2 py-1.5 + text-xs ≈ สูง 30px — พ้นเกณฑ์ touch target 24px (WCAG 2.5.8) เหมือน VersionHistoryPanel */
-const BTN_ACTION =
- "focus-ring inline-flex items-center gap-1 rounded-md px-2 py-1.5 text-xs text-ink-soft transition hover:bg-primary/[0.06] hover:text-primary disabled:pointer-events-none disabled:opacity-50";
-
-/** ปุ่มแทรกองค์ประกอบ (ย่อหน้า/ตัวแบ่ง) — icon บน label ล่าง 3 ปุ่มต่อแถว */
-const BTN_INSERT =
- "focus-ring flex flex-col items-center gap-1 rounded-md border border-line bg-white px-1 py-2 text-xs text-ink transition hover:border-primary hover:text-primary disabled:pointer-events-none disabled:opacity-50";
-
-function TemplateToolsPanel({ onBusyChange }: { onBusyChange?: (busy: boolean) => void }) {
- /** null = ยังไม่เคยสแกน (empty state ต่างจาก [] = สแกนแล้วไม่มีช่อง) */
- const [fields, setFields] = useState