AgentSkillsCN

verify-inquiry-ui

咨询详情页面 UI 组件验证(以 shadcn/ui + Tailwind 为标准)。在修改咨询选项卡(信息/分析/解答/历史)及上传组件后使用。

SKILL.md
--- frontmatter
name: verify-inquiry-ui
description: 문의 상세 페이지 UI 컴포넌트 검증 (shadcn/ui + Tailwind 기준). 문의 탭(Info/Analysis/Answer/History) 및 업로드 컴포넌트 수정 후 사용.

Purpose

  1. Citation 파싱 일관성 — AnswerTab과 HistoryTab의 parseCitation이 백엔드 citations 형식과 동기화되는지 확인
  2. Split Pane 레이아웃 — Tailwind grid + lg: 반응형으로 split pane 구현 확인
  3. PdfViewer SSR 제한 — AnswerTab과 HistoryTab에서 dynamic import + ssr: false 사용 확인
  4. sourceType 뱃지 매핑 — KNOWLEDGE_BASE="지식 기반"/INQUIRY="문의 첨부" 일관성 확인
  5. 한국어 라벨 함수 사용 — 영문 enum 값을 직접 표시하지 않고 labelVerdict/labelDocStatus 등 사용 확인
  6. shadcn 컴포넌트 사용 — Button, Badge, Skeleton 등 shadcn/커스텀 UI 컴포넌트 사용 확인
  7. react-hook-form + zod — InquiryCreateForm에서 폼 유효성 검사 확인

When to Run

  • frontend/src/components/inquiry/ 하위 컴포넌트 수정 후
  • frontend/src/components/upload/ 하위 컴포넌트 수정 후
  • frontend/src/lib/api/client.ts의 타입/함수 변경 후
  • 답변 초안 표시 로직 변경 후
  • 근거 표시 형식 변경 후

Related Files

FilePurpose
frontend/src/components/inquiry/InquiryAnswerTab.tsx답변 탭 (Tailwind grid split pane + Citation 파싱 + PdfViewer)
frontend/src/components/inquiry/InquiryAnalysisTab.tsx분석 탭 (근거 표시 + sourceType 뱃지 + shadcn Button)
frontend/src/components/inquiry/InquiryCreateForm.tsx문의 생성 폼 (react-hook-form + zod + shadcn Button)
frontend/src/components/inquiry/InquiryInfoTab.tsx정보 탭 (문서 목록 + 인덱싱 상태 + Skeleton)
frontend/src/components/inquiry/InquiryHistoryTab.tsx이력 탭 (버전 히스토리 + Tailwind grid split pane + PdfViewer)
frontend/src/components/upload/SmartUploadModal.tsx스마트 업로드 모달 (KB 문서 일괄 업로드)
frontend/src/components/upload/FileDropZone.tsx파일 드래그앤드롭 영역 (cn + Tailwind)
frontend/src/components/upload/FileQueueItem.tsx파일 큐 아이템 (cn + status 기반 스타일)
frontend/src/lib/api/client.tsAPI 클라이언트 (타입 정의 + 헬퍼 함수)
frontend/src/lib/i18n/labels.ts한국어 라벨 매핑 함수

Workflow

Step 1: Citation 파싱 정규식 확인

파일: InquiryAnswerTab.tsx, InquiryHistoryTab.tsx

검사: parseCitation 함수가 6개 키 (chunk, score, documentId, fileName, pageStart, pageEnd)를 파싱하는지 확인.

bash
grep -n "chunk=\|score=\|documentId=\|fileName=\|pageStart=\|pageEnd=" frontend/src/components/inquiry/InquiryAnswerTab.tsx frontend/src/components/inquiry/InquiryHistoryTab.tsx

PASS: 양쪽 모두 6개 키 정규식 매칭 존재 FAIL: 키 누락 또는 fileName regex 오류

Step 2: Tailwind Grid Split Pane 확인

파일: InquiryAnswerTab.tsx, InquiryHistoryTab.tsx

검사: split pane이 Tailwind grid (grid grid-cols-1 gap-6 lg:grid-cols-[1fr_400px])로 구현되었는지 확인.

bash
grep -n "grid.*cols\|lg:grid-cols\|lg:sticky\|lg:self-start" frontend/src/components/inquiry/InquiryAnswerTab.tsx frontend/src/components/inquiry/InquiryHistoryTab.tsx

PASS: Tailwind grid + lg: 반응형 + sticky 오른쪽 패널 존재 FAIL: 레거시 .split-pane CSS 클래스 사용 또는 split pane 누락

Step 3: PdfViewer dynamic import + ssr: false 확인

파일: InquiryAnswerTab.tsx, InquiryHistoryTab.tsx

검사: PdfViewer를 next/dynamic으로 ssr: false 설정하여 임포트하는지 확인.

bash
grep -rn "dynamic\|ssr.*false\|PdfViewer" frontend/src/components/inquiry/InquiryAnswerTab.tsx frontend/src/components/inquiry/InquiryHistoryTab.tsx

PASS: 양쪽 모두 dynamic(() => import(...), { ssr: false }) 패턴 존재 FAIL: 직접 import 사용

