사건 상세 페이지 — 버튼 Contract SSoT
ADR 0043 v2.66 — Track O. 사건 상세 페이지 (/cases/[caseId]) 의 모든 클릭 가능 요소의 contract (클릭 시 호출되는 handler + 기대 effect) 명세.
검증 경로:
- 정적 (vitest):
apps/web/__tests__/case-detail-contract-invariants.test.ts
- E2E (Playwright):
e2e/regression-case-detail-buttons.spec.ts (visibility 만)
카테고리별 65 버튼
| # | 라벨 | onClick / href | Handler 정의 위치 | 기대 effect |
|---|
| 1 | 뒤로가기 (←) | <Link href="/cases"> | next/link 자체 | /cases 로 이동 |
| 2 | 이전 사건 | router.push('/cases/{prev}') | CasePrevNextNav.tsx:77 | 이전 사건 상세 |
| 3 | 다음 사건 | router.push('/cases/{next}') | CasePrevNextNav.tsx:93 | 다음 사건 상세 |
| 4 | 서류 작성 | onShowDocGenerate | CaseDetailClient setShowDocGenerate(true) | InlineDocGenerate 모달 |
| 5 | 인쇄 (Printer) | onPrintSummary | CaseDetailClient window.open + win.print() | 새 탭 + print dialog |
| 6 | 사건 삭제 (Trash) | onDelete | CaseDetailClient setShowDeleteDialog(true) | AlertDialog open |
| 7 | 상태 드롭다운 | setPendingStatus(value) | CaseHeader.tsx:288 | 상태 변경 확인 dialog |
| # | 라벨 | onClick | 기대 effect |
|---|
| 8 | 취소 | AlertDialogCancel | 다이얼로그 닫기 |
| 9 | 변경 | AlertDialogAction → handleStatusConfirm | Firestore mutation: 사건 status 변경 + activityLog |
탭 네비게이션 (CaseDetailClient.tsx) — 13개
| # | 라벨 | onClick | 기대 effect |
|---|
| 10 | 개요 | TabsTrigger value="overview" | overview 탭 활성 |
| 11 | 회수 (desktop) | value="recovery" | recovery 탭 |
| 12 | 서류 | value="documents" | documents 탭 |
| 13 | 증거 (desktop) | value="evidence" | evidence 탭 |
| 14 | 기일 | value="hearings" | hearings 탭 |
| 15 | 변제 (desktop) | value="recoveries" | recoveries 탭 |
| 16 | 대화 | value="messages" | messages 탭 |
| 17 | 메모 (desktop) | value="notes" | notes 탭 |
| 18 | ⋯ 더보기 (mobile) | DropdownMenuTrigger | 숨겨진 탭 메뉴 |
| 19 | 회수 (mobile) | handleTabChange("recovery") | recovery 탭 (mobile) |
| 20 | 증거 (mobile) | handleTabChange("evidence") | evidence 탭 (mobile) |
| 21 | 변제 (mobile) | handleTabChange("recoveries") | recoveries 탭 (mobile) |
| 22 | 메모 (mobile) | handleTabChange("notes") | notes 탭 (mobile) |
사건 정보 카드 (CaseInfoSection.tsx) — 6개
| # | 라벨 | onClick | 기대 effect |
|---|
| 23 | 편집 | setEditing(true) | 편집 mode 진입 |
| 24 | 취소 (편집) | setEditing(false) | 편집 mode 종료 |
| 25 | 저장 (form submit) | handleSubmit → updateCaseAction | Firestore mutation |
| 26 | 의뢰인 포털 링크 | DialogTrigger | PortalLinkDialog open |
| 27 | 계약기한 편집 | handleStartEdit | 계약기한 편집 mode |
| 28 | 계약기한 삭제 | handleDelete | 계약기한 삭제 |
포털 링크 다이얼로그 (PortalLinkDialog.tsx) — 7개
| # | 라벨 | onClick | 기대 effect |
|---|
| 29 | 의뢰인 포털 링크 생성 | handleGenerate → createPortalTokenAction | Firestore mutation: portalTokens add |
| 30 | 복사 (URL) | handleCopyUrl | clipboard.writeText(url) + toast |
| 31 | 복사 (코드) | handleCopyCode | clipboard.writeText(code) + toast |
| 32 | 함께 공유 | handleShare | 카카오톡 공유 또는 클립보드 |
| 33 | 새 코드로 재발급 | handleRegenerate | 새 토큰 발급 + 기존 무효화 |
| 34 | 링크 비활성화 | handleRevoke | revokePortalTokenAction |
| 35 | (Dialog close) | DialogClose | 다이얼로그 닫기 |
AI 전략 분석 (CaseStrategyReport.tsx) — 5개
| # | 라벨 | onClick | 기대 effect |
|---|
| 36 | 전략 분석 (초기) | handleGenerate | executeAiAction → Gemini → saveStrategyReportAction |
| 37 | 다시 분석 (top-right) | handleGenerate | 위와 동일 |
| 38 | 재분석 (stale 배너) | handleGenerate | 위와 동일 |
| 39 | 다시 시도 (error) | handleGenerate | 위와 동일 |
| 40 | 이전 분석 (toggle) | toggleHistory → listStrategyReportsAction | history list expand (v2.59) |
| # | 라벨 | onClick / href | 기대 effect |
|---|
| 41 | 기억에서 찾기 + AI 분석 | handleRun | findRelatedMemoriesAction + Gemini + saveMemoryAnalysisAction (v2.58) |
| 42 | 다시 분석 | handleRun | 위와 동일 |
| 43 | 이전 분석 (toggle) | toggleHistory → listMemoryAnalysesAction | history list expand (v2.58) |
| 44+ | 검색 결과 카드 | <Link href="/legacy/{docId}"> | 사무실 기억 상세로 이동 (v2.62) |
Tab 컨텐츠 카드 (개요/서류/기일/대화 등) — 21개
| # | 위치 | 라벨 | onClick | 기대 effect |
|---|
| 45 | CaseSummaryCards | 다음 기일 카드 | onClick | hearings 탭 전환 |
| 46 | CaseSummaryCards | 청구금액 카드 | onClick | recoveries 탭 전환 |
| 47 | CaseFlowStageBanner | 다음액션 (동적) | onAction | 권장 액션 (탭/모달) |
| 48 | CaseNextActionsCard | 다음 행동 추천 | onClick | status 변경/탭 전환 |
| 49 | PostJudgmentActionsPanel | 판결후 액션 | onClick | 항소/집행 액션 |
| 50 | CaseDetailClient | 서류 생성 (탭 내) | setShowDocGenerate(true) | InlineDocGenerate 모달 |
| 51 | CaseDetailClient | 업로드 | setShowDocUpload(true) | CaseDocUploadModal |
| 52 | RelatedCasesSection | 연결 | DialogTrigger | 관련사건 추가 dialog |
| 53 | ClientDocChecklistPanel | 체크리스트 항목 | handleClick | 문서 수집 상태 토글 |
| 54 | CaseComments | 메모 전송 | handleSend | Firestore mutation: comments add |
| 55+ | 기일 row 액션 | (행별로 다양) | 결과 입력/수정/삭제 | hearing mutations |
기타 ARIA / 정보성 — 2개
| # | 라벨 | 동작 | 기대 effect |
|---|
| 64 | ℹ️ 상태 안내 | TooltipTrigger | 사건 상태 설명 툴팁 |
| 65 | ℹ️ 흐름 단계 안내 | TooltipTrigger | 9단계 흐름 설명 |
Contract 위반 회귀 가드 (정적 vitest)
각 핵심 버튼이 expected handler 와 정확히 연결되었는지 grep 검증.
검증 항목
- 헤더 7개 —
onClick={onPrintSummary}, onClick={onDelete}, onClick={onShowDocGenerate}, <Link href="/cases">, disabled={!data.prevId/nextId}, setPendingStatus
- 상태 confirm 9 — AlertDialog open + handleStatusConfirm 호출
- 탭 13개 — TabsTrigger value 명시 + handleTabChange 모바일 분기
- 편집/저장 23~25 — setEditing 분기 + form submit handler
- 포털 29~34 — Server Action 호출 명시 (createPortalTokenAction 등)
- AI 36~40 — handleGenerate / toggleHistory + 액션 호출
- RAG 41~44 — handleRun / toggleHistory + Link href 사무실 기억
본 SSoT 파일 자체도 정적 invariant 가 검증 (위 목록 수가 65인지 + 핵심 키워드 누락 X).