"use client"; // N4 — ฟอร์มอัปโหลดไฟล์เอกสารแบบง่ายบนหน้ารายการ (PDF/รูป รับพร้อมกัน) // เสร็จแล้วรายการโผล่เองจาก revalidatePath("/") ของ action // Genesis: หน้าตาเป็นการ์ด surface 12px radius ขอบ line (ใต้หัวข้อของ section // "เอกสาร" — ไฟล์ที่อัปโหลดเข้ารายการนั้น) + ปุ่ม primary เดียวของ section import { useState, useTransition } from "react"; import { Upload } from "lucide-react"; import { uploadFile } from "@/app/actions/files"; const ACCEPT = ".pdf,.jpg,.jpeg,.png,.tif,.tiff"; /** ขนาดสูงสุดตาม validator ของ uploadFile (app/actions/files.ts) — เช็คฝั่ง client * ก่อนอัปโหลด (M5, UX audit 2026-09-16): ไฟล์สแกนคดีที่เกินไม่ต้องรอส่งจนจบ * บนเน็ตช้าก่อนเจอ error ของ server */ const MAX_BYTES = 100 * 1024 * 1024; export default function UploadFileForm() { const [error, setError] = useState(null); const [pending, startTransition] = useTransition(); const onSubmit = (e: React.FormEvent) => { e.preventDefault(); const form = e.currentTarget; setError(null); const input = form.elements.namedItem("file") as HTMLInputElement | null; const file = input?.files?.[0]; if (file && file.size > MAX_BYTES) { setError("ไฟล์ใหญ่เกิน 100MB — เลือกไฟล์เล็กกว่า"); return; } startTransition(async () => { try { const result = await uploadFile(new FormData(form)); if (result.ok) { form.reset(); } else { setError(result.error); } } catch { // action fail ที่ระดับ transport (เช่น body ใหญ่เกิน bodySizeLimit ของ next.config) setError("อัปโหลดไม่สำเร็จ — ลองใหม่อีกครั้ง"); } }); }; return (

อัปโหลดไฟล์

{/* กลุ่ม typeId ทางเลือก (N9) — ช่องเดียวกับลิงก์ e-Court, ไม่กรอก = "ไม่มีกลุ่ม"; uncontrolled ส่งไปกับ FormData เหมือนช่องไฟล์ (normalize ที่ action) */}

รองรับ PDF, JPG, PNG, TIFF — ไม่เกิน 100MB ต่อไฟล์

{error &&

{error}

}
); }