Skip to content

fix: 사건조회 UI 개선 및 AI 판결 플로우 버그 수정 - #95

Merged
evenif99 merged 24 commits into
devfrom
fix/dispute-page-ui
Jun 20, 2026
Merged

fix: 사건조회 UI 개선 및 AI 판결 플로우 버그 수정#95
evenif99 merged 24 commits into
devfrom
fix/dispute-page-ui

Conversation

@juahcheon

@juahcheon juahcheon commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • AI 모델 gemini-2.0-flash-lite 미지원 → gemini-2.5-flash로 변경 (moderation, meta 추출)
  • 진술 저장 후 AI 메타 추출 완료 전까지 스피너 유지 (statement 페이지 + disputes 페이지 폴링)
  • disputes/[id] 페이지: 제목이 "새 사건"인 동안 2초마다 폴링, 최대 15회 후 중단
  • (page) 그룹 공통 BottomNavigation 레이아웃 적용 (/statement 경로 제외)
  • rooms POST roomMode AI_ROOM 수정 및 에러 로깅 추가
  • Prisma 스키마 DB pull 동기화

Test plan

  • 새 사건 생성 → 카테고리 선택 → 정상 생성 확인
  • 진술 저장 시 스피너 표시 → AI 추출 완료 후 사건조회로 이동 확인
  • 사건조회 페이지에서 AI 추출 중 스피너 표시 → 완료 후 제목/요약 표시 확인
  • BottomNavigation: 홈/사건기록/마이페이지/사건조회에 표시, 사건작성에 미표시 확인

🤖 Generated with Claude Code

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 분쟁 상세에서 새 사건 메타 분석 진행 중 안내 스피너 및 자동 갱신(횟수 제한) 추가
    • 경로에 따라 하단 네비게이션 노출/숨김을 조건부로 적용
  • Bug Fixes

    • 진술 저장 처리 시 로딩/안내 표시 흐름 개선
    • 메타 추출 및 API 오류 상황에서 로깅/표시 정확도 개선
  • Chores

    • 데이터 스키마 정리 및 분쟁 상태값 확장
    • AI 메타 추출/콘텐츠 검증 모델 업그레이드

juahcheon and others added 19 commits June 20, 2026 12:40
- extractDisputeMeta 전용 모델을 gemini-2.0-flash-lite로 분리
- moderation 모델도 gemini-2.0-flash-lite로 변경
- 제목 30자→20자, 요약 100자→50자로 축소

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- PATCH /api/disputes/[id]/status 엔드포인트 추가
- closeDispute API 함수 및 useCloseDispute 훅 추가
- DisputePage 사건종료 버튼에 훅 연결 및 로딩/에러 처리

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 진술 제출 시 dispute 상태를 waiting_opponent로 업데이트
- fire-and-forget 방식으로 judge API 호출 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- AbortController 30초 타임아웃 방식으로 충돌 해결 (dev 기준)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- statement 제출 후 fire-and-forget judge 호출 제거
- 스피너를 DB status 기반이 아닌 isJudging (API 호출 중) 기준으로만 표시
- 판결 완료 후 query invalidation으로 자동 UI 전환

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- extractDisputeMeta fire-and-forget → await으로 변경 (title/summary 추출 완료 후 응답)
- 저장 중 fullscreen 스피너 화면 추가
- 중복 PATCH /status 호출 제거 (statements route에서 이미 처리)
- next/image 적용 및 카카오 이미지 도메인 허용 (next.config.ts)
- avatarFallback → 기본 이미지(thumbnail-default.png) 폴백
- categoryChip inline background-color 제거

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- StatementPage: savingContent 폭 반응형 처리 (min(100%, 362px))
- statements/route: extractDisputeMeta에 10초 타임아웃 추가
- status/route: 동일 상태 재요청 시 멱등 성공 반환
- judgment.ts: Array.from 기반 유니코드 안전 문자열 절단

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
talky-owl Ready Ready Preview, Comment Jun 20, 2026 11:22am

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 2901bd32-1869-4ae1-bf14-346002981891

📥 Commits

Reviewing files that changed from the base of the PR and between 0b8248b and 975fb20.

📒 Files selected for processing (1)
  • prisma/schema.prisma

📝 Walkthrough

