-
- e-Court Documents Versioning
- {phase !== "signed-out" && phase !== "checking" && username ? (
- /* จอแคบ: username ย้ายไป title/aria-label — ไม่กินพื้นที่แถบหัวจนตัวชื่อแอป wrap 3-4 บรรทัด */
-
- ) : null}
-
-
- {phase === "checking" ? (
-
-
- {bootError ? (
- void detect()}
- >
- ลองใหม่
-
- }
- >
- {bootError}
-
- ) : null}
-
- ) : null}
-
- {phase === "signed-out" ? (
-
-
เข้าสู่ระบบเพื่อเริ่มใช้งาน versioning
-
- ใช้บัญชีของ realm word-versioning — หน้าต่าง login จะเปิดแยกต่างหาก
-
-
- {loginError ?
{loginError} : null}
-
- ) : null}
-
- {phase === "untracked" ? (
-
-
เอกสารนี้ยังไม่ได้ติดตาม 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" ? (
- /* ห้ามใส่ 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}
-
- {/* กดยืนยันแล้วปิด 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)}
- />
-
- );
-};
-
-export default TaskpaneApp;
diff --git a/components/wordaddin/VersionHistoryPanel.tsx b/components/wordaddin/VersionHistoryPanel.tsx
deleted file mode 100644
index 7755035..0000000
--- a/components/wordaddin/VersionHistoryPanel.tsx
+++ /dev/null
@@ -1,149 +0,0 @@
-import { Download, FileText, LoaderCircle } from "lucide-react";
-
-import { VersionRecord } from "@/wordaddin/models/versionRecord";
-
-import { MessageBar } from "./MessageBar";
-import { Spinner } from "./Spinner";
-
-/**
- * FR-4 — แสดง version history (เลข version / เวลา / ผู้สร้าง) + ปุ่มดาวน์โหลด version นั้น
- * ชั้นภาพ: timeline แนวตั้ง — จุดโหนดเท่าทึบคือเวอร์ชันล่าสุด จุดกลวงคือเก่ากว่า
- * (เลข version เป็น static → ใช้ ink ตามกฎ "blue เฉพาะ interactive" ของ DESIGN.md)
- */
-
-function formatTimestamp(iso: string): string {
- const date = new Date(iso);
- return Number.isNaN(date.getTime())
- ? iso
- : date.toLocaleString(undefined, { dateStyle: "medium", timeStyle: "short" });
-}
-
-/** px-2 py-1.5 + text-xs ≈ สูง 30px — พ้นเกณฑ์ touch target 24px ของ WCAG 2.5.8 โดยยัง dense พอสำหรับ list */
-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";
-
-export function VersionHistoryPanel({
- versions,
- loading,
- error,
- downloadingVersionId,
- downloadingPdfVersionId,
- onDownloadPdf,
- onDownload,
- onRetry,
-}: {
- versions: VersionRecord[];
- loading: boolean;
- error: string | null;
- /** versionId ของ version ที่กำลังดาวน์โหลดอยู่ (แสดง spinner ที่ปุ่ม) */
- downloadingVersionId: string | null;
- downloadingPdfVersionId: string | null;
- onDownloadPdf: (version: VersionRecord) => void;
- onDownload: (version: VersionRecord) => void;
- onRetry: () => void;
-}) {
- const anyDownloading = downloadingVersionId !== null || downloadingPdfVersionId !== null;
-
- return (
-
-
-
Version history
- {versions.length > 0 ? {versions.length} เวอร์ชัน : null}
-
-
- {loading ?
: null}
-
- {error ? (
-
- ลองใหม่
-
- }
- >
- {error}
-
- ) : null}
-
- {!loading && !error && versions.length === 0 ? (
-
ยังไม่มี version ในระบบ
- ) : null}
-
- {versions.length > 0 ? (
-
- {/* ราง timeline — วาดครั้งเดียวระดับรายการ (เวอร์ชันเดียวไม่ต้องมีเส้น) */}
- {versions.length > 1 ? (
-
- ) : null}
- {versions.map((version, index) => {
- const isLatest = index === 0;
- return (
- -
-
-
- v{version.versionNumber}
- {isLatest ? (
- ล่าสุด
- ) : null}
-
-
- {version.hasPdf ? (
-
- ) : null}
-
-
- {version.message ? (
-
- {version.message}
-
- ) : null}
-
- {formatTimestamp(version.createdAt)} · โดย {version.createdByUserId}
-
-
- );
- })}
-
- ) : null}
-
- );
-}
-
-export default VersionHistoryPanel;
diff --git a/components/wordaddin/WordAddinGate.tsx b/components/wordaddin/WordAddinGate.tsx
deleted file mode 100644
index 5df16c3..0000000
--- a/components/wordaddin/WordAddinGate.tsx
+++ /dev/null
@@ -1,131 +0,0 @@
-"use client";
-
-import { useEffect, useState } from "react";
-
-import { withBasePath } from "@/utils/base-path";
-import { signInForDemo } from "@/wordaddin/services/authService";
-
-import { MessageBar } from "./MessageBar";
-import { Spinner } from "./Spinner";
-import TaskpaneApp from "./TaskpaneApp";
-
-/**
- * Gate ของ taskpane ใน App Router — ทำหน้าที่แทน Office.onReady ก่อน render ของ webpack
- * ต้นฉบับ: Office.js โหลดใน ของ taskpane.html แล้ว Office.onReady ก่อน createRoot
- * (บริบท Next: ฉีด