8.7 KiB
Implementation Plan: AI Console Collapsible Cards
Branch: [240-ai-console-collapsible-cards] | Date: 2026-06-19 | Spec: spec.md
Input: Feature specification from /specs/200-fullstacks/240-ai-console-collapsible-cards/spec.md
Summary
ปรับปรุงหน้า AI Console (/admin/ai) ให้รองรับการย่อ/ขยาย (Collapsible) สำหรับการ์ดการตรวจติดตามสุขภาพระบบ AI (Monitoring Cards) เพื่อให้ Superadmin สามารถบริหารจัดการพื้นที่หน้าจอได้ดีขึ้นระหว่างการทดสอบระบบ Sandbox:
- เพิ่มส่วนหัวของกลุ่มการ์ดพร้อมปุ่มย่อ/ขยายระบบตรวจติดตามทั้งหมด (Master Collapse)
- เพิ่มปุ่มย่อ/ขยายการ์ดแต่ละใบแบบอิสระ (Ollama, Qdrant, OCR Sidecar, BullMQ, VRAM)
- เก็บสถานะการย่อ/ขยายไว้ใน
localStorageเพื่อให้คงสถานะไว้เมื่อรีเฟรชหน้าเว็บหรือเปลี่ยนแท็บ
Technical Context
Language/Version: TypeScript 5.x, React, Next.js 16 (Client Components) Primary Dependencies:
- Frontend:
lucide-react(สำหรับไอคอนChevronUpหรือChevronDown) - Tailwind CSS (สำหรับทำ transition:
transition-all duration-300 ease-in-out,max-h-0,max-h-[500px],rotate-180) localStorage(สำหรับ persistence)
Storage: localStorage ในเบราว์เซอร์
Testing: การตรวจสอบสไตล์ UI/UX และการทำงานแบบ Manual เท่านั้น
Constitution Check
| Gate | Status | Notes |
|---|---|---|
| 2 projects max | PASS | เปลี่ยนแปลงเฉพาะหน้า UI บน Frontend |
| Language aligned | PASS | โค้ดภาษาอังกฤษ เอกสารภาษาไทย |
| Storage aligned | PASS | ใช้ localStorage บนฝั่งไคลเอนต์เท่านั้น |
| Test coverage | PASS | UI/UX refactor เน้นการทำ manual validation |
Project Structure
Documentation (this feature)
specs/200-fullstacks/240-ai-console-collapsible-cards/
├── plan.md # This file
├── spec.md # Feature specification
└── checklists/
└── requirements.md # Quality checklist
Source Code
frontend/
└── app/(admin)/admin/ai/
└── page.tsx # AI Console page (modify)
Structure Decision: Web application (frontend only refactor). แก้ไขไฟล์ frontend/app/(admin)/admin/ai/page.tsx เพียงไฟล์เดียวเพื่อควบคุมสถานะและการเคลื่อนไหวแบบ Collapsible
Proposed Changes
[Component Name] Next.js Frontend Page
[MODIFY] page.tsx
-
Imports:
- เพิ่มการนำเข้าไอคอน
ChevronUp(หรือChevronDown) จากlucide-react
- เพิ่มการนำเข้าไอคอน
-
React States & Effects:
- เพิ่ม
isSectionCollapsed(boolean) เริ่มต้นเป็นfalse - เพิ่ม
collapsedCards(object) สำหรับเก็บสถานะการย่อของการ์ดแต่ละใบ:const [isSectionCollapsed, setIsSectionCollapsed] = useState<boolean>(false); const [collapsedCards, setCollapsedCards] = useState<{ ollama: boolean; qdrant: boolean; ocr: boolean; bullmq: boolean; vram: boolean; }>({ ollama: false, qdrant: false, ocr: false, bullmq: false, vram: false, }); - เพิ่ม
useEffectสำหรับโหลดค่าสถานะเหล่านี้จากlocalStorageตอนเริ่มต้นโหลดหน้าเว็บ:useEffect(() => { const savedSection = localStorage.getItem('ai_console_section_collapsed'); if (savedSection !== null) { setIsSectionCollapsed(savedSection === 'true'); } const savedCards = localStorage.getItem('ai_console_cards_collapsed'); if (savedCards) { try { setCollapsedCards(JSON.parse(savedCards)); } catch (e) { // เงียบข้อผิดพลาด } } }, []); - เพิ่มฟังก์ชันเพื่อบันทึกสถานะลง
localStorageทุกครั้งที่มีการเปลี่ยนค่า:const toggleSection = () => { const nextVal = !isSectionCollapsed; setIsSectionCollapsed(nextVal); localStorage.setItem('ai_console_section_collapsed', String(nextVal)); }; const toggleCard = (cardKey: keyof typeof collapsedCards) => { const nextCards = { ...collapsedCards, [cardKey]: !collapsedCards[cardKey] }; setCollapsedCards(nextCards); localStorage.setItem('ai_console_cards_collapsed', JSON.stringify(nextCards)); };
- เพิ่ม
-
Master Section Toggle Header:
- ด้านบนของกลุ่มการ์ด เพิ่มส่วนหัวของระบบตรวจติดตาม (Monitoring Header):
<div className="flex items-center justify-between border-b pb-2 mb-4"> <h2 className="text-lg font-semibold flex items-center gap-2"> <Activity className="h-5 w-5 text-primary" /> AI Engine Infrastructure Monitoring </h2> <Button variant="ghost" size="icon" className="h-8 w-8 text-muted-foreground hover:text-foreground" onClick={toggleSection} > <ChevronUp className={`h-5 w-5 transition-transform duration-300 ${isSectionCollapsed ? 'rotate-180' : ''}`} /> </Button> </div>
- ด้านบนของกลุ่มการ์ด เพิ่มส่วนหัวของระบบตรวจติดตาม (Monitoring Header):
-
Grid Animation Wrapper:
- ครอบกลุ่มการ์ดด้วยดิฟที่มีคลาสทำ transition:
<div className={`grid gap-4 md:grid-cols-3 transition-all duration-300 ease-in-out ${ isSectionCollapsed ? 'max-h-0 opacity-0 overflow-hidden pointer-events-none' : 'max-h-[2000px] opacity-100' }`}>
- ครอบกลุ่มการ์ดด้วยดิฟที่มีคลาสทำ transition:
-
Individual Card Adjustments:
- เพิ่มปุ่มย่อ/ขยายถัดจากสถานะในแต่ละการ์ด (Ollama, Qdrant, OCR Sidecar, BullMQ, VRAM)
- ครอบเนื้อหา
<CardContent>(รวมถึงส่วนข้อมูลเพิ่มเติม) เพื่อย่อ/ขยายด้วย transition:<div className={`transition-all duration-300 ease-in-out ${ collapsedCards.ollama ? 'max-h-0 opacity-0 overflow-hidden' : 'max-h-[500px] opacity-100' }`}> <CardContent className="space-y-2"> ... </CardContent> </div> - สลับไอคอน chevron ตามสถานะการย่อ/ขยาย
Verification Plan
Automated Tests
- ตรวจสอบชนิดข้อมูล (Type Checking):
pnpm --filter lcbp3-frontend exec tsc --noEmit - ตรวจสอบรูปแบบโค้ด (Linting):
pnpm --filter lcbp3-frontend exec eslint .
Manual Verification
- เปิดหน้า AI Console ในแอปพลิเคชัน
- คลิกปุ่มย่อ/ขยายระบบติดตามตรวจสอบทั้งหมด (Master Collapse) และดูการตอบสนอง
- คลิกปุ่มย่อ/ขยายในการ์ดแต่ละใบและดูการย่อ/ขยายเฉพาะเนื้อหา
- โหลดหน้าเว็บซ้ำ (F5) และยืนยันว่าสถานะการย่อ/ขยายในแต่ละปุ่มถูกรักษาไว้ด้วย
localStorage - สลับแท็บไปที่ RAG Playground หรือ 3-Step Pipeline Sandbox และสลับกลับมายืนยันว่าสถานะคงเดิม