Walkthrough

Prisma 스키마에서 calendarRecords 관계 필드 전체와 AuditLog 모델이 제거되었으며 DisputeStatus enum이 확장되었습니다. useDispute 훅에 refetchInterval 옵션이 추가되어 DisputePage에서 메타 추출 중 조건부 폴링 및 전용 로딩 화면을 구현합니다. BottomNavigation이 레이아웃 수준에서 경로 기반으로 중앙화되어 조건부 관리되도록 변경되었으며, mypagerecords 페이지에서 개별 렌더링이 제거됩니다. AI 모델이 gemini-2.5-flash로 업그레이드되고 API 라우트의 에러 로깅이 개선되었습니다.

Changes

Prisma 스키마 정리

Layer / File(s) Summary
calendarRecords 관계 필드 제거 및 AuditLog 모델 삭제
prisma/schema.prisma
User, DisputeRoom, RoomAiConversation, Dispute, EmotionDiary 모델에서 calendarRecords 관계 필드를 삭제하고, AuditLog 모델 전체를 스키마에서 제거하며, DisputeStatus enum에 a_submitted 값을 추가합니다.

분쟁 메타 추출 폴링 및 진술 저장 흐름

Layer / File(s) Summary
useDispute 훅 refetchInterval 옵션 추가
src/domains/dispute/dispute.hooks.ts
useDispute 시그니처에 options?: Pick<UseQueryOptions<DisputeDto>, 'refetchInterval'> 인자를 추가하고 useQuery에 해당 값을 전달합니다.
DisputePage 메타 추출 폴링 및 isExtractingMeta 렌더링
src/app/(page)/disputes/[id]/page.tsx
pollCountRefMAX_POLL(15회)로 폴링을 제한하며, 새 사건 + role_a 진술 존재 + 미완료 조건에서만 자동 재조회를 활성화합니다. isExtractingMeta가 참이면 META_MESSAGES를 2500ms 주기로 회전하며 "사건 정보를 분석 중" 스피너를 조기 반환합니다.
진술 저장 handleSave isLoading 세분화
src/app/(page)/disputes/[id]/statement/page.tsx
finally 블록을 제거하고 실패·개인정보 경고 분기에서만 setIsLoading(false)를 명시 호출하며, 성공 경로에서는 router.push 이동 시점까지 스피너를 유지합니다.

BottomNavigation 중앙화 및 개별 페이지 제거

Layer / File(s) Summary
PageLayout 클라이언트 전환 및 BottomNavigation 조건부 렌더링
src/app/(page)/layout.tsx, src/app/(page)/mypage/page.tsx, src/app/(page)/records/page.tsx
layout.tsx'use client'로 전환되어 usePathname()으로 경로를 읽고 /statement로 끝나거나 /join/, /login, /auth/, /terms, /privacy로 시작하는 경우에만 BottomNavigation을 숨기며, mypagerecords 페이지에서 개별 BottomNavigation 렌더링 및 import가 제거됩니다.

AI 모델 업그레이드 및 에러 로깅 개선

Layer / File(s) Summary
Gemini 모델 업그레이드 및 에러 로깅 개선
src/lib/ai/judgment.ts, src/lib/ai/moderation.ts, src/app/api/disputes/[id]/statements/route.ts, src/app/api/rooms/route.ts
META_MODELMODEL_NAMEgemini-2.5-flash로 업그레이드하고, extractDisputeMeta 실패 로깅에서 Error 여부에 따른 메시지 추출 방식과 rooms POST 핸들러의 catch 에러 로깅을 개선합니다.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • I5-Project/TALKY-OWL#91: disputes/[id]/page.tsxdisputes/[id]/statement/page.tsx에서 사건 진행 흐름, 폴링, 로딩 상태 처리를 동일하게 수정하여 코드 레벨에서 직접 겹칩니다.
  • I5-Project/TALKY-OWL#79: disputes/[id]/statement/page.tsxhandleSavejson.success/hasPersonalInfo 처리 및 로딩 동작이 동일한 코드 경로에서 겹칩니다.
  • I5-Project/TALKY-OWL#70: 본 PR의 src/lib/ai/judgment.ts Gemini 모델 변경이 해당 PR의 extractDisputeMeta 구현 및 폴링 로직과 코드 레벨에서 직접 연결됩니다.

