690519:1631 224 to 226 AI #01
CI / CD Pipeline / build (push) Failing after 3m57s
CI / CD Pipeline / deploy (push) Has been skipped

This commit is contained in:
2026-05-19 16:31:50 +07:00
parent 3e25097470
commit ea5499123e
127 changed files with 12387 additions and 42 deletions
@@ -0,0 +1,34 @@
# Specification Quality Checklist: Document Chat UI Pattern
**Purpose**: ตรวจสอบความถูกต้องสมบูรณ์และคุณภาพของ Specification ก่อนดำเนินขั้นตอนการวางแผนทางเทคนิค
**Created**: 2026-05-19
**Feature**: [spec.md](../spec.md)
## Content Quality (คุณภาพของเนื้อหา)
- [x] ไม่มีรายละเอียดทางเทคนิคของการทำงานของระบบ (เช่น ภาษาเขียนโปรแกรม, เฟรมเวิร์ก, หรือ API ภายนอก)
- [x] มุ่งเน้นไปที่มูลค่าของผู้ใช้และความต้องการทางธุรกิจ
- [x] เขียนด้วยคำอธิบายสำหรับผู้มีส่วนได้ส่วนเสียที่ไม่ใช่สายเทคนิค (Non-technical stakeholders)
- [x] กรอกข้อมูลในทุกส่วนที่กำหนด (Mandatory sections) ครบถ้วน
## Requirement Completeness (ความครบถ้วนของข้อกำหนด)
- [x] ไม่มีเครื่องหมาย [NEEDS CLARIFICATION] หลงเหลืออยู่
- [x] ข้อกำหนดต่างๆ สามารถทำการทดสอบและไม่มีความคลุมเครือ
- [x] Success Criteria สามารถวัดผลได้เป็นตัวเลขและระยะเวลา
- [x] Success Criteria ไม่ขึ้นอยู่กับเทคโนโลยีใดๆ (ไม่มีการเอ่ยถึงรายละเอียดการติดตั้ง)
- [x] มีการกำหนด Acceptance Scenarios สำหรับทุก User Story
- [x] มีการระบุ Edge Cases ครบถ้วน
- [x] กำหนดขอบเขตของระบบ (Scope) อย่างชัดเจน
- [x] มีการระบุ Dependencies และ Assumptions ที่เกี่ยวข้อง
## Feature Readiness (ความพร้อมของฟีเจอร์)
- [x] ทุกข้อกำหนดการใช้งานหลักมีเกณฑ์การยอมรับ (Acceptance Criteria) ชัดเจน
- [x] User Scenarios ครอบคลุมการใช้งานหลักทุกประเภท
- [x] ฟีเจอร์บรรลุผลตามตัววัดที่กำหนดไว้ใน Success Criteria
- [x] ไม่มีข้อมูลรายละเอียดทางเทคนิครั่วไหลเข้ามาในข้อกำหนด
## Notes
- รายการตรวจสอบทั้งหมดผ่านการยืนยันเรียบร้อยแล้ว Spec มีความพร้อมสมบูรณ์สำหรับการวางแผนขั้นถัดไป
@@ -0,0 +1,98 @@
openapi: 3.0.3
info:
title: Document Chat Subsystem API
description: API endpoints for interacting with the document-isolated AI Assistant (ADR-026)
version: 1.0.0
paths:
/api/ai/chat:
post:
summary: Send a query to the AI Assistant within a specific document context
description: |
Processes a natural language query under a strict CASL-guarded document context.
The AI Gateway uses the provided `context` to fetch context-specific data via the AI Tool Layer (ADR-025)
before forwarding the enriched prompt to the local Ollama LLM.
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- query
- context
properties:
query:
type: string
example: "ช่วยสรุปรายการ Drawing ใน RFA นี้หน่อย"
context:
type: object
required:
- type
- publicId
properties:
type:
type: string
enum: [drawing, rfa, transmittal, correspondence]
example: "rfa"
publicId:
type: string
format: uuid
example: "019505a1-7c3e-7000-8000-abc123def456"
responses:
'200':
description: Successful response returning AI reply and optional action chips
content:
application/json:
schema:
type: object
required:
- messageId
- role
- content
- latencyMs
properties:
messageId:
type: string
format: uuid
example: "019505a4-569d-7000-8000-f1f2f3f4f5f6"
role:
type: string
enum: [assistant]
example: "assistant"
content:
type: string
description: Markdown-formatted AI response
example: "จากการตรวจสอบ RFA-0042 นี้ มี Drawing ที่เกี่ยวข้องทั้งหมด 3 รายการ..."
suggestedActions:
type: array
items:
type: object
required:
- label
- query
properties:
label:
type: string
example: "ดู Drawing ฉบับใหม่ล่าสุด"
query:
type: string
example: "ขอรายละเอียดเกี่ยวกับ Drawing ล่าสุด"
latencyMs:
type: integer
example: 2450
'400':
description: Invalid input parameters or malformed UUIDv7
'401':
description: Unauthorized access (Missing or invalid JWT token)
'403':
description: Forbidden (User fails CASL security guard for the specified project/document context)
'504':
description: AI Gateway Timeout (Ollama pipeline took more than 10 seconds to respond)
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
@@ -0,0 +1,86 @@
// File: specs/200-fullstacks/226-document-chat-ui-pattern/data-model.md
// Change Log:
// - 2026-05-19: Initial data model specifications for Document Chat UI Pattern
# Data Model & State Specifications: Document Chat UI Pattern
เนื่องจากข้อตกลงใน ADR-026 กำหนดให้ระบบ Document Chat ใน v1 นี้ ทำงานแบบ **Client-side Persistence (Session Storage เท่านั้น)** ดังนั้นจึงไม่มีการเปลี่ยนแปลงโครงสร้างตารางฐานข้อมูล MariaDB หรือ Qdrant เพิ่มเติม เอกสารฉบับนี้จึงเน้นกำหนดโครงสร้างอ็อบเจกต์ข้อมูลในฝั่ง Frontend และ API Request/Response DTOs เพื่อความเป็นระเบียบและสอดคล้องกับมาตรฐานความปลอดภัย
---
## 1. Frontend Data Structures (โครงสร้างข้อมูลฝั่งไคลเอนต์)
### 1.1 ChatMessage (โครงสร้างข้อความแชท)
ใช้เก็บประวัติการสนทนาในแต่ละ Session
| Field | Type | Description |
|---|---|---|
| `id` | `string` | รหัสเฉพาะของข้อความในรูปแบบ **UUIDv7 string** |
| `role` | `'user' \| 'assistant' \| 'system'` | บทบาทของผู้ส่งข้อความ |
| `content` | `string` | เนื้อหาของข้อความ (รองรับการเขียนแบบ Markdown พื้นฐาน) |
| `timestamp` | `Date` | วันเวลาที่ส่งหรือได้รับข้อความ |
| `suggestedActions` | `SuggestedAction[]` | รายการปุ่มสั่งการแนะนำที่ส่งมาพร้อมคำตอบของ AI (ถ้ามี) |
| `isStreaming` | `boolean` | สถานะบ่งบอกว่าคำตอบนี้กำลังอยู่ในกระบวนการโหลดข้อมูลแบบ Stream |
### 1.2 SuggestedAction (ปุ่มกระทำการแนะนำ)
ปุ่มที่ปรากฏใต้ข้อความของ AI เพื่อช่วยให้ผู้ใช้กดสั่งการระบบต่อได้ง่ายขึ้น
| Field | Type | Description |
|---|---|---|
| `label` | `string` | ข้อความที่จะแสดงบนปุ่ม Chip (เช่น "ดู Drawing ฉบับใหม่ล่าสุด") |
| `query` | `string` | ข้อความที่จะถูกส่งเข้าสู่กล่องสนทนาแทนการพิมพ์เมื่อผู้ใช้กดคลิกปุ่มนี้ |
---
## 2. API DTOs (Data Transfer Objects)
### 2.1 ChatRequestDto
ข้อมูลที่ระบบส่งไปยัง API Endpoint `/api/ai/chat`
```typescript
// ✅ สอดคล้องกับหลักการ UUIDv7 และหลีกเลี่ยง Integer PK (ADR-019)
export interface ChatRequestDto {
query: string; // ข้อความถามคำถามของผู้ใช้
context: {
type: 'drawing' | 'rfa' | 'transmittal' | 'correspondence'; // ประเภทเอกสารต้นทาง
publicId: string; // UUIDv7 publicId ของเอกสารนั้นๆ
};
}
```
### 2.2 ChatResponseDto
ข้อมูลที่ระบบตอบรับกลับมาจาก API (ในกรณีไม่เปิดใช้ Web Stream หรือเป็น Fallback)
```typescript
export interface ChatResponseDto {
messageId: string; // UUIDv7 string ของข้อความตอบกลับ
role: 'assistant';
content: string; // คำตอบของ AI (Markdown format)
suggestedActions?: SuggestedAction[]; // ปุ่มสั่งการแนะนำ
latencyMs: number; // ระยะเวลาการประมวลผลของ AI Subsystem
}
```
---
## 3. UI State Transitions (สถานะและการเปลี่ยนสถานะในระบบ UI)
ระบบใช้วงจรสถานะแชท (Chat Panel State Life-cycle) ดังแผนภาพนี้:
```mermaid
stateDiagram-v2
[*] --> Closed: เริ่มต้น (Default ปิดแผง)
Closed --> Opened: กดปุ่ม Toggle หรือ Ctrl/.
Opened --> Closed: กดปุ่ม ปิด หรือสลับหน้าเอกสารอื่น
state Opened {
[*] --> Idle: พร้อมใช้งาน
Idle --> Typing: ผู้ใช้พิมพ์ข้อความ
Typing --> Sending: กดส่งข้อความ (เรียก API)
Sending --> Receiving: เริ่มได้รับผลลัพธ์แบบ Stream
Receiving --> Idle: ประมวลผลเสร็จสิ้น
Sending --> ErrorState: เกิดความล่าช้า/ข้อผิดพลาดเครือข่าย
ErrorState --> Sending: ผู้ใช้กด Retry
ErrorState --> Idle: ยกเลิกข้อเสนอแนะ
}
```
@@ -0,0 +1,73 @@
// File: specs/200-fullstacks/226-document-chat-ui-pattern/plan.md
// Change Log:
// - 2026-05-19: Initial implementation plan for Document Chat UI Pattern
# Implementation Plan: Document Chat UI Pattern
**Branch**: `226-document-chat-ui-pattern` | **Date**: 2026-05-19 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/200-fullstacks/226-document-chat-ui-pattern/spec.md`
---
## Summary (สรุปแนวทางเชิงเทคนิค)
ฟีเจอร์นี้เป็นการพัฒนาส่วนต่อประสานกับผู้ใช้ (Frontend UI) ร่วมกับ Next.js 16 (App Router), TailwindCSS, Radix UI/shadcn, และ React Hook Form + Zod เพื่อสร้างแผงควบคุมระบบสนทนาของ AI Assistant ในหน้าแสดงผลเอกสารของระบบ LCBP3 DMS โดยจะประมวลผลข้อมูลผ่าน API `/api/ai/chat` โดยอัตโนมัติแนบบริบทของเอกสาร เช่น `documentType` และ UUIDv7 `publicId` (หลีกเลี่ยง Integer PK ตามกฎ Tier 1 ADR-019) และจัดเก็บการสนทนาทั้งหมดไว้ภายใน Session Storage (Client-side) ตามขอบเขตการทำงานของระยะแรก
---
## Technical Context (บริบททางเทคนิค)
- **Language/Version**: TypeScript / Node.js >= 24 / Next.js 16
- **Primary Dependencies**: Radix UI (Sheet / Dialog / ScrollArea / Button / Badge), TanStack React Query v5, TailwindCSS 3.4.3, Lucide React, Axios, Zod, Zustand
- **Storage**: Client-side Session Storage สำหรับจัดเก็บข้อความแชทในปัจจุบันต่อเอกสารย่อย
- **Testing**: Vitest + React Testing Library (สำหรับ Component Unit Tests)
- **Target Platform**: เว็บเบราว์เซอร์ที่รองรับ Responsive ทั้งเครื่องคอมพิวเตอร์สำนักงาน (1920x1080) และแท็บเล็ตหน้างาน (768x1024)
- **Project Type**: Next.js App Router Web Application (`frontend/`)
- **Performance Goals**: การเปิด/ปิด Chat Panel Animation ต้องใช้เวลาเพียง 200ms เท่านั้น (Slide transition), UI ต้องตอบสนองต่อผู้ใช้ทันทีเมื่อมีสัญญาณเตือนหรือเกิดข้อผิดพลาด
- **Constraints**: ต้องไม่มีการหลุดของ Integer Primary Key ไปยัง LLM หรือ API Payload เป็นอันขาด (Tier 1 Blocker), ต้องรองรับการกรองตามบริบทโครงการผ่าน CASL permissions
---
## Constitution Check (การตรวจสอบความถูกต้องร่วมกับรัฐธรรมนูญโครงการ)
_GATE: ผ่านการทดสอบทั้งหมด_
- [x] **UUID Strategy (ADR-019)**: ระบบใช้ UUIDv7 `publicId` เป็นตัวชี้วัดเอกสารในการแนบบริบท (Context Injection) เท่านั้น ไม่มีการใช้ integer id หรือ fallback `id ?? ''`
- [x] **Security (ADR-016)**: API Route `/api/ai/chat` จะถูกคลุมด้วย Authentication Guard และมีการ Enforce CASL สิทธิ์ของผู้ใช้ในการอ่านเอกสารนั้นๆ ผ่าน AI Gateway ก่อนจะเรียกใช้งาน
- [x] **AI Subsystem boundary (ADR-023A)**: AI Subsystem ทำงานแบบ Read-only Insight และ Action suggestion เท่านั้น ห้ามทำการเปลี่ยนสถานะเอกสาร (Transition) โดยตรงผ่านแชทโดยไม่มีการยืนยันจากผู้ใช้ (Human-in-the-loop)
- [x] **Error Handling (ADR-007)**: มีการจัดการเครือข่ายขัดข้องและ AI Timeout อย่างสง่างาม แสดงคำอธิบายที่ใช้งานง่ายโดยไม่เปิดเผยข้อมูลเซิร์ฟเวอร์ภายใน
---
## Project Structure (โครงสร้างไฟล์ที่เกี่ยวข้องในฟีเจอร์นี้)
### Documentation (เอกสารการออกแบบและพัฒนา)
```text
specs/200-fullstacks/226-document-chat-ui-pattern/
├── spec.md # Feature specification
├── plan.md # แผนการทางเทคนิคฉบับนี้
├── research.md # ผลวิจัยการจัดวางและการเก็บสถานะข้อมูล
├── data-model.md # รายละเอียดชนิดข้อมูลฝั่ง Frontend และ API Payload DTO
├── quickstart.md # คู่มือการเริ่มต้นพัฒนาและรัน Test
└── contracts/
└── chat-api.yaml # OpenAPI Specification ของ Chat Endpoint
```
### Source Code (โครงสร้างไฟล์โค้ดของระบบ)
```text
frontend/
├── app/
│ └── api/
│ └── ai/
│ └── chat/
│ └── route.ts # Next.js API Route สำหรับ Chat proxy ไปยัง Backend AI Gateway
├── components/
│ └── ai/
│ ├── ai-chat-panel.tsx # คอมโพเนนต์หลักที่ประกอบด้วย Sheet / Panel สำหรับแต่ละ Breakpoint
│ ├── ai-chat-toggle.tsx # ปุ่มสำหรับสลับเปิด/ปิด Chat Panel (และปุ่มลอยสำหรับอุปกรณ์พกพา)
│ ├── ai-chat-messages.tsx # รายการประวัติสนทนาและการเรนเดอร์ Message Bubbles ตาม Role
│ ├── ai-chat-input.tsx # ช่องพิมพ์คำสั่ง ปุ่มส่งคำถาม และปุ่มลัด
│ └── ai-suggested-actions.tsx # แถบ Badge Chip แนะนำการทำงานต่อเนื่อง
└── hooks/
└── use-ai-chat.ts # React hook สำหรับจัดการ API และเก็บสถานะลง Session Storage
```
@@ -0,0 +1,70 @@
// File: specs/200-fullstacks/226-document-chat-ui-pattern/quickstart.md
// Change Log:
// - 2026-05-19: Initial developer quickstart guide for Document Chat UI Pattern
# Developer Quickstart Guide: Document Chat UI Pattern
คู่มือแนะนำขั้นตอนการทำความเข้าใจ การทดสอบ และการตรวจสอบการทำงานของฟีเจอร์ AI Document Chat ในฝั่ง Frontend และการเชื่อมต่อกับ Backend AI Gateway (226)
---
## 1. การติดตั้งโค้ดและส่วนประกอบหลัก (Component Architecture)
โครงสร้างโฟลเดอร์ฝั่งไคลเอนต์จะอยู่ที่:
```text
frontend/components/ai/
├── ai-chat-panel.tsx # คอมโพเนนต์หลักที่ประกอบด้วย Sheet / Panel สำหรับแต่ละ Breakpoint
├── ai-chat-toggle.tsx # ปุ่มสำหรับสลับเปิด/ปิด Chat Panel (และปุ่มลอยสำหรับอุปกรณ์พกพา)
├── ai-chat-messages.tsx # รายการประวัติสนทนาและการเรนเดอร์ Message Bubbles ตาม Role
├── ai-chat-input.tsx # กล่องพิมพ์คำสั่ง ปุ่มส่งคำถาม และปุ่มลัด
├── ai-suggested-actions.tsx # แถบ Badge Chip แนะนำการทำงานต่อเนื่อง
└── hooks/
└── use-ai-chat.ts # คอนเท็กซ์และฮุกของ React / TanStack Query ในการจัดการ API และ State
```
---
## 2. การเปิดใช้งานและตั้งค่าพัฒนา (Development Setup)
### 2.1 รันระบบ Frontend ในโหมดพัฒนา
เปิด PowerShell (เนื่องจากทำงานบน Windows OS ตามกฎ) และรันคำสั่ง:
```powershell
cd frontend
pnpm dev
```
ระบบจะเริ่มต้นที่พอร์ต `http://localhost:3000`
### 2.2 โครงสร้าง API Mockup สำหรับการพัฒนาช่วงแรก
ในระหว่างการพัฒนาฝั่ง Frontend สามารถเปิดการใช้งาน Mock Data ใน `use-ai-chat.ts` หรือจำลองการทำงานโดยการทดสอบผ่าน `/api/ai/chat` Mock Route ได้
---
## 3. ขั้นตอนการทดสอบการใช้งานด้วยตนเอง (Manual Testing Steps)
### 3.1 การตรวจสอบบน Desktop (ขนาดหน้าจอ ≥ 1024px)
1. เข้าสู่หน้าเอกสาร เช่น `/rfas/019505a1-7c3e-7000-8000-abc123def456`
2. มองหาปุ่ม **AI Chat** ทางขวาบนของเอกสาร
3. คลิกปุ่มเพื่อเปิดใช้งาน Chat Panel (จะเห็นการ Slide-in เข้ามาจากทางขวาอย่างราบรื่นใช้เวลา 200ms)
4. พิมพ์ทดสอบสนทนาในช่องพิมพ์ หรือกดคีย์ลัด `Ctrl + .` เพื่อเปิด/ปิด Panel
### 3.2 การตรวจสอบความเข้ากันได้ของการแสดงผล (Responsive Test)
1. เปิด Developer Tools ในเว็บเบราว์เซอร์ แล้วเลือกขนาดหน้าจอเป็น Tablet (768px - 1023px)
2. ตรวจสอบว่าขนาดของ Panel กว้างขึ้นเป็นประมาณ 30% ของ viewport หรือไม่
3. เปลี่ยนขนาดหน้าจอเป็น Mobile (< 768px)
4. ยืนยันว่าปุ่มสลับกลายเป็นปุ่มลอย และเมื่อกดแล้วแชทเลื่อนขึ้นมาจากด้านล่าง (Bottom Sheet สูง 60% ของจอ)
---
## 4. การรันชุดทดสอบอัตโนมัติ (Automated Testing)
ฟีเจอร์นี้ครอบคลุมการตรวจสอบความถูกต้องด้วยชุดทดสอบผ่าน **Vitest** ในฝั่ง Frontend:
```powershell
# รันการทดสอบทั้งหมดของ AI module
cd frontend
pnpm test components/ai
```
### สิ่งที่ชุดทดสอบจะยืนยัน:
- `ai-chat-panel.tsx` สามารถปิดและเปิดได้จริงเมื่อรับคำสั่ง Action
- `use-ai-chat.ts` สามารถแปลงและแนบพารามิเตอร์ `contextType` และ `contextPublicId` ได้อย่างสมบูรณ์โดยไม่มีการใช้ Integer ID หลุดออกไป (Tier 1 UUID Compliance)
@@ -0,0 +1,56 @@
// File: specs/200-fullstacks/226-document-chat-ui-pattern/research.md
// Change Log:
// - 2026-05-19: Initial research and technical decisions for Document Chat UI Pattern
# Research & Technical Decisions: Document Chat UI Pattern
เอกสารนี้ระบุการตัดสินใจทางเทคนิค การเลือกเครื่องมือ และทางเลือกอื่นที่ได้รับการประเมินสำหรับงานออกแบบระบบ Document Chat UI (226)
## 1. การจัดวางและพฤติกรรมของ UI Panel (UI Layout & Placement)
### การตัดสินใจ (Decision)
เลือกรูปแบบ **Right-side collapsible side-panel** (แผงควบคุมด้านขวาที่สามารถยับเลื่อนปิดได้) บน Desktop และ Tablet และแสดงผลแบบ **Bottom Sheet** สำหรับหน้าจอมือถือ (Mobile)
### เหตุผลสนับสนุน (Rationale)
1. **รักษา Context ของเอกสารหลัก**: ผู้ใช้สามารถเห็น Drawing หรือเนื้อหา RFA ที่ฝั่งซ้ายของจอและแชทถาม AI ที่ฝั่งขวาของจอไปพร้อมกันได้ ทำให้ไม่เกิดปัญหาสลับหน้าจอไปมา (No Context Switching)
2. **ความยืดหยุ่นและการขยายตัว**: ในอนาคตสามารถขยายความกว้างของ Panel หรือเปิดปิดได้อย่างง่ายดาย โดยไม่ขัดจังหวะการอ่านเอกสาร
### ทางเลือกอื่นที่พิจารณา (Alternatives Considered)
- **Modal dialog (แบบ Overlay)**: บดบังเอกสารหลักทั้งหมด ผู้ใช้งานไม่สามารถพิมพ์ถามและดูรูปภาพหรือข้อความของเอกสารหลักไปพร้อมๆ กันได้ จึงปฏิเสธทางเลือกนี้
- **หน้าเพจเดี่ยวแยกต่างหาก (/documents/[id]/chat)**: บังคับให้ผู้ใช้งานสลับหน้าจอไปมาอย่างรุนแรง ทำให้สูญเสีย muscle memory และความลื่นไหลในการทำงาน
---
## 2. การเก็บข้อมูลสนทนาแบบชั่วคราว (Client-side Chat Session Persistence)
### การตัดสินใจ (Decision)
ใช้ **Session Storage** ของบราวเซอร์ในการบันทึกข้อความสนทนาในแต่ละ `documentPublicId` ในระหว่างที่มีการใช้งานบราวเซอร์เซสชันนั้น
### เหตุผลสนับสนุน (Rationale)
1. **ลดภาระฝั่งเซิร์ฟเวอร์**: สอดคล้องกับข้อกำหนด Phase 1 ที่ไม่ต้องการเก็บข้อมูลสนทนาย้อนหลังในฐานข้อมูลส่วนกลาง ช่วยลดการออกแบบ DB schema และการทำ API เคลียร์ข้อมูล
2. **รักษา Context ระหว่างการนำทาง**: หากผู้ใช้สลับไปดูแท็บอื่นหรือหน้าอื่นชั่วคราวแล้วคลิกกลับมา ข้อมูลการคุยกับ AI สำหรับเอกสารนี้จะยังคงอยู่ จนกว่าจะมีการปิดแท็บบราวเซอร์หรือทำการรีเฟรชแบบรุนแรง (Hard Reload)
### ทางเลือกอื่นที่พิจารณา (Alternatives Considered)
- **Local Storage**: ข้อมูลจะค้างอยู่ตลอดไปแม้ปิดบราวเซอร์แล้ว ซึ่งอาจนำไปสู่ปัญหาข้อมูลค้างล้าสมัยหรือความเสี่ยงเรื่องข้อมูลความลับของโครงการในกรณีแชร์บอร์ดคอมพิวเตอร์
- **Redux / Zustand state (In-memory เท่านั้น)**: ข้อมูลหายทันทีเมื่อผู้ใช้เผลอกดโหลดหน้าซ้ำ (Soft Reload) ซึ่งขัดกับความสะดวกในการทำงานต่อเนื่อง
---
## 3. การแสดงผล Suggested Actions
### การตัดสินใจ (Decision)
AI Gateway จะส่งข้อเสนอการกระทำถัดไป (Suggested Actions) ในรูปแบบอาร์เรย์ข้อความและคำสั่งใน payload การตอบกลับ จากนั้น Frontend จะเรนเดอร์ในรูปแบบ **Radix UI/shadcn Badge/Button Chip** ที่สามารถกดใช้งานได้ทันที
### เหตุผลสนับสนุน (Rationale)
1. **สอดคล้องกับสถาปัตยกรรม AI**: AI Gateway/Ollama สามารถแนะนำการดำเนินการตามบริบท (เช่น "ดูการส่ง RFA ล่าสุด", "สร้างฉบับร่างใหม่") ช่วยนำทางผู้ใช้ในระบบ Workflow ได้ดีขึ้น
2. **การทำงานแบบรวดเร็ว**: ลดขั้นตอนการที่ผู้ใช้ต้องนั่งพิมพ์คำสั่งยาวๆ บนอุปกรณ์หน้าจอสัมผัสหรือแท็บเล็ตหน้างาน
---
## 4. API Endpoints & Contract Design
### การตัดสินใจ (Decision)
ออกแบบ API Route หลักที่ `/api/ai/chat` โดยมีโครงสร้างการคุยแบบบูรณาการกับ CASL permission layer ของ NestJS เสมอ
### เหตุผลสนับสนุน (Rationale)
- เพื่อให้มั่นใจว่าคำร้องขอของ AI Subsystem ทั้งหมดอยู่ภายใต้ข้อจำกัดสิทธิ์ **Tenant/Project Isolation (ADR-016 & ADR-023A)** และไม่หลุดพ้นขอบเขต CASL
@@ -0,0 +1,107 @@
// File: specs/200-fullstacks/226-document-chat-ui-pattern/spec.md
// Change Log:
// - 2026-05-19: Initial specification for Document Chat UI Pattern
# Feature Specification: Document Chat UI Pattern
**Feature Branch**: `226-document-chat-ui-pattern`
**Created**: 2026-05-19
**Status**: Draft
**Category**: 200-fullstacks
**Input**: User description from specs/06-Decision-Records/ADR-026-document-chat-ui-pattern.md and CONTEXT.md
## User Scenarios & Testing _(mandatory)_
### User Story 1 - ดูเอกสารและคุยกับ AI พร้อมกันบน Desktop (Priority: P1)
ผู้ใช้งานเปิดดูเอกสาร (เช่น Drawing, RFA, Transmittal, Correspondence) บนหน้าจอ Desktop และสามารถเปิด Panel AI Chat ทางด้านขวาได้โดยที่เนื้อหาของเอกสารหลักไม่ถูกบดบัง ทำให้สามารถดูข้อมูลในเอกสารไปพร้อมๆ กับการพิมพ์ถามหรืออ่านคำตอบจาก AI ได้
**Why this priority**: เป็น Core value ที่ช่วยรักษา context ของเอกสารไม่ให้สลับหน้าไปมา (No context switching)
**Independent Test**: ทดสอบการกดปุ่ม Toggle chat บนหน้าเอกสารหลัก แล้วเปิด Panel ด้านขวา (กว้าง 400px แบบ slide-in) ตรวจสอบว่าหน้าจอหลักปรับความกว้างเพื่อไม่ให้โดนทับ และสามารถพิมพ์โต้ตอบได้สำเร็จ
**Acceptance Scenarios**:
1. **Given** ผู้ใช้เปิดหน้าดูรายละเอียดของ Drawing, **When** ผู้ใช้กดปุ่ม Toggle AI Chat, **Then** Panel AI Chat กว้าง 400px จะ Slide-in ออกมาจากทางด้านขวา และเนื้อหา Drawing จะย่อขนาดลงให้พอดีกับพื้นที่ที่เหลือ
2. **Given** Panel AI Chat เปิดอยู่, **When** ผู้ใช้กดปุ่ม Toggle หรือกดปุ่มปิด Panel, **Then** Panel จะ Slide-out ปิดตัวลง และหน้าจอหลักของ Drawing จะขยายกลับมาเต็มหน้าจอเหมือนเดิม
---
### User Story 2 - การสนทนากับ AI โดยใช้เอกสารเป็นบริบท (Context Injection) (Priority: P1)
ผู้ใช้สามารถส่งคำถามหา AI ใน Chat Panel โดยระบบจะแนบ `documentPublicId` และ `documentType` ไปใน API request โดยอัตโนมัติ ทำให้ AI เข้าใจบริบทของเอกสารที่เปิดอยู่และสามารถตอบคำถามหรือสรุปเนื้อหาได้อย่างถูกต้อง
**Why this priority**: ช่วยให้ผู้ใช้ไม่ต้องพิมพ์อ้างอิงเอกสารซ้ำซ้อน และได้รับคำตอบที่ตรงประเด็นเกี่ยวกับเอกสารนั้นๆ
**Independent Test**: สามารถส่ง query ไปยัง endpoint `/api/ai/chat` พร้อมกับแนบบริบทของ Drawing/RFA แล้วระบบสามารถส่งต่อไปยัง AI Gateway และประมวลผลคำตอบกลับมาได้ถูกต้องตามเอกสารอ้างอิง
**Acceptance Scenarios**:
1. **Given** ผู้ใช้เปิดหน้า RFA ฉบับหนึ่ง, **When** ผู้ใช้พิมพ์ถามว่า "สรุปเอกสารนี้", **Then** ระบบจะเรียก API `/api/ai/chat` โดยมี payload query "สรุปเอกสารนี้" และ context `{ type: "rfa", publicId: "..." }` และแสดงผลลัพธ์การสรุปของ RFA ฉบับนั้นใน Chat Panel
---
### User Story 3 - ปรับเปลี่ยนการแสดงผลตามขนาดหน้าจอ (Responsive Chat Interface) (Priority: P2)
หน้าจอระบบรองรับการเปิดใช้งาน AI Chat บนอุปกรณ์ที่หลากหลาย เช่น Tablet (ขนาด 768px - 1023px) จะแสดง panel ด้านขวาเป็น 30% ของ viewport และบน Mobile (< 768px) จะแสดงผลเป็น Bottom Sheet สูง 60% ที่มี overlay บางๆ บนเอกสารหลัก
**Why this priority**: รองรับพฤติกรรมผู้ใช้ที่เปิดหน้างานก่อสร้างผ่าน Tablet/Mobile นอกสถานที่
**Independent Test**: ปรับขนาดหน้าจอผ่าน Responsive design mode ของ Browser และเปิดใช้งาน Chat Panel เพื่อยืนยันพฤติกรรม UI
**Acceptance Scenarios**:
1. **Given** ผู้ใช้ใช้งานผ่านหน้าจอขนาด 800px (Tablet), **When** กดเปิด AI Chat, **Then** Chat panel จะแสดงผลทางขวากว้าง 30% ของ viewport
2. **Given** ผู้ใช้ใช้งานผ่านหน้าจอขนาด 375px (Mobile), **When** กดเปิด AI Chat, **Then** AI Chat จะแสดงผลในรูปแบบ Bottom Sheet เลื่อนขึ้นมาจากด้านล่างสูง 60% ของจอ โดยมี overlay บดบังส่วนอื่นของจอ
---
### User Story 4 - การนำเสนอ Suggested Actions และการแสดงผลหลายประเภท (Suggested Actions & Response UI) (Priority: P2)
ระบบสามารถแสดงคำแนะนำการกระทำต่อเนื่อง (Suggested Actions) ที่ได้จาก AI ในรูปแบบปุ่ม Chip (เช่น "ดู RFA ฉบับเต็ม", "สร้าง RFA ตัวถัดไป") และผู้ใช้สามารถคลิกปุ่มเพื่อส่ง query ใหม่ได้ทันทีโดยไม่ต้องพิมพ์
**Why this priority**: ช่วยอำนวยความสะดวกในการใช้งานแบบ Workflow Continuity
**Independent Test**: ตรวจสอบการเรนเดอร์ Suggested Actions ใน chat history และการทำงานเมื่อกดปุ่ม Chip
**Acceptance Scenarios**:
1. **Given** AI ส่งข้อความคำตอบพร้อมรายการ Suggested Actions, **When** ข้อความแสดงขึ้นบนจอ, **Then** จะมีปุ่ม Chip แสดงผลใต้กล่องข้อความของ AI
2. **Given** ปุ่ม Suggested Action แสดงอยู่บนจอ, **When** ผู้ใช้คลิกเลือกปุ่มนั้น, **Then** ระบบจะทำการพิมพ์และส่ง query ตามข้อความของปุ่มนั้นไปยัง AI โดยอัตโนมัติ
---
### Edge Cases
- **Network Error / Service Unavailable**: เมื่อเกิดปัญหาเครือข่าย หรือ AI Gateway ล่ม Chat Panel จะต้องแสดงสถานะข้อผิดพลาดสีส้ม/แดงเตือนว่า "ไม่สามารถเชื่อมต่อ AI ได้ กรุณาลองใหม่" พร้อมปุ่ม Retry โดยจะต้องรักษาข้อความสนทนาก่อนหน้าไว้ ไม่ถูกล้างไป
- **AI Timeout**: หาก AI ใช้เวลาประมวลผลนานเกิน 10 วินาที ระบบจะยกเลิกการรอและแสดงข้อความ "AI ตอบช้าเกินไป กรุณาลองอีกครั้ง" และบันทึกเหตุการณ์ลงใน `ai_audit_logs`
- **ไม่มีสิทธิ์เข้าถึงเอกสาร (Permission/CASL Error)**: หากสิทธิ์ของผู้ใช้ถูกเปลี่ยนระหว่างเปิดหน้านั้นๆ หรือไม่มีสิทธิ์เข้าถึงข้อมูลย่อยใน Tool Layer ระบบต้องแจ้งเตือนว่า "คุณไม่มีสิทธิ์เข้าถึงข้อมูลนี้" โดยไม่แสดงรายละเอียดด้านเทคนิคภายใน
- **การเปลี่ยนหน้าเอกสาร (Document Switching/Navigation)**: เมื่อผู้ใช้เปิดหน้าเอกสารอื่น ระบบจะทำการ reset หรือ auto-collapse chat panel เพื่อป้องกันความสับสนของบริบท (Context Preservation)
- **การเก็บสถานะสนทนา (Session Persistence)**: ข้อความการสนทนาใน session นี้จะเก็บอยู่ใน Session Storage เพื่อไม่ให้หายเมื่อมีการเปลี่ยนหน้า แต่หากกดรีเฟรชหน้าจอ (Hard Reload) สนทนาจะถูกเคลียร์เพื่อลดความซับซ้อนตามขอบเขตระยะแรก (v1)
## Requirements _(mandatory)_
### Functional Requirements
- **FR-001**: ระบบต้องมี `AiChatPanel` component ที่สามารถเปิด/ปิดได้ทางด้านขวาบนหน้าจอ Desktop และมีปุ่ม `AiChatToggle` สำหรับควบคุม
- **FR-002**: ระบบต้องตรวจจับขนาดหน้าจอของอุปกรณ์และแสดงผลลัพธ์เป็น Collapsible panel (ขวากว้าง 400px สำหรับ Desktop, ขวากว้าง 30% สำหรับ Tablet) หรือ Bottom Sheet (สูง 60% สำหรับ Mobile)
- **FR-003**: ระบบต้องทำการแนบ `context` ซึ่งประกอบด้วย `type` และ `publicId` ของหน้าเอกสารปัจจุบันทุกครั้งที่ส่งคำถามไปยัง `/api/ai/chat`
- **FR-004**: ระบบต้องรองรับการส่งและรับคำตอบแบบ Stream/Chunk จาก AI Gateway เพื่อการแสดงผลแบบค่อยๆ ปรากฏ (หาก API รองรับ) หรือแบบปกติ (v1 fallback)
- **FR-005**: ระบบต้องจัดเตรียมคีย์บอร์ดชอร์ตคัต `Ctrl/Cmd + .` ในการเปิด/ปิด Chat Panel เพื่อการเข้าถึงที่รวดเร็ว (Accessibility)
- **FR-006**: ระบบต้องแสดง Suggested Actions ในรูปของปุ่ม Chip ใต้ข้อความของ AI และเมื่อคลิกจะส่งข้อความนั้นเข้าสู่สนทนาโดยอัตโนมัติ
- **FR-007**: ระบบต้องบันทึกเหตุการณ์การถามตอบทั้งหมดลงใน `ai_audit_logs` ผ่าน API หลังการสนทนาแต่ละครั้ง รวมถึง Latency, ContextType, Query, ResponseType
- **FR-008**: ระบบต้องรักษาประวัติสนทนาใน Session Storage ตราบใดที่ยังอยู่ใน Session ปัจจุบัน และเคลียร์ประวัติเมื่อจบ session หรือปิดหน้าจอหลัก
### Key Entities
- **ChatMessage**: ตัวแทนของแต่ละข้อความในประวัติสนทนา ประกอบด้วย `id` (UUIDv7 string), `role` ('user' | 'assistant' | 'system'), `content` (string), `timestamp` (Date), `suggestedActions` (array of actions)
- **SuggestedAction**: ปุ่มนำเสนอเพื่อให้ผู้ใช้กดทำงานต่อ ประกอบด้วย `label` (ข้อความปุ่ม), `query` (คำสั่งที่จะส่งหา AI เมื่อกด)
## Success Criteria _(mandatory)_
### Measurable Outcomes
- **SC-001**: ผู้ใช้งานสามารถเปิด/ปิด AI Chat panel ได้ภายใน 200ms ด้วยความลื่นไหลของการแสดงผล Animation (Slide in/out)
- **SC-002**: ระบบสามารถแนบ context ของเอกสารที่เปิดอยู่ได้อย่างสมบูรณ์ 100% โดยไม่มีข้อผิดพลาดด้านความเข้ากันได้ของข้อมูล
- **SC-003**: ผู้ใช้พึงพอใจและสามารถเข้าถึงข้อมูลของหน้าจอหลักขณะเปิด Panel สนทนาได้โดยไม่มีส่วนสำคัญของเอกสารถูกบดบังบน Desktop
- **SC-004**: เมื่อเกิดปัญหา Network error ระบบต้องใช้เวลาน้อยกว่า 500ms ในการตรวจจับและแสดง UI แจ้งเตือนข้อผิดพลาดพร้อมปุ่มให้ Retry
@@ -0,0 +1,122 @@
// File: specs/200-fullstacks/226-document-chat-ui-pattern/tasks.md
// Change Log:
// - 2026-05-19: Initial task list for Document Chat UI Pattern
# Tasks: Document Chat UI Pattern
**Input**: Design documents from `/specs/200-fullstacks/226-document-chat-ui-pattern/`
**Prerequisites**: plan.md (required), spec.md (required)
---
## Phase 1: Setup (การเตรียมโครงสร้างและ Proxy API)
**Purpose**: ตั้งค่าโครงสร้างโปรเจกต์และสร้าง API endpoint proxy เบื้องต้น
- [X] T001 สร้างโครงสร้างโฟลเดอร์สำหรับเอกสารวิศวกรรมใน `specs/200-fullstacks/226-document-chat-ui-pattern/`
- [X] T002 ตั้งค่า API Route Proxy สำหรับ Chat ใน `frontend/app/api/ai/chat/route.ts` เพื่อรับส่งงานไปยัง AI Gateway
---
## Phase 2: Foundational (โครงสร้างข้อมูลแชทและ React State Hook)
**Purpose**: สร้างระบบพื้นฐานและ Hook สำหรับจัดการแชท ซึ่งเป็นรากฐานของหน้าจอย่อยทั้งหมด
**⚠️ CRITICAL**: ต้องทำส่วนนี้ให้เสร็จสิ้นก่อนเริ่มทำ User Story อื่นๆ
- [X] T003 [P] สร้างอินเตอร์เฟซ TypeScript สำหรับ Chat Messages และ API payload ใน `frontend/types/ai-chat.ts`
- [X] T004 พัฒนา custom React Hook `useAiChat` ใน `frontend/hooks/use-ai-chat.ts` เพื่อจัดการ Session Storage และการเรียกใช้ API ของ AI Chat
**Checkpoint**: โครงสร้างพื้นฐานเสร็จสมบูรณ์ - พร้อมสำหรับการเริ่มพัฒนา User Story ในขั้นตอนถัดไป
---
## Phase 3: User Story 1 - ดูเอกสารและคุยกับ AI พร้อมกันบน Desktop (Priority: P1) 🎯 MVP
**Goal**: พัฒนาหน้าจอแชทแบบ Slide-in panel ด้านขวาในหน้าดูรายละเอียดเอกสารหลัก โดยไม่บดบังเนื้อหา (Desktop)
**Independent Test**: ผู้ใช้งานบน Desktop สามารถเปิด/ปิด Chat Panel ได้ผ่านปุ่ม Toggle และพิมพ์สนทนากับ AI ได้อย่างลื่นไหลโดยเอกสารหลักย่อขนาดหลบด้านข้าง
### Implementation for User Story 1
- [X] T005 [P] [US1] พัฒนาคอมโพเนนต์ `AiChatToggle` ใน `frontend/components/ai/ai-chat-toggle.tsx` สำหรับเป็นปุ่มควบคุม
- [X] T006 [P] [US1] พัฒนาคอมโพเนนต์ `AiChatInput` ใน `frontend/components/ai/ai-chat-input.tsx` สำหรับพิมพ์คำสั่งและส่งข้อความ
- [X] T007 [US1] พัฒนาคอมโพเนนต์หลัก `AiChatPanel` ใน `frontend/components/ai/ai-chat-panel.tsx` เพื่อเรนเดอร์แผงกว้าง 400px (Desktop) แบบ Slide-in (ขึ้นกับ T005, T006)
- [X] T008 [US1] ติดตั้ง `AiChatPanel` และ `AiChatToggle` ในหน้าดูข้อมูล Drawing ใน `frontend/app/drawings/[publicId]/page.tsx`
- [X] T009 [US1] ติดตั้ง `AiChatPanel` และ `AiChatToggle` ในหน้าดูข้อมูล RFA ใน `frontend/app/rfas/[publicId]/page.tsx`
**Checkpoint**: สิ้นสุดขั้นตอนนี้ ระบบจะสามารถใช้งาน AI Chat เคียงคู่กับเอกสารบน Desktop ได้อย่างสมบูรณ์แบบอิสระ
---
## Phase 4: User Story 2 - การสนทนากับ AI โดยใช้เอกสารเป็นบริบท (Context Injection) (Priority: P1)
**Goal**: ระบบแนบบริบทของเอกสาร (type และ publicId) ไปพร้อมคำถามทุกครั้งเพื่อให้ AI ให้ Insight ได้ตรงจุด
**Independent Test**: เมื่อพิมพ์คำถาม "สรุปเอกสารนี้" ระบบสามารถเรียก endpoint ด้วย context payload ที่ถูกต้อง โดยที่ไม่มี integer id รั่วไหล
### Implementation for User Story 2
- [X] T010 [US2] เพิ่มตรรกะตรวจจับบริบท (Context Injection) ใน `frontend/hooks/use-ai-chat.ts` เพื่อแนบประเภทและ publicId อัตโนมัติ
- [X] T011 [US2] พัฒนาคอมโพเนนต์แสดงผลรายการประวัติข้อความ `AiChatMessages` ใน `frontend/components/ai/ai-chat-messages.tsx` ให้แยกความแตกต่างระหว่างกล่องข้อความผู้ใช้, AI, ระบบ, หรือข้อผิดพลาด
**Checkpoint**: ระบบเข้าใจบริบทของเอกสารที่ผู้ใช้เปิดอ่านอยู่ได้สำเร็จและแสดงผลการตอบสนองได้ตรงประเด็น
---
## Phase 5: User Story 3 - ปรับเปลี่ยนการแสดงผลตามขนาดหน้าจอ (Priority: P2)
**Goal**: รองรับ Responsive layout (Tablet กว้าง 30%, Mobile แสดงผลเป็น Bottom sheet เด้งลอยสูง 60%)
**Independent Test**: ย่อบราวเซอร์หรือทดสอบบนแท็บเล็ตและอุปกรณ์พกพา ยืนยันว่าลักษณะของ Chat Panel ปรับตาม Breakpoint ได้ถูกต้อง
### Implementation for User Story 3
- [X] T012 [US3] ปรับปรุง `AiChatPanel` ใน `frontend/components/ai/ai-chat-panel.tsx` โดยใช้ CSS Media query หรือ Radix UI primitives ให้ปรับเปลี่ยนเลย์เอาต์ตาม Responsive breakpoint
---
## Phase 6: User Story 4 - การนำเสนอ Suggested Actions แนะนำการสั่งงาน (Priority: P2)
**Goal**: แสดงปุ่ม Chip แนะนำการทำงาน และเมื่อคลิกจะส่งคำถามไปยัง AI อัตโนมัติ
**Independent Test**: กล่องข้อความ AI เรนเดอร์ปุ่ม Chip สั่งงานใต้คำตอบ และเมื่อคลิกจะส่งข้อความนั้นเข้ากล่องแชททันที
### Implementation for User Story 4
- [X] T013 [P] [US4] สร้างคอมโพเนนต์แนะนำคำสั่ง `AiSuggestedActions` ใน `frontend/components/ai/ai-suggested-actions.tsx` สำหรับแสดงปุ่ม Chip
- [X] T014 [US4] ผนวกรหัสสั่งงานเข้ากับ `AiChatPanel` ใน `frontend/components/ai/ai-chat-panel.tsx` เพื่อให้การกด Chip ส่งคำสั่งทันที
---
## Phase 7: Polish & Cross-Cutting Concerns (ความสมบูรณ์ขั้นสุดท้ายและเค้าโครงระบบทดสอบ)
**Purpose**: ปรับแต่งจุดข้ามผ่าน ความเป็นระเบียบ และการติดตั้งระบบตรวจสอบอัตโนมัติ
- [X] T015 ติดตั้งคีย์บอร์ดชอร์ตคัต `Ctrl/Cmd + .` ใน `frontend/components/ai/ai-chat-panel.tsx`
- [X] T016 เพิ่ม Unit Test สำหรับ `useAiChat` ใน `frontend/hooks/use-ai-chat.spec.ts` ด้วย Vitest
- [X] T017 เพิ่ม Unit Test สำหรับ `AiChatPanel` ใน `frontend/components/ai/ai-chat-panel.spec.tsx`
- [X] T018 ตรวจทานความสอดคล้องกับมาตรการความปลอดภัยและ UUIDv7 (ADR-019) ในทุกไฟล์ที่พัฒนาขึ้นใหม่
---
## Dependencies & Execution Order (ลำดับและการพึ่งพากันในการรันงาน)
### Phase Dependencies
```mermaid
graph TD
P1[Phase 1: Setup] --> P2[Phase 2: Foundational]
P2 --> P3[Phase 3: User Story 1 - Desktop MVP]
P2 --> P4[Phase 4: User Story 2 - Context Injection]
P3 --> P5[Phase 5: User Story 3 - Responsive]
P4 --> P6[Phase 6: User Story 4 - Suggested Actions]
P5 --> P7[Phase 7: Polish & Verification]
P6 --> P7
```
### Parallel Opportunities (โอกาสทำงานคู่ขนาน)
- **Foundational (Phase 2)**: สามารถพัฒนาอินเตอร์เฟซและโมเดลข้อมูล `T003` คู่ขนานไปกับการออกแบบ custom hook `T004` ได้
- **User Story 1 (Phase 3)**: สามารถแยกสร้างคอมโพเนนต์ย่อย `T005` (Toggle) และ `T006` (Input) ในเวลาเดียวกันได้
- **User Story 4 (Phase 6)**: สามารถพัฒนาปุ่มแนะนำ `T013` คู่ขนานไปกับส่วนประกอบอื่นได้