Step 4: 답변 본문 whitespace-pre-wrap 확인

파일: InquiryAnswerTab.tsx, InquiryHistoryTab.tsx

검사: 답변 초안 본문에 Tailwind whitespace-pre-wrap 클래스가 적용되는지 확인.

bash
grep -rn "whitespace-pre-wrap\|pre-wrap" frontend/src/components/inquiry/InquiryAnswerTab.tsx frontend/src/components/inquiry/InquiryHistoryTab.tsx

PASS: 답변 본문 표시 영역에 whitespace-pre-wrap 클래스 적용 FAIL: whitespace-pre-wrap 없음

Step 5: sourceType 뱃지 매핑 일관성

파일: InquiryAnalysisTab.tsx, InquiryAnswerTab.tsx

검사: KNOWLEDGE_BASE="지식 기반" (info), INQUIRY/else="문의 첨부" (neutral) 매핑이 양쪽 컴포넌트에서 일관되는지 확인.

bash
grep -rn "지식 기반\|문의 첨부\|KNOWLEDGE_BASE\|sourceType" frontend/src/components/inquiry/InquiryAnalysisTab.tsx frontend/src/components/inquiry/InquiryAnswerTab.tsx

PASS: 양쪽 모두 동일한 매핑 규칙 사용 FAIL: 컴포넌트 간 뱃지 variant 또는 라벨 불일치

Step 6: 한국어 라벨 함수 사용 확인

파일: frontend/src/components/inquiry/*.tsx

검사: 영문 enum 값을 직접 표시하지 않고 labels.ts의 함수를 통해 변환하는지 확인.

bash
grep -rn "labelVerdict\|labelAnswerStatus\|labelDocStatus\|labelChannel\|labelTone" frontend/src/components/inquiry/

PASS: 4개 이상의 라벨 함수 사용 FAIL: 영문 enum 값 직접 표시

Step 7: shadcn Button 사용 확인

파일: frontend/src/components/inquiry/*.tsx

검사: 모든 inquiry 컴포넌트에서 레거시 .btn 클래스 대신 shadcn Button 컴포넌트를 사용하는지 확인.

bash
grep -rn "from.*button\|className=\"btn" frontend/src/components/inquiry/*.tsx

PASS: shadcn Button import 존재, .btn 클래스 없음 FAIL: 레거시 .btn 클래스 사용

Step 8: react-hook-form + zod 스키마 확인

파일: InquiryCreateForm.tsx

검사: react-hook-form의 useForm + zodResolver를 사용하고, zod 스키마가 정의되어 있는지 확인.

bash
grep -rn "useForm\|zodResolver\|z\.object\|z\.string\|z\.enum" frontend/src/components/inquiry/InquiryCreateForm.tsx

PASS: useForm + zodResolver + z.object 스키마 존재 FAIL: 수동 상태 관리 또는 유효성 검사 누락

Step 9: 파일 업로드 accept 속성 확인

파일: InquiryCreateForm.tsx, FileDropZone.tsx

검사: 파일 업로드에 허용 파일 형식이 지정되어 있는지 확인.

bash
grep -n "accept\|\.pdf\|\.doc" frontend/src/components/inquiry/InquiryCreateForm.tsx frontend/src/components/upload/FileDropZone.tsx

PASS: accept 속성에 PDF/DOC/DOCX 지정 FAIL: accept 속성 없음

Step 10: API 클라이언트 다운로드 URL 헬퍼 확인

파일: frontend/src/lib/api/client.ts

검사: getDocumentDownloadUrlgetDocumentPagesUrl 헬퍼 함수가 존재하는지 확인.

bash
grep -n "getDocumentDownloadUrl\|getDocumentPagesUrl" frontend/src/lib/api/client.ts

PASS: 두 함수 모두 존재 FAIL: 함수 누락

Output Format

#검사 항목결과상세
1Citation 파싱 정규식PASS/FAIL누락 키, regex 방식
2Tailwind Grid Split PanePASS/FAILgrid 패턴, lg: 반응형
3PdfViewer SSR 제한PASS/FAILimport 방식
4whitespace-pre-wrapPASS/FAIL미적용 컴포넌트
5sourceType 뱃지 매핑PASS/FAIL불일치 위치
6한국어 라벨 함수PASS/FAIL직접 표시 위치
7shadcn Button 사용PASS/FAIL레거시 .btn 사용처
8react-hook-form + zodPASS/FAIL누락 패턴
9파일 업로드 acceptPASS/FAILaccept 속성
10다운로드 URL 헬퍼PASS/FAIL함수 유무

Exceptions

다음은 위반이 아닙니다:

  1. 3단계 폴백 표시 — fileName → documentId.slice(0,8) → chunkId.slice(0,8) 순서는 레거시 호환
  2. SmartUploadModal의 category 기본값 — 기본값이 빈 문자열인 것은 의도된 동작 (사용자 선택 유도)
  3. InquiryCreateForm의 file useState — react-hook-form 외부에서 파일 상태를 관리하는 것은 File 객체의 직렬화 제한 때문