Suggested reviewers

  • evenif99
  • wjdalss21

🐇 스키마를 가볍게 다듬고,
폴링은 열다섯 번으로 딱 맞춰~
스피너는 페이지 떠날 때까지 꾹!
네비는 레이아웃에서 한 번에 쏙,
Gemini는 2.5로 훌쩍 올라갔네.
토끼도 코드도 더 똑똑해졌다 🦉✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning PR 설명이 주요 변경사항 요약과 테스트 계획을 포함하고 있으나, 템플릿의 필수 섹션(작업 내용, 담당 작업 영역, 변경 사항 상세, 테스트 결과 체크, 작업 범위 확인 등)이 대부분 미작성되어 템플릿 준수 수준이 낮습니다. 저장소의 PR 설명 템플릿을 따라 필수 섹션을 모두 작성하세요. 특히 작업 내용 상세화, 담당 영역 체크, 관련 이슈/요구사항 기입, 테스트 결과 체크 완료가 필요합니다.
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항(AI 모델 업데이트, 진술 저장 플로우 개선, 사건조회 페이지 폴링, BottomNavigation 레이아웃 적용, DB 스키마 동기화)을 포괄적으로 요약하고 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dispute-page-ui

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
prisma/schema.prisma (1)

30-39: ⚠️ Potential issue | 🔴 Critical

auditLog 모델 부재로 인한 런타임 에러 발생 — 즉시 수정 필요

스키마에서 AuditLog 모델이 제거되었으나, src/app/api/user/me/route.ts:307에서 여전히 prisma.auditLog.create()를 호출하고 있습니다. 이는 사용자 계정 삭제 엔드포인트에서 직접 런타임 에러를 야기합니다. 동시에 docs/API_SPEC.md에는 AuditLog 기록 정책(라인 466, 583, 666, 919 등)과 CalendarRecord 생성 정책(라인 465)이 여전히 기술되어 있습니다. 스키마에서 모델을 제거한 경우, 이를 참조하는 모든 코드와 문서를 함께 정리해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prisma/schema.prisma` around lines 30 - 39, The AuditLog model has been
removed from the Prisma schema, but the code in src/app/api/user/me/route.ts
still contains a call to prisma.auditLog.create() which will cause a runtime
error. Remove the prisma.auditLog.create() call from the user account deletion
endpoint logic. Additionally, update docs/API_SPEC.md to remove all references
to AuditLog logging policies and CalendarRecord creation policies that are no
longer supported by the schema (review lines 465, 466, 583, 666, 919 and any
other mentions of these removed functionalities).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@prisma/schema.prisma`:
- Around line 451-452: The `a_submitted` enum value in the dispute status enum
violates both naming conventions and the state machine contract. It lacks a
`@map` annotation that other enum values have (violating camelCase + `@map` naming
rules), and more critically, it is never referenced in any code and is not part
of the documented state transition flow (draft → waiting_opponent →
opponent_joined → both_submitted → judging → judged → closed/expired/deleted).
Remove the `a_submitted` line entirely from the enum definition in the Prisma
schema since it represents a dead state that should not exist.

In `@src/app/`(page)/disputes/[id]/page.tsx:
- Around line 45-47: When polling reaches MAX_POLL and stops (line 45-47 where
it returns false), the isExtractingMeta state is not being updated to reflect
this termination. This causes the spinner in the early return condition (lines
109-119) to continue displaying indefinitely even after polling has stopped.
Update the pollInterval callback that checks MAX_POLL to also set
isExtractingMeta to false when polling is terminated, ensuring the UI state
stays synchronized with the actual polling status.

In `@src/domains/dispute/dispute.hooks.ts`:
- Around line 10-15: The `refetchInterval` property type in the options
parameter of the `useDispute` function is incomplete. The current type
declaration only includes `number | false`, but TanStack React Query v5 also
supports a function form that accepts a query object and returns a number or
false. Extend the type definition of the `refetchInterval` property in the
options object to include the function form signature alongside the existing
number and false types to match the actual usage in disputes/[id]/page.tsx and
resolve the TypeScript error.

---

