genesis+worker: design system Genesis ทั้งชุด + patch pdf.worker แก้ fake-space ไทย + ปิด review design/responsive/quality รอบ 2026-09-24 — (1) Genesis: ฟอนต์ General Sans self-host + DM Sans + Sarabun, AppNav 56px backdrop-blur แทน SessionBar, DotGrid หน้า login, palette/รัศมี/เงา/focus ตาม docs/DESIGN.md ครบทุกหน้า (2) postinstall scripts/patch-pdf-worker.mjs ถอด if (scaledDim) รอบ prevTransform ให้อัปเดตทุก glyph — กัน addFakeSpaces แทรก space กลางคำไทยใน PDF ที่ justify ด้วย letter-spacing + test กัน regression (tests/scripts/ + fixture thai_letterspacing.pdf, invariant #6) (3) ฟอร์มอัปโหลด + ช่องกลุ่ม typeId ทางเลือก — normDocumentGroup ที่ utils/external-file.ts เป็น single source ร่วมกับ N8 (4) token fixes: focus ring ปุ่ม pin + แถว bookmark ตามหน้า, ปุ่ม action ใน popup/composer/dialog เป็น rounded-md ทั้งคู่, selection preview เป็น tint ของ primary แทน blue-500 ดิบ, default สี shape/highlight รวมที่ utils/annotation-display, loading animate-pulse + จดข้อยกเว้น (เงา pin, font weights ของ viewer) ลง DESIGN.md (5) responsive: Export PDF max-lg:order-first ให้เห็นบน iPad, แถวบน header แถวเดียวเลื่อนได้บนจอแคบ, re-fit ความกว้างตอน toggle sidebar เฉพาะเมื่อยังไม่ซูมเอง, pin popover flip ขึ้นบนเมื่อใกล้ท้ายหน้า, toast hint ตอนสลับ tool กลางเอกสาร, ป้าย "ชนิด · ผู้ทำ" ของรายการผู้อื่นสำหรับจอสัมผัส (6) คุณภาพ: @layer ครอบ @media กันกฎ touch รั่ยไป desktop (Tailwind v3 ยก @layer ออกจาก media ทิ้ง wrapper — ยืนยันด้วย build จริง + วัดบนจอ), กฎ M5 ครอบ contenteditable กัน Safari zoom ตอนแก้ไข TEXTBOX บน iPad, COMMENT ใช้ box มาตราฐานเดียวตาม pin px จริง (render/scroll target/move-clamp/bookmark), ตัดหัวการ์ดซ้ำกับ h2 หน้ารายการ — พร้อมไฟล์ untracked ที่ postinstall/โค้ดอ้างถึงครบชุด (app/fonts/, AppNav, DotGrid, tests/) กัน fresh clone fail ที่ npm install (คำขอผู้ใช้ 2026-09-24)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-09-24 11:46:02 +07:00
parent e254b935ce
commit c5c6b65bd2
42 changed files with 1429 additions and 745 deletions

View file

@ -6,14 +6,15 @@
// ลิงก์จริงจาก e-Court (รับทั้ง path ในระบบเช่น /samples/… และ URL ของโฮสต์ที่อนุญาต
// — ไม่มี scheme นำหน้าระบบเติม https:// ให้)
// แถบลิงก์เต็มข้างล่างแสดง URL จริงที่ปุ่มจะพาไป (absolute — copy ไปเปิด/ส่งต่อได้) ตามที่พิมพ์สด ๆ
// Genesis: การ์ด surface 12px radius ขอบ line ใน section "เปิดเอกสารจากลิงก์ e-Court"
// (แยกจากส่วนเอกสาร) / ปุ่มเป็น secondary ขอบฟ้า / input ผ่าน .genesis-input
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { Link2 } from "lucide-react";
import { withBasePath } from "@/utils/base-path";
const inputClass =
"rounded-md border border-slate-300 bg-white px-3 py-2 text-sm text-slate-700 placeholder:text-slate-400 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20";
"genesis-input mt-1 w-full text-base transition aria-invalid:border-error";
export default function EcourtLinkForm() {
const router = useRouter();
@ -50,20 +51,12 @@ export default function EcourtLinkForm() {
};
return (
<form
onSubmit={onSubmit}
className="mt-8 rounded-xl border border-dashed border-slate-300 bg-white/60 p-4"
>
<div className="flex items-center gap-2">
<Link2 className="h-4 w-4 shrink-0 text-primary" />
<p className="text-sm font-medium text-slate-700">เปิดเอกสารจากลิงก์ e-Court</p>
</div>
<div className="mt-3 grid gap-x-2 gap-y-3 sm:grid-cols-2">
<form onSubmit={onSubmit} className="flex flex-col rounded-xl border border-line bg-white p-5">
{/* ไม่มีหัวการ์ดซ้ำ — h2 "เปิดเอกสารจากลิงก์ e-Court" ของ section ในหน้ารายการ
เป็นหัวเดียวพอแล้ว (responsive audit 2026-09-24: เดิมซ้ำสองชั้นติดกัน) */}
<div className="grid gap-x-4 gap-y-3 sm:grid-cols-2">
<div className="sm:col-span-2">
<label
htmlFor="ecourt-file-url"
className="block text-xs font-medium text-slate-600"
>
<label htmlFor="ecourt-file-url" className="block text-sm font-medium text-ink">
ลิงก์ไฟล์
</label>
<input
@ -74,14 +67,11 @@ export default function EcourtLinkForm() {
value={fileUrl}
onChange={(e) => setFileUrl(e.target.value)}
placeholder="เช่น /samples/ชื่อไฟล์.pdf หรือ https://…"
className={`${inputClass} mt-1 w-full`}
className={inputClass}
/>
</div>
<div>
<label
htmlFor="ecourt-file-id"
className="block text-xs font-medium text-slate-600"
>
<label htmlFor="ecourt-file-id" className="block text-sm font-medium text-ink">
รหัสเอกสาร fileId
</label>
<input
@ -90,14 +80,11 @@ export default function EcourtLinkForm() {
name="fileId"
value={fileId}
onChange={(e) => setFileId(e.target.value)}
className={`${inputClass} mt-1 w-full`}
className={inputClass}
/>
</div>
<div>
<label
htmlFor="ecourt-type-id"
className="block text-xs font-medium text-slate-600"
>
<label htmlFor="ecourt-type-id" className="block text-sm font-medium text-ink">
กลุ่ม typeId
</label>
<input
@ -107,25 +94,25 @@ export default function EcourtLinkForm() {
value={typeId}
onChange={(e) => setTypeId(e.target.value)}
placeholder="เช่น 1"
className={`${inputClass} mt-1 w-full`}
className={inputClass}
/>
</div>
</div>
<button
type="submit"
className="mt-3 w-full rounded-md bg-primary px-4 py-2.5 text-sm font-medium text-white transition hover:opacity-90"
className="focus-ring mt-4 w-full rounded-md border border-primary/30 px-4 py-2 text-sm font-medium text-primary transition hover:-translate-y-px hover:border-primary hover:bg-primary/5"
>
เปิดเอกสาร
</button>
<p className="mt-2 text-xs text-slate-500">
<p className="mt-3 text-xs leading-relaxed text-ink-soft">
กดแล้วระบบลงทะเบียนเอกสาร (ถ้ายังไม่มี) แล้วพาเข้าหน้าอ่าน/มาร์กเอกสารทันที —
ไฟล์รีโมตรับเฉพาะ https ของโฮสต์ที่อนุญาต
</p>
<p className="mt-2 break-all rounded-md bg-slate-50 px-3 py-2 text-xs text-slate-500">
<span className="font-medium text-slate-600">ลิงก์เต็ม: </span>
<p className="mt-3 break-all rounded-lg bg-ink/[0.04] px-3 py-2.5 text-xs text-ink-soft">
<span className="font-medium text-ink">ลิงก์เต็ม: </span>
{fullLink || "…"}
</p>
{error && <p className="mt-1 text-xs text-red-600">{error}</p>}
{error && <p className="mt-2 text-xs text-error-ink">{error}</p>}
</form>
);
}