Outside diff comments:
In `@prisma/schema.prisma`:
- Around line 30-39: The AuditLog model has been removed from the Prisma schema,
but the code in src/app/api/user/me/route.ts still contains a call to
prisma.auditLog.create() which will cause a runtime error. Remove the
prisma.auditLog.create() call from the user account deletion endpoint logic.
Additionally, update docs/API_SPEC.md to remove all references to AuditLog
logging policies and CalendarRecord creation policies that are no longer
supported by the schema (review lines 465, 466, 583, 666, 919 and any other
mentions of these removed functionalities).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 48b50560-a6f6-4fde-9ce1-269e1c7be7d9

📥 Commits

Reviewing files that changed from the base of the PR and between c61d04e and b82eb58.

📒 Files selected for processing (11)
  • prisma/schema.prisma
  • src/app/(page)/disputes/[id]/page.tsx
  • src/app/(page)/disputes/[id]/statement/page.tsx
  • src/app/(page)/layout.tsx
  • src/app/(page)/mypage/page.tsx
  • src/app/(page)/records/page.tsx
  • src/app/api/disputes/[id]/statements/route.ts
  • src/app/api/rooms/route.ts
  • src/domains/dispute/dispute.hooks.ts
  • src/lib/ai/judgment.ts
  • src/lib/ai/moderation.ts
💤 Files with no reviewable changes (2)
  • src/app/(page)/mypage/page.tsx
  • src/app/(page)/records/page.tsx

Comment thread prisma/schema.prisma Outdated
Comment thread src/app/(page)/disputes/[id]/page.tsx Outdated
Comment thread src/domains/dispute/dispute.hooks.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(page)/layout.tsx:
- Around line 8-14: The hideNav variable definition is missing checks for the
root `/join` and `/auth` paths because the current conditions use
`startsWith('/join/')` and `startsWith('/auth/')` which require a trailing
slash. Add additional `pathname.startsWith()` checks in the hideNav variable to
also match `/join` and `/auth` without the trailing slashes, ensuring the
navigation is properly hidden for both the root paths and their child routes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: a649ec8c-ddf6-41d7-87c3-c77ded1cbbe4

📥 Commits

Reviewing files that changed from the base of the PR and between b82eb58 and 0b8248b.

📒 Files selected for processing (4)
  • prisma/schema.prisma
  • src/app/(page)/disputes/[id]/page.tsx
  • src/app/(page)/layout.tsx
  • src/domains/dispute/dispute.hooks.ts
💤 Files with no reviewable changes (1)
  • prisma/schema.prisma
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/domains/dispute/dispute.hooks.ts
  • src/app/(page)/disputes/[id]/page.tsx

Comment thread src/app/(page)/layout.tsx
Comment on lines +8 to +14
const hideNav =
pathname.endsWith('/statement') ||
pathname.startsWith('/join/') ||
pathname.startsWith('/login') ||
pathname.startsWith('/auth/') ||
pathname.startsWith('/terms') ||
pathname.startsWith('/privacy')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

/join, /auth 루트 경로가 hide 조건에서 누락됩니다.

Line 10, Line 12의 startsWith('/join/'), startsWith('/auth/')는 각각 /join, /auth를 포함하지 않아 하단 내비가 의도치 않게 노출될 수 있습니다.

수정 제안
   const hideNav =
     pathname.endsWith('/statement') ||
-    pathname.startsWith('/join/') ||
+    pathname === '/join' ||
+    pathname.startsWith('/join/') ||
     pathname.startsWith('/login') ||
-    pathname.startsWith('/auth/') ||
+    pathname === '/auth' ||
+    pathname.startsWith('/auth/') ||
     pathname.startsWith('/terms') ||
     pathname.startsWith('/privacy')

근거: PR 목표에 숨김 대상 경로가 /join, /login, /auth, /terms, /privacy로 명시되어 있습니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(page)/layout.tsx around lines 8 - 14, The hideNav variable
definition is missing checks for the root `/join` and `/auth` paths because the
current conditions use `startsWith('/join/')` and `startsWith('/auth/')` which
require a trailing slash. Add additional `pathname.startsWith()` checks in the
hideNav variable to also match `/join` and `/auth` without the trailing slashes,
ensuring the navigation is properly hidden for both the root paths and their
child routes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants