feat: 판결 결과 페이지 구현 (판결/유형 탭, JudgmentResult, JudgmentTypeResult) - #90
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DisputePage: 판결/유형 서브탭(Tab 공통컴포넌트) 추가 - JudgmentResult: 이미지 기준 UI 재구성, nickname 적용 - JudgmentTypeResult: 유형탭 컴포넌트 신규 생성 (카드이미지, ActionPrompt) - Tab.module.scss: w60 h36 사이즈 조정 - DisputeParticipantDto: nickname 필드 추가 - disputes/[id]/route: nickname 조회 추가 - judgment.mapper: cardImageUrl 추가 - types/judgment: ConflictTypeDetailDto에 cardImageUrl 추가 - auth/index: 카카오 로그인 시 profileImageUrl 저장 - page.module.scss: diaryBox max-width 제거 - NewCaseButton: AbortController timeout 30s 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>
…ature/judgement-result
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthrough분쟁 상세 페이지에서 판결 완료/종료 상태에만 판결 결과 데이터를 로딩하고, 판결/유형 서브탭을 통해 렌더링합니다. 참여자의 실명과 프로필 이미지 URL이 API 응답에 포함되며, 카카오 로그인 시 프로필 이미지가 저장됩니다. Changes판결 결과 렌더링 및 연관 인프라
Sequence Diagram(s)sequenceDiagram
participant User as 사용자
participant DisputePage as DisputePage
participant useJudgment as useJudgment 훅
participant ResultAPI as /api/disputes/[id]/result
participant JudgmentResult as JudgmentResult
participant JudgmentTypeResult as JudgmentTypeResult
User->>DisputePage: 판결 탭 클릭 (judged/closed 상태)
DisputePage->>useJudgment: useJudgment(id, isCompleted=true)
useJudgment->>ResultAPI: GET /api/disputes/${id}/result
ResultAPI-->>useJudgment: AiJudgmentDto
useJudgment-->>DisputePage: judgment, judgmentLoading
alt judgmentLoading
DisputePage-->>User: 로딩 스피너 표시
else judgment 존재
DisputePage->>DisputePage: 판결/유형 서브탭 렌더링
alt 판결 서브탭
DisputePage->>JudgmentResult: judgment, participants 전달
JudgmentResult-->>User: 잘못 카드 + 화해 제안 표시
else 유형 서브탭
DisputePage->>JudgmentTypeResult: judgment, participants 전달
JudgmentTypeResult-->>User: 유형 카드 이미지 + 액션 표시
end
else judgment 없음
DisputePage-->>User: 빈 결과 메시지
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
| type DisputeForDetail = Prisma.DisputeGetPayload<{ | ||
| include: { | ||
| participants: { include: { user: { select: { profileImageUrl: true } } } } | ||
| participants: { include: { user: { select: { nickname: true; profileImageUrl: true } } } } |
There was a problem hiding this comment.
nickname 쓰나요? name 안쓰고?!
There was a problem hiding this comment.
아 네임이에요?? 저 닉네임인줄 알았습니다 수정하도록 하겠습니다 ㅎㅎ
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (3)
src/components/judgement/JudgmentTypeResult.tsx (1)
23-29: 💤 Low value공유/다운로드 기능이 placeholder로 구현되어 있습니다.
현재 두 핸들러 모두 "준비 중" 토스트만 표시합니다. 향후 실제 구현이 필요하며, 이슈 트래커에 등록되어 있는지 확인하세요.
실제 기능 구현을 위한 이슈를 생성하거나 구현 가이드가 필요하시면 도와드릴 수 있습니다.
🤖 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/components/judgement/JudgmentTypeResult.tsx` around lines 23 - 29, The handleShare and handleDownload functions in JudgmentTypeResult.tsx are currently placeholder implementations that only show toast messages. Replace these placeholder implementations with actual share and download functionality. Verify whether tracking issues or tickets exist for these features, and implement the real share and download capabilities based on the project requirements. If implementation details are unclear, consult with the team on the expected behavior before implementing.src/components/judgement/JudgmentResult.tsx (1)
13-22: ⚡ Quick win고정 크기 아바타에는 명시적 width/height 사용을 권장합니다.
현재
width={0} height={0} sizes="100vw"패턴은 반응형 이미지에 적합하지만, 아바타는 CSS에서 24x24 고정 크기로 렌더링됩니다. Next.js Image 컴포넌트에 명시적 치수를 지정하면 레이아웃 시프트를 방지하고 최적화된 이미지 크기를 선택할 수 있습니다.♻️ 제안하는 수정
function Avatar({ src }: { src: string | null }) { return ( <div className={styles.avatar}> {src - ? <Image src={src} alt="" width={0} height={0} sizes="100vw" className={styles.avatarImg} /> + ? <Image src={src} alt="" width={24} height={24} className={styles.avatarImg} /> : <div className={styles.avatarFallback} /> } </div> ) }🤖 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/components/judgement/JudgmentResult.tsx` around lines 13 - 22, The Avatar component in JudgmentResult.tsx uses width={0} height={0} sizes="100vw" pattern which is designed for responsive images, but since the avatar is rendered at a fixed 24x24 size in CSS, explicit width and height values should be specified instead. Update the Image component by replacing width={0} height={0} sizes="100vw" with explicit width={24} height={24}, and remove the sizes prop, which is only needed for responsive images. This will prevent layout shifts and allow Next.js to optimize the image properly for the fixed avatar dimensions.src/domains/judgement/judgement.api.ts (1)
4-11: ⚖️ Poor tradeoff타입 안정성 개선을 고려해보세요.
JSON.parse(text) as ApiResponse<T>캐스팅은 런타임에 서버가 예상과 다른 구조를 반환할 경우 타입 불일치 문제를 발생시킬 수 있습니다. Zod와 같은 런타임 검증 라이브러리를 사용하면 더 안전하게 처리할 수 있습니다.현재 구현도 일반적인 패턴이며 동작은 하지만, 향후 개선 시 고려해보시기 바랍니다.
🤖 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/domains/judgement/judgement.api.ts` around lines 4 - 11, The parseJson function uses an unsafe type cast `as ApiResponse<T>` on the parsed JSON data, which does not validate that the runtime structure actually matches the expected ApiResponse<T> type. Instead of relying on a type assertion, implement runtime validation using a library like Zod to create a schema that validates the JSON response structure before casting. This ensures that if the server returns data in an unexpected format, you will catch the validation error rather than silently accepting mistyped data.
🤖 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 `@next.config.ts`:
- Around line 20-22: The current configuration allows HTTP protocol for the
hostname k.kakaocdn.net in the Next.js image configuration, but Kakao's official
API documentation only supports HTTPS for profile image URLs. Remove the HTTP
protocol entry for k.kakaocdn.net in the next.config.ts file, as HTTP endpoints
are not officially supported by Kakao and should not be used.
In `@src/app/`(page)/disputes/[id]/page.tsx:
- Around line 41-43: The isCompleted variable calculation checks for undefined
but not null, which can cause a runtime crash when dispute is null and
dispute.status is accessed. Replace the condition checking dispute !== undefined
with a proper null-safety check that handles both null and undefined cases, such
as using dispute != null or dispute && before accessing dispute.status in the
boolean expression.
In `@src/components/judgement/JudgmentResult.module.scss`:
- Line 88: The stylelint rule `declaration-empty-line-before` requires blank
lines before CSS declarations in certain contexts. Add a blank line before each
of the three color declarations (at the original lines 88, 93, and 100 in the
JudgmentResult.module.scss file) to comply with this formatting rule. Place an
empty line directly before each `color: v.$color-black-400;` statement and any
other declarations that need this spacing.
In `@src/components/judgement/JudgmentTypeResult.module.scss`:
- Line 14: The stylelint rule `declaration-empty-line-before` requires a blank
line to precede property declarations within CSS blocks. Add an empty line
before the `color: v.$color-black-700;` declaration to comply with this
formatting rule. The same issue also appears at another location in the file
(line 42), so apply the same fix there as well by adding a blank line before
that declaration.
In `@src/lib/auth/index.ts`:
- Around line 132-138: The prisma.user.update call within the profileImageUrl
backfill logic (checking !existing.profileImageUrl && user.image) is not wrapped
in error handling. If the database update fails, the exception will propagate
and block the entire authentication flow. Wrap the prisma.user.update operation
in a try-catch block to gracefully handle any database errors, log the error if
needed, but allow the authentication to continue and return true since profile
image backfill is not a critical operation for login success.
---
Nitpick comments:
In `@src/components/judgement/JudgmentResult.tsx`:
- Around line 13-22: The Avatar component in JudgmentResult.tsx uses width={0}
height={0} sizes="100vw" pattern which is designed for responsive images, but
since the avatar is rendered at a fixed 24x24 size in CSS, explicit width and
height values should be specified instead. Update the Image component by
replacing width={0} height={0} sizes="100vw" with explicit width={24}
height={24}, and remove the sizes prop, which is only needed for responsive
images. This will prevent layout shifts and allow Next.js to optimize the image
properly for the fixed avatar dimensions.
In `@src/components/judgement/JudgmentTypeResult.tsx`:
- Around line 23-29: The handleShare and handleDownload functions in
JudgmentTypeResult.tsx are currently placeholder implementations that only show
toast messages. Replace these placeholder implementations with actual share and
download functionality. Verify whether tracking issues or tickets exist for
these features, and implement the real share and download capabilities based on
the project requirements. If implementation details are unclear, consult with
the team on the expected behavior before implementing.
In `@src/domains/judgement/judgement.api.ts`:
- Around line 4-11: The parseJson function uses an unsafe type cast `as
ApiResponse<T>` on the parsed JSON data, which does not validate that the
runtime structure actually matches the expected ApiResponse<T> type. Instead of
relying on a type assertion, implement runtime validation using a library like
Zod to create a schema that validates the JSON response structure before
casting. This ensures that if the server returns data in an unexpected format,
you will catch the validation error rather than silently accepting mistyped
data.
🪄 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: 91a024ee-0fa0-4c51-b20e-d40881e949ee
⛔ Files ignored due to path filters (3)
docs/screenshots/common-components-test.pngis excluded by!**/*.png판결 결과(1인).pngis excluded by!**/*.png판결 결과(2인).pngis excluded by!**/*.png
📒 Files selected for processing (18)
next.config.tssrc/app/(page)/disputes/[id]/DisputePage.module.scsssrc/app/(page)/disputes/[id]/page.tsxsrc/app/api/disputes/[id]/route.tssrc/app/api/disputes/route.tssrc/app/api/personal-analyses/.gitkeepsrc/components/home/NewCaseButton.tsxsrc/components/judgement/JudgmentResult.module.scsssrc/components/judgement/JudgmentResult.tsxsrc/components/judgement/JudgmentTypeResult.module.scsssrc/components/judgement/JudgmentTypeResult.tsxsrc/components/ui/StatusBadge.tsxsrc/components/ui/Tab.module.scsssrc/domains/judgement/judgement.api.tssrc/domains/judgement/judgement.hooks.tssrc/domains/judgement/judgment.mapper.tssrc/lib/auth/index.tssrc/types/judgment.ts
💤 Files with no reviewable changes (2)
- src/app/api/disputes/route.ts
- src/components/home/NewCaseButton.tsx
|
|
||
| .title { | ||
| @include m.text-title-s; | ||
| color: v.$color-black-700; |
There was a problem hiding this comment.
Stylelint 포맷팅 규칙을 준수하세요.
선언문 앞에 빈 줄을 추가하여 declaration-empty-line-before 규칙을 만족시키세요.
🎨 제안하는 수정
.title {
`@include` m.text-title-s;
+
color: v.$color-black-700;
}
.fallbackText {
`@include` m.text-title-m;
+
color: v.$color-black-400;
}Also applies to: 42-42
🧰 Tools
🪛 Stylelint (17.13.0)
[error] 14-14: Expected empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 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/components/judgement/JudgmentTypeResult.module.scss` at line 14, The
stylelint rule `declaration-empty-line-before` requires a blank line to precede
property declarations within CSS blocks. Add an empty line before the `color:
v.$color-black-700;` declaration to comply with this formatting rule. The same
issue also appears at another location in the file (line 42), so apply the same
fix there as well by adding a blank line before that declaration.
Source: Linters/SAST tools
| ) | ||
| } | ||
|
|
||
| export default function JudgmentResult({ judgment, participants }: Props) { |
There was a problem hiding this comment.
이 페이지도 마찬가지로, 지금 props로 받아오고 있는데 이렇게 되면 새로고침시 데이터가 다 날라가요. 그래서
props로 넘겨주는 거보다 그냥 id를 기준으로 페이지 진입시 get API를 호출하는 것이 안전합니다.
| import type { DisputeParticipantDto } from '@/types/dispute' | ||
| import styles from './JudgmentTypeResult.module.scss' | ||
|
|
||
| interface Props { |
| export async function fetchJudgment(disputeId: string): Promise<AiJudgmentDto> { | ||
| const res = await fetch(`/api/disputes/${disputeId}/result`) | ||
| const json = await parseJson<AiJudgmentDto>(res, '판결 결과 조회 실패') | ||
| if (!json.success || !json.data) throw new Error(json.error?.message ?? '판결 결과 조회 실패') |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- participants nickname → name으로 변경 (DTO, route, 컴포넌트, useActiveCases) - next.config: 카카오 HTTP 패턴 제거 (HTTPS만 허용) - DisputePage: isCompleted null 케이스 처리 (!!dispute) - JudgmentResult.module.scss: declaration-empty-line-before stylelint 수정 - JudgmentTypeResult.module.scss: 동일 stylelint 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/app/api/disputes/route.ts (1)
25-27:⚠️ Potential issue | 🟠 Major | ⚡ Quick win활성 사건 목록 응답에서 참여자 이름이 항상
null로 고정됩니다Line 35에서
name을null로 고정하고, Line 26/118/237에서user.name을 조회하지 않아participants[].name이 실제로 채워지지 않습니다. 현재src/hooks/useActiveCases.ts가p.name을 사용하도록 바뀐 상태라, 이름 표시 요구사항이 목록 API에서 끊깁니다.🔧 제안 수정안
type DisputeForList = Prisma.DisputeGetPayload<{ - include: { participants: { include: { user: { select: { profileImageUrl: true } } } } } + include: { participants: { include: { user: { select: { name: true; profileImageUrl: true } } } } } }> ... function toParticipantDto(p: DisputeForList['participants'][number]): DisputeParticipantDto { return { ... - name: null, + name: p.user.name ?? null, profileImageUrl: p.user.profileImageUrl ?? null, ... } } ... prisma.dispute.findMany({ where, - include: { participants: { include: { user: { select: { profileImageUrl: true } } } } }, + include: { participants: { include: { user: { select: { name: true, profileImageUrl: true } } } } }, ... await tx.disputeParticipant.create({ data: { disputeId: created.id, userId, role: 'ROLE_A' }, }) return tx.dispute.findUniqueOrThrow({ where: { id: created.id }, - include: { participants: { include: { user: { select: { profileImageUrl: true } } } } }, + include: { participants: { include: { user: { select: { name: true, profileImageUrl: true } } } } }, })Also applies to: 35-36, 118-118, 237-237
🤖 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/api/disputes/route.ts` around lines 25 - 27, The DisputeForList type definition does not include the user name field in its select statement, only profileImageUrl, which means participant names are not being fetched from the database. Additionally, the name field is being hardcoded to null on line 35 instead of being populated from the user data. Fix this by adding name: true to the user select statement within the include object of the DisputeForList type definition (around line 26), and then update line 35 to populate the name field from the actual user.name value instead of null. Also verify and apply the same fixes at lines 118 and 237 where similar issues occur.
🤖 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.
Outside diff comments:
In `@src/app/api/disputes/route.ts`:
- Around line 25-27: The DisputeForList type definition does not include the
user name field in its select statement, only profileImageUrl, which means
participant names are not being fetched from the database. Additionally, the
name field is being hardcoded to null on line 35 instead of being populated from
the user data. Fix this by adding name: true to the user select statement within
the include object of the DisputeForList type definition (around line 26), and
then update line 35 to populate the name field from the actual user.name value
instead of null. Also verify and apply the same fixes at lines 118 and 237 where
similar issues occur.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 438eb579-d130-4bb4-b9fc-4a75105f3bfc
📒 Files selected for processing (11)
next.config.tssrc/app/(page)/disputes/[id]/page.tsxsrc/app/api/disputes/[id]/route.tssrc/app/api/disputes/route.tssrc/components/judgement/JudgmentResult.module.scsssrc/components/judgement/JudgmentResult.tsxsrc/components/judgement/JudgmentTypeResult.module.scsssrc/components/judgement/JudgmentTypeResult.tsxsrc/hooks/useActiveCases.tssrc/lib/auth/index.tssrc/types/dispute.ts
💤 Files with no reviewable changes (1)
- next.config.ts
✅ Files skipped from review due to trivial changes (1)
- src/components/judgement/JudgmentResult.module.scss
🚧 Files skipped from review as they are similar to previous changes (5)
- src/components/judgement/JudgmentTypeResult.module.scss
- src/components/judgement/JudgmentTypeResult.tsx
- src/components/judgement/JudgmentResult.tsx
- src/app/(page)/disputes/[id]/page.tsx
- src/lib/auth/index.ts
- JudgmentResult/JudgmentTypeResult: props 대신 disputeId 기반 직접 API 호출 (새로고침 시 데이터 유실 방지, TanStack Query 캐시로 중복 요청 없음) - DisputePage: judgment/participants props 제거, isError 기반 에러 처리 - auth/index.ts: 프로필 이미지 백필 try-catch 감싸기 (실패 시 로그인 차단 방지) - judgement.api.ts: 에러 메시지 사용자 친화적으로 개선 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@evenif99 저 PR 코멘트까지 다 업데이트했습니다 ! |
* feat: 판결 결과 컴포넌트 및 도메인 로직 초기 작업 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 판결 결과 페이지 구현 (#판결탭/유형탭/UI) - DisputePage: 판결/유형 서브탭(Tab 공통컴포넌트) 추가 - JudgmentResult: 이미지 기준 UI 재구성, nickname 적용 - JudgmentTypeResult: 유형탭 컴포넌트 신규 생성 (카드이미지, ActionPrompt) - Tab.module.scss: w60 h36 사이즈 조정 - DisputeParticipantDto: nickname 필드 추가 - disputes/[id]/route: nickname 조회 추가 - judgment.mapper: cardImageUrl 추가 - types/judgment: ConflictTypeDetailDto에 cardImageUrl 추가 - auth/index: 카카오 로그인 시 profileImageUrl 저장 - page.module.scss: diaryBox max-width 제거 - NewCaseButton: AbortController timeout 30s Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: next.config에 Supabase Storage 및 카카오 이미지 도메인 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: JudgmentResult Avatar img 태그를 next/image로 교체 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 리뷰 반영 - participants nickname → name으로 변경 (DTO, route, 컴포넌트, useActiveCases) - next.config: 카카오 HTTP 패턴 제거 (HTTPS만 허용) - DisputePage: isCompleted null 케이스 처리 (!!dispute) - JudgmentResult.module.scss: declaration-empty-line-before stylelint 수정 - JudgmentTypeResult.module.scss: 동일 stylelint 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 추가 리뷰 반영 - JudgmentResult/JudgmentTypeResult: props 대신 disputeId 기반 직접 API 호출 (새로고침 시 데이터 유실 방지, TanStack Query 캐시로 중복 요청 없음) - DisputePage: judgment/participants props 제거, isError 기반 에러 처리 - auth/index.ts: 프로필 이미지 백필 try-catch 감싸기 (실패 시 로그인 차단 방지) - judgement.api.ts: 에러 메시지 사용자 친화적으로 개선 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: 불필요한 스크린샷 PNG 파일 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: CalendarRecord 모델 제거 및 EmotionDiary title 필드 추가 - CalendarRecord 모델 및 CalendarRecordType enum 제거 - User, DisputeRoom, RoomAiConversation, Dispute에서 calendarRecords relation 제거 - EmotionDiary에 title 필드 추가 (VarChar 200) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 페이지 API 연동 - GET /api/disputes에 completed=true 쿼리 파라미터 추가 (judged/closed 필터링) - fetchCompletedCases, useCompletedCases 추가 (카테고리 필터 + 최신순) - RecordListSection 더미 데이터 제거, 실제 API 연동 - 사건 박스 클릭 시 /disputes/{id}로 이동 (기존 Link 구조 유지) - 로딩/에러/빈 상태 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 빈 상태 UI 개선 - 빈 상태 텍스트 → '등록한 사건이 없어요' - character-case.png 이미지 + 텍스트 중앙 배치 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건박스 공통 컴포넌트 CaseRecordCard 분리 - CaseRecordCard 신규 생성 (src/components/ui) - MUI AvatarGroup으로 1인/2인 참여자 프로필 겹침 표시 - RecordListSection에서 CaseRecordCard 사용하도록 교체 - 카드 스타일 RecordListSection.module.scss → CaseRecordCard.module.scss로 이동 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카카오 CDN http 프로토콜 이미지 허용 (img1.kakaocdn.net) 카카오 기본 프로필 이미지 URL이 http로 오는 경우가 있어 *.kakaocdn.net http 패턴 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 홈 페이지 배경 그라데이션 추가 (primary-200 → white) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 홈 그라데이션 범위 15%로 조정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 import 충돌 사전 해결 - UseQueryOptions, DisputeDto import 추가 (dev 브랜치 기준) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 useDispute refetchInterval 옵션 반영 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 및 juacheon 리뷰 반영 - disputes/route.ts: active/completed 동시 사용 시 if/else 분기로 필터 충돌 방지 - CaseRecordCard: <time> 요소에 dateTime 속성 추가 (접근성) - Header: transparent prop 추가, :global(header) 셀렉터 제거 - RecordListSection: 에러 메시지 구체화 - next.config.ts: 중복 HTTP 항목 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: 판결 결과 컴포넌트 및 도메인 로직 초기 작업 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 판결 결과 페이지 구현 (#판결탭/유형탭/UI) - DisputePage: 판결/유형 서브탭(Tab 공통컴포넌트) 추가 - JudgmentResult: 이미지 기준 UI 재구성, nickname 적용 - JudgmentTypeResult: 유형탭 컴포넌트 신규 생성 (카드이미지, ActionPrompt) - Tab.module.scss: w60 h36 사이즈 조정 - DisputeParticipantDto: nickname 필드 추가 - disputes/[id]/route: nickname 조회 추가 - judgment.mapper: cardImageUrl 추가 - types/judgment: ConflictTypeDetailDto에 cardImageUrl 추가 - auth/index: 카카오 로그인 시 profileImageUrl 저장 - page.module.scss: diaryBox max-width 제거 - NewCaseButton: AbortController timeout 30s Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: next.config에 Supabase Storage 및 카카오 이미지 도메인 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: JudgmentResult Avatar img 태그를 next/image로 교체 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 리뷰 반영 - participants nickname → name으로 변경 (DTO, route, 컴포넌트, useActiveCases) - next.config: 카카오 HTTP 패턴 제거 (HTTPS만 허용) - DisputePage: isCompleted null 케이스 처리 (!!dispute) - JudgmentResult.module.scss: declaration-empty-line-before stylelint 수정 - JudgmentTypeResult.module.scss: 동일 stylelint 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 추가 리뷰 반영 - JudgmentResult/JudgmentTypeResult: props 대신 disputeId 기반 직접 API 호출 (새로고침 시 데이터 유실 방지, TanStack Query 캐시로 중복 요청 없음) - DisputePage: judgment/participants props 제거, isError 기반 에러 처리 - auth/index.ts: 프로필 이미지 백필 try-catch 감싸기 (실패 시 로그인 차단 방지) - judgement.api.ts: 에러 메시지 사용자 친화적으로 개선 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: 불필요한 스크린샷 PNG 파일 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: CalendarRecord 모델 제거 및 EmotionDiary title 필드 추가 - CalendarRecord 모델 및 CalendarRecordType enum 제거 - User, DisputeRoom, RoomAiConversation, Dispute에서 calendarRecords relation 제거 - EmotionDiary에 title 필드 추가 (VarChar 200) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 페이지 API 연동 - GET /api/disputes에 completed=true 쿼리 파라미터 추가 (judged/closed 필터링) - fetchCompletedCases, useCompletedCases 추가 (카테고리 필터 + 최신순) - RecordListSection 더미 데이터 제거, 실제 API 연동 - 사건 박스 클릭 시 /disputes/{id}로 이동 (기존 Link 구조 유지) - 로딩/에러/빈 상태 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 빈 상태 UI 개선 - 빈 상태 텍스트 → '등록한 사건이 없어요' - character-case.png 이미지 + 텍스트 중앙 배치 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건박스 공통 컴포넌트 CaseRecordCard 분리 - CaseRecordCard 신규 생성 (src/components/ui) - MUI AvatarGroup으로 1인/2인 참여자 프로필 겹침 표시 - RecordListSection에서 CaseRecordCard 사용하도록 교체 - 카드 스타일 RecordListSection.module.scss → CaseRecordCard.module.scss로 이동 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카카오 CDN http 프로토콜 이미지 허용 (img1.kakaocdn.net) 카카오 기본 프로필 이미지 URL이 http로 오는 경우가 있어 *.kakaocdn.net http 패턴 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 홈 페이지 배경 그라데이션 추가 (primary-200 → white) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 홈 그라데이션 범위 15%로 조정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 import 충돌 사전 해결 - UseQueryOptions, DisputeDto import 추가 (dev 브랜치 기준) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 useDispute refetchInterval 옵션 반영 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 및 juacheon 리뷰 반영 - disputes/route.ts: active/completed 동시 사용 시 if/else 분기로 필터 충돌 방지 - CaseRecordCard: <time> 요소에 dateTime 속성 추가 (접근성) - Header: transparent prop 추가, :global(header) 셀렉터 제거 - RecordListSection: 에러 메시지 구체화 - next.config.ts: 중복 HTTP 항목 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 2인 판결결과 점수 그래프 UI 수정 - isEqual/barEqual 제거, 색상 로직 ratioA >= ratioB 패턴으로 단순화 - scoreGraph margin-bottom 추가 - scoreAvatarImg 크기 명시적 fn.r(48)로 변경 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 2인 판결결과 그래프 디테일 수정 - 바 height 12 → 16, border-radius 6 → 4 - 중앙 실선 추가 (solid, border-strong, h36) - barDark 컬러 → status-disabled-text - scoreTitle 이름 부분만 bold 처리 - AI 고지 문구 컬러 → text-secondary Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 진술 탭 참여자 이름/MBTI 표시, 프로필 이미지 fallback 개선 - 진술 카드 레이블 A/B → 참여자 실명으로 변경 - 진술 카드 하단 프로필 이미지 + MBTI 추가 - DisputeParticipantDto에 mbti 필드 추가 - API participants에 mbti 포함 (disputes/[id] GET/PATCH) - profileImageUrl null 시 image 필드 fallback 적용 (목록/상세 API) - DisputePage.module.scss mixins import 추가 - JudgmentResult 그래프 점선/바 높이 디테일 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: JudgmentResult 참여자 이름 변수 통일 및 텍스트 치환 적용 - nameA / nameB 변수로 cardLabel, barLabel 통일 - replaceRoleNames 함수로 aFault/bFault/aSuggestedLine/bSuggestedLine 내 A님→실제이름 치환 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 리뷰 반영 - replaceRoleNames 단일 패스 치환으로 개선 (A님|B님 alternation) - disputes 목록/POST API Prisma 쿼리에 image 필드 선택 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: 판결 결과 컴포넌트 및 도메인 로직 초기 작업 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 판결 결과 페이지 구현 (#판결탭/유형탭/UI) - DisputePage: 판결/유형 서브탭(Tab 공통컴포넌트) 추가 - JudgmentResult: 이미지 기준 UI 재구성, nickname 적용 - JudgmentTypeResult: 유형탭 컴포넌트 신규 생성 (카드이미지, ActionPrompt) - Tab.module.scss: w60 h36 사이즈 조정 - DisputeParticipantDto: nickname 필드 추가 - disputes/[id]/route: nickname 조회 추가 - judgment.mapper: cardImageUrl 추가 - types/judgment: ConflictTypeDetailDto에 cardImageUrl 추가 - auth/index: 카카오 로그인 시 profileImageUrl 저장 - page.module.scss: diaryBox max-width 제거 - NewCaseButton: AbortController timeout 30s Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: next.config에 Supabase Storage 및 카카오 이미지 도메인 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: JudgmentResult Avatar img 태그를 next/image로 교체 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 리뷰 반영 - participants nickname → name으로 변경 (DTO, route, 컴포넌트, useActiveCases) - next.config: 카카오 HTTP 패턴 제거 (HTTPS만 허용) - DisputePage: isCompleted null 케이스 처리 (!!dispute) - JudgmentResult.module.scss: declaration-empty-line-before stylelint 수정 - JudgmentTypeResult.module.scss: 동일 stylelint 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 추가 리뷰 반영 - JudgmentResult/JudgmentTypeResult: props 대신 disputeId 기반 직접 API 호출 (새로고침 시 데이터 유실 방지, TanStack Query 캐시로 중복 요청 없음) - DisputePage: judgment/participants props 제거, isError 기반 에러 처리 - auth/index.ts: 프로필 이미지 백필 try-catch 감싸기 (실패 시 로그인 차단 방지) - judgement.api.ts: 에러 메시지 사용자 친화적으로 개선 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: 불필요한 스크린샷 PNG 파일 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: CalendarRecord 모델 제거 및 EmotionDiary title 필드 추가 - CalendarRecord 모델 및 CalendarRecordType enum 제거 - User, DisputeRoom, RoomAiConversation, Dispute에서 calendarRecords relation 제거 - EmotionDiary에 title 필드 추가 (VarChar 200) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 페이지 API 연동 - GET /api/disputes에 completed=true 쿼리 파라미터 추가 (judged/closed 필터링) - fetchCompletedCases, useCompletedCases 추가 (카테고리 필터 + 최신순) - RecordListSection 더미 데이터 제거, 실제 API 연동 - 사건 박스 클릭 시 /disputes/{id}로 이동 (기존 Link 구조 유지) - 로딩/에러/빈 상태 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 빈 상태 UI 개선 - 빈 상태 텍스트 → '등록한 사건이 없어요' - character-case.png 이미지 + 텍스트 중앙 배치 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건박스 공통 컴포넌트 CaseRecordCard 분리 - CaseRecordCard 신규 생성 (src/components/ui) - MUI AvatarGroup으로 1인/2인 참여자 프로필 겹침 표시 - RecordListSection에서 CaseRecordCard 사용하도록 교체 - 카드 스타일 RecordListSection.module.scss → CaseRecordCard.module.scss로 이동 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카카오 CDN http 프로토콜 이미지 허용 (img1.kakaocdn.net) 카카오 기본 프로필 이미지 URL이 http로 오는 경우가 있어 *.kakaocdn.net http 패턴 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 홈 페이지 배경 그라데이션 추가 (primary-200 → white) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 홈 그라데이션 범위 15%로 조정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 import 충돌 사전 해결 - UseQueryOptions, DisputeDto import 추가 (dev 브랜치 기준) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 useDispute refetchInterval 옵션 반영 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 및 juacheon 리뷰 반영 - disputes/route.ts: active/completed 동시 사용 시 if/else 분기로 필터 충돌 방지 - CaseRecordCard: <time> 요소에 dateTime 속성 추가 (접근성) - Header: transparent prop 추가, :global(header) 셀렉터 제거 - RecordListSection: 에러 메시지 구체화 - next.config.ts: 중복 HTTP 항목 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 2인 판결결과 점수 그래프 UI 수정 - isEqual/barEqual 제거, 색상 로직 ratioA >= ratioB 패턴으로 단순화 - scoreGraph margin-bottom 추가 - scoreAvatarImg 크기 명시적 fn.r(48)로 변경 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 2인 판결결과 그래프 디테일 수정 - 바 height 12 → 16, border-radius 6 → 4 - 중앙 실선 추가 (solid, border-strong, h36) - barDark 컬러 → status-disabled-text - scoreTitle 이름 부분만 bold 처리 - AI 고지 문구 컬러 → text-secondary Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 진술 탭 참여자 이름/MBTI 표시, 프로필 이미지 fallback 개선 - 진술 카드 레이블 A/B → 참여자 실명으로 변경 - 진술 카드 하단 프로필 이미지 + MBTI 추가 - DisputeParticipantDto에 mbti 필드 추가 - API participants에 mbti 포함 (disputes/[id] GET/PATCH) - profileImageUrl null 시 image 필드 fallback 적용 (목록/상세 API) - DisputePage.module.scss mixins import 추가 - JudgmentResult 그래프 점선/바 높이 디테일 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: JudgmentResult 참여자 이름 변수 통일 및 텍스트 치환 적용 - nameA / nameB 변수로 cardLabel, barLabel 통일 - replaceRoleNames 함수로 aFault/bFault/aSuggestedLine/bSuggestedLine 내 A님→실제이름 치환 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 리뷰 반영 - replaceRoleNames 단일 패스 치환으로 개선 (A님|B님 alternation) - disputes 목록/POST API Prisma 쿼리에 image 필드 선택 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf: statistics/categories API 빌드 시 DB 호출 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 카테고리 사건 2개 제한 및 사건기록 무한스크롤 - POST /api/rooms 카테고리당 진행중 사건 2개 초과 시 CATEGORY_LIMIT_EXCEEDED(422) 반환 - DisputeListResponse에 hasNext 필드 추가 - fetchCompletedCases 페이지 기반 API 호출로 전환 (limit 10) - useCompletedCases useInfiniteQuery로 전환 - RecordListSection IntersectionObserver 기반 무한스크롤 구현 - 모든 데이터 로드 시 '모든 데이터를 불러왔습니다' 표시 - NewCaseButton 카테고리 한도 초과 시 에러 모달 표시 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 리뷰 반영 - GET /api/disputes: completed 파라미터 where 조건 반영으로 hasNext 정확도 개선 - POST /api/disputes: 카테고리 한도 체크 추가 (직접 API 호출 우회 방지) - NewCaseButton: limitError 모달 표시 시 body 스크롤 잠금 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카테고리 한도 초과 에러 모달 UI 개선 - 기존 카테고리 패널 스타일 재사용 → 독립 검은 배경 센터 모달로 변경 - limitOverlay, limitModal, limitMessage, limitCloseButton 스타일 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카테고리 한도 에러 모달 메시지 줄바꿈 적용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: 판결 결과 컴포넌트 및 도메인 로직 초기 작업 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 판결 결과 페이지 구현 (#판결탭/유형탭/UI) - DisputePage: 판결/유형 서브탭(Tab 공통컴포넌트) 추가 - JudgmentResult: 이미지 기준 UI 재구성, nickname 적용 - JudgmentTypeResult: 유형탭 컴포넌트 신규 생성 (카드이미지, ActionPrompt) - Tab.module.scss: w60 h36 사이즈 조정 - DisputeParticipantDto: nickname 필드 추가 - disputes/[id]/route: nickname 조회 추가 - judgment.mapper: cardImageUrl 추가 - types/judgment: ConflictTypeDetailDto에 cardImageUrl 추가 - auth/index: 카카오 로그인 시 profileImageUrl 저장 - page.module.scss: diaryBox max-width 제거 - NewCaseButton: AbortController timeout 30s Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: next.config에 Supabase Storage 및 카카오 이미지 도메인 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: JudgmentResult Avatar img 태그를 next/image로 교체 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 리뷰 반영 - participants nickname → name으로 변경 (DTO, route, 컴포넌트, useActiveCases) - next.config: 카카오 HTTP 패턴 제거 (HTTPS만 허용) - DisputePage: isCompleted null 케이스 처리 (!!dispute) - JudgmentResult.module.scss: declaration-empty-line-before stylelint 수정 - JudgmentTypeResult.module.scss: 동일 stylelint 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 추가 리뷰 반영 - JudgmentResult/JudgmentTypeResult: props 대신 disputeId 기반 직접 API 호출 (새로고침 시 데이터 유실 방지, TanStack Query 캐시로 중복 요청 없음) - DisputePage: judgment/participants props 제거, isError 기반 에러 처리 - auth/index.ts: 프로필 이미지 백필 try-catch 감싸기 (실패 시 로그인 차단 방지) - judgement.api.ts: 에러 메시지 사용자 친화적으로 개선 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: 불필요한 스크린샷 PNG 파일 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: CalendarRecord 모델 제거 및 EmotionDiary title 필드 추가 - CalendarRecord 모델 및 CalendarRecordType enum 제거 - User, DisputeRoom, RoomAiConversation, Dispute에서 calendarRecords relation 제거 - EmotionDiary에 title 필드 추가 (VarChar 200) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 페이지 API 연동 - GET /api/disputes에 completed=true 쿼리 파라미터 추가 (judged/closed 필터링) - fetchCompletedCases, useCompletedCases 추가 (카테고리 필터 + 최신순) - RecordListSection 더미 데이터 제거, 실제 API 연동 - 사건 박스 클릭 시 /disputes/{id}로 이동 (기존 Link 구조 유지) - 로딩/에러/빈 상태 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 빈 상태 UI 개선 - 빈 상태 텍스트 → '등록한 사건이 없어요' - character-case.png 이미지 + 텍스트 중앙 배치 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건박스 공통 컴포넌트 CaseRecordCard 분리 - CaseRecordCard 신규 생성 (src/components/ui) - MUI AvatarGroup으로 1인/2인 참여자 프로필 겹침 표시 - RecordListSection에서 CaseRecordCard 사용하도록 교체 - 카드 스타일 RecordListSection.module.scss → CaseRecordCard.module.scss로 이동 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카카오 CDN http 프로토콜 이미지 허용 (img1.kakaocdn.net) 카카오 기본 프로필 이미지 URL이 http로 오는 경우가 있어 *.kakaocdn.net http 패턴 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 홈 페이지 배경 그라데이션 추가 (primary-200 → white) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 홈 그라데이션 범위 15%로 조정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 import 충돌 사전 해결 - UseQueryOptions, DisputeDto import 추가 (dev 브랜치 기준) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 useDispute refetchInterval 옵션 반영 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 및 juacheon 리뷰 반영 - disputes/route.ts: active/completed 동시 사용 시 if/else 분기로 필터 충돌 방지 - CaseRecordCard: <time> 요소에 dateTime 속성 추가 (접근성) - Header: transparent prop 추가, :global(header) 셀렉터 제거 - RecordListSection: 에러 메시지 구체화 - next.config.ts: 중복 HTTP 항목 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 2인 판결결과 점수 그래프 UI 수정 - isEqual/barEqual 제거, 색상 로직 ratioA >= ratioB 패턴으로 단순화 - scoreGraph margin-bottom 추가 - scoreAvatarImg 크기 명시적 fn.r(48)로 변경 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 2인 판결결과 그래프 디테일 수정 - 바 height 12 → 16, border-radius 6 → 4 - 중앙 실선 추가 (solid, border-strong, h36) - barDark 컬러 → status-disabled-text - scoreTitle 이름 부분만 bold 처리 - AI 고지 문구 컬러 → text-secondary Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 진술 탭 참여자 이름/MBTI 표시, 프로필 이미지 fallback 개선 - 진술 카드 레이블 A/B → 참여자 실명으로 변경 - 진술 카드 하단 프로필 이미지 + MBTI 추가 - DisputeParticipantDto에 mbti 필드 추가 - API participants에 mbti 포함 (disputes/[id] GET/PATCH) - profileImageUrl null 시 image 필드 fallback 적용 (목록/상세 API) - DisputePage.module.scss mixins import 추가 - JudgmentResult 그래프 점선/바 높이 디테일 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: JudgmentResult 참여자 이름 변수 통일 및 텍스트 치환 적용 - nameA / nameB 변수로 cardLabel, barLabel 통일 - replaceRoleNames 함수로 aFault/bFault/aSuggestedLine/bSuggestedLine 내 A님→실제이름 치환 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 리뷰 반영 - replaceRoleNames 단일 패스 치환으로 개선 (A님|B님 alternation) - disputes 목록/POST API Prisma 쿼리에 image 필드 선택 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf: statistics/categories API 빌드 시 DB 호출 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 카테고리 사건 2개 제한 및 사건기록 무한스크롤 - POST /api/rooms 카테고리당 진행중 사건 2개 초과 시 CATEGORY_LIMIT_EXCEEDED(422) 반환 - DisputeListResponse에 hasNext 필드 추가 - fetchCompletedCases 페이지 기반 API 호출로 전환 (limit 10) - useCompletedCases useInfiniteQuery로 전환 - RecordListSection IntersectionObserver 기반 무한스크롤 구현 - 모든 데이터 로드 시 '모든 데이터를 불러왔습니다' 표시 - NewCaseButton 카테고리 한도 초과 시 에러 모달 표시 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 리뷰 반영 - GET /api/disputes: completed 파라미터 where 조건 반영으로 hasNext 정확도 개선 - POST /api/disputes: 카테고리 한도 체크 추가 (직접 API 호출 우회 방지) - NewCaseButton: limitError 모달 표시 시 body 스크롤 잠금 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카테고리 한도 초과 에러 모달 UI 개선 - 기존 카테고리 패널 스타일 재사용 → 독립 검은 배경 센터 모달로 변경 - limitOverlay, limitModal, limitMessage, limitCloseButton 스타일 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카테고리 한도 에러 모달 메시지 줄바꿈 적용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 홈 통계 staleTime 24시간 → 1시간으로 단축 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 갈등유형 공유 페이지 분리 및 URL 공유 기능 구현 - /disputes/[id]/type 갈등유형 전용 페이지 신규 생성 (비회원 접근 가능) - GET /api/disputes/[id]/conflict-type 공개 API 추가 (유형명·이미지 URL만 반환) - 미들웨어에서 /disputes/[id]/type 인증 예외 처리 - 카카오 공유 → URL 복사(PC) / Web Share API(모바일) 방식으로 변경 - generateMetadata로 OG 메타 태그 생성 (og:image에 cardImageUrl 적용) - root layout에 metadataBase 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 갈등유형 결과 이미지 다운로드 기능 구현 - ConflictTypeClient, JudgmentTypeResult 결과 다운받기 버튼 활성화 - Supabase Storage 이미지 fetch 후 Blob 변환으로 로컬 저장 - fetch 실패(CORS 등) 시 새 탭으로 열어 수동 저장 유도 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: metadataBase에 VERCEL_URL fallback 추가 - 배포 환경에서 NEXT_PUBLIC_BASE_URL 미설정 시 VERCEL_URL을 자동 감지하여 사용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: ConflictTypeDetail Prisma 필드명 card_image_url로 수정 - cardImageUrl은 @Map 없이 card_image_url로 정의된 필드 - select 및 반환 시 camelCase 변환 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: JudgmentTypeResult에 disputeId prop 전달 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: ConflictTypeClient data null 체크 옵셔널 체이닝 적용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 리뷰 반영 (res.ok 체크, SCSS 린트, 에러 로그, Kakao SDK 제거) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 갈등 유형 탭 이름 표시를 role_a 고정에서 현재 사용자 기준으로 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: session.user.id 타입 오류 수정 및 유형 탭 이름 표시 fallback 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: 판결 결과 컴포넌트 및 도메인 로직 초기 작업 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 판결 결과 페이지 구현 (#판결탭/유형탭/UI) - DisputePage: 판결/유형 서브탭(Tab 공통컴포넌트) 추가 - JudgmentResult: 이미지 기준 UI 재구성, nickname 적용 - JudgmentTypeResult: 유형탭 컴포넌트 신규 생성 (카드이미지, ActionPrompt) - Tab.module.scss: w60 h36 사이즈 조정 - DisputeParticipantDto: nickname 필드 추가 - disputes/[id]/route: nickname 조회 추가 - judgment.mapper: cardImageUrl 추가 - types/judgment: ConflictTypeDetailDto에 cardImageUrl 추가 - auth/index: 카카오 로그인 시 profileImageUrl 저장 - page.module.scss: diaryBox max-width 제거 - NewCaseButton: AbortController timeout 30s Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: next.config에 Supabase Storage 및 카카오 이미지 도메인 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: JudgmentResult Avatar img 태그를 next/image로 교체 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 리뷰 반영 - participants nickname → name으로 변경 (DTO, route, 컴포넌트, useActiveCases) - next.config: 카카오 HTTP 패턴 제거 (HTTPS만 허용) - DisputePage: isCompleted null 케이스 처리 (!!dispute) - JudgmentResult.module.scss: declaration-empty-line-before stylelint 수정 - JudgmentTypeResult.module.scss: 동일 stylelint 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #90 추가 리뷰 반영 - JudgmentResult/JudgmentTypeResult: props 대신 disputeId 기반 직접 API 호출 (새로고침 시 데이터 유실 방지, TanStack Query 캐시로 중복 요청 없음) - DisputePage: judgment/participants props 제거, isError 기반 에러 처리 - auth/index.ts: 프로필 이미지 백필 try-catch 감싸기 (실패 시 로그인 차단 방지) - judgement.api.ts: 에러 메시지 사용자 친화적으로 개선 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: 불필요한 스크린샷 PNG 파일 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: CalendarRecord 모델 제거 및 EmotionDiary title 필드 추가 - CalendarRecord 모델 및 CalendarRecordType enum 제거 - User, DisputeRoom, RoomAiConversation, Dispute에서 calendarRecords relation 제거 - EmotionDiary에 title 필드 추가 (VarChar 200) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 페이지 API 연동 - GET /api/disputes에 completed=true 쿼리 파라미터 추가 (judged/closed 필터링) - fetchCompletedCases, useCompletedCases 추가 (카테고리 필터 + 최신순) - RecordListSection 더미 데이터 제거, 실제 API 연동 - 사건 박스 클릭 시 /disputes/{id}로 이동 (기존 Link 구조 유지) - 로딩/에러/빈 상태 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건기록 빈 상태 UI 개선 - 빈 상태 텍스트 → '등록한 사건이 없어요' - character-case.png 이미지 + 텍스트 중앙 배치 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 사건박스 공통 컴포넌트 CaseRecordCard 분리 - CaseRecordCard 신규 생성 (src/components/ui) - MUI AvatarGroup으로 1인/2인 참여자 프로필 겹침 표시 - RecordListSection에서 CaseRecordCard 사용하도록 교체 - 카드 스타일 RecordListSection.module.scss → CaseRecordCard.module.scss로 이동 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카카오 CDN http 프로토콜 이미지 허용 (img1.kakaocdn.net) 카카오 기본 프로필 이미지 URL이 http로 오는 경우가 있어 *.kakaocdn.net http 패턴 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 홈 페이지 배경 그라데이션 추가 (primary-200 → white) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 홈 그라데이션 범위 15%로 조정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 import 충돌 사전 해결 - UseQueryOptions, DisputeDto import 추가 (dev 브랜치 기준) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: dispute.hooks.ts dev 브랜치 useDispute refetchInterval 옵션 반영 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 및 juacheon 리뷰 반영 - disputes/route.ts: active/completed 동시 사용 시 if/else 분기로 필터 충돌 방지 - CaseRecordCard: <time> 요소에 dateTime 속성 추가 (접근성) - Header: transparent prop 추가, :global(header) 셀렉터 제거 - RecordListSection: 에러 메시지 구체화 - next.config.ts: 중복 HTTP 항목 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 2인 판결결과 점수 그래프 UI 수정 - isEqual/barEqual 제거, 색상 로직 ratioA >= ratioB 패턴으로 단순화 - scoreGraph margin-bottom 추가 - scoreAvatarImg 크기 명시적 fn.r(48)로 변경 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 2인 판결결과 그래프 디테일 수정 - 바 height 12 → 16, border-radius 6 → 4 - 중앙 실선 추가 (solid, border-strong, h36) - barDark 컬러 → status-disabled-text - scoreTitle 이름 부분만 bold 처리 - AI 고지 문구 컬러 → text-secondary Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 진술 탭 참여자 이름/MBTI 표시, 프로필 이미지 fallback 개선 - 진술 카드 레이블 A/B → 참여자 실명으로 변경 - 진술 카드 하단 프로필 이미지 + MBTI 추가 - DisputeParticipantDto에 mbti 필드 추가 - API participants에 mbti 포함 (disputes/[id] GET/PATCH) - profileImageUrl null 시 image 필드 fallback 적용 (목록/상세 API) - DisputePage.module.scss mixins import 추가 - JudgmentResult 그래프 점선/바 높이 디테일 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: JudgmentResult 참여자 이름 변수 통일 및 텍스트 치환 적용 - nameA / nameB 변수로 cardLabel, barLabel 통일 - replaceRoleNames 함수로 aFault/bFault/aSuggestedLine/bSuggestedLine 내 A님→실제이름 치환 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 리뷰 반영 - replaceRoleNames 단일 패스 치환으로 개선 (A님|B님 alternation) - disputes 목록/POST API Prisma 쿼리에 image 필드 선택 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf: statistics/categories API 빌드 시 DB 호출 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 카테고리 사건 2개 제한 및 사건기록 무한스크롤 - POST /api/rooms 카테고리당 진행중 사건 2개 초과 시 CATEGORY_LIMIT_EXCEEDED(422) 반환 - DisputeListResponse에 hasNext 필드 추가 - fetchCompletedCases 페이지 기반 API 호출로 전환 (limit 10) - useCompletedCases useInfiniteQuery로 전환 - RecordListSection IntersectionObserver 기반 무한스크롤 구현 - 모든 데이터 로드 시 '모든 데이터를 불러왔습니다' 표시 - NewCaseButton 카테고리 한도 초과 시 에러 모달 표시 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 리뷰 반영 - GET /api/disputes: completed 파라미터 where 조건 반영으로 hasNext 정확도 개선 - POST /api/disputes: 카테고리 한도 체크 추가 (직접 API 호출 우회 방지) - NewCaseButton: limitError 모달 표시 시 body 스크롤 잠금 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카테고리 한도 초과 에러 모달 UI 개선 - 기존 카테고리 패널 스타일 재사용 → 독립 검은 배경 센터 모달로 변경 - limitOverlay, limitModal, limitMessage, limitCloseButton 스타일 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 카테고리 한도 에러 모달 메시지 줄바꿈 적용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 홈 통계 staleTime 24시간 → 1시간으로 단축 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 갈등유형 공유 페이지 분리 및 URL 공유 기능 구현 - /disputes/[id]/type 갈등유형 전용 페이지 신규 생성 (비회원 접근 가능) - GET /api/disputes/[id]/conflict-type 공개 API 추가 (유형명·이미지 URL만 반환) - 미들웨어에서 /disputes/[id]/type 인증 예외 처리 - 카카오 공유 → URL 복사(PC) / Web Share API(모바일) 방식으로 변경 - generateMetadata로 OG 메타 태그 생성 (og:image에 cardImageUrl 적용) - root layout에 metadataBase 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 갈등유형 결과 이미지 다운로드 기능 구현 - ConflictTypeClient, JudgmentTypeResult 결과 다운받기 버튼 활성화 - Supabase Storage 이미지 fetch 후 Blob 변환으로 로컬 저장 - fetch 실패(CORS 등) 시 새 탭으로 열어 수동 저장 유도 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: metadataBase에 VERCEL_URL fallback 추가 - 배포 환경에서 NEXT_PUBLIC_BASE_URL 미설정 시 VERCEL_URL을 자동 감지하여 사용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: ConflictTypeDetail Prisma 필드명 card_image_url로 수정 - cardImageUrl은 @Map 없이 card_image_url로 정의된 필드 - select 및 반환 시 camelCase 변환 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: JudgmentTypeResult에 disputeId prop 전달 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: ConflictTypeClient data null 체크 옵셔널 체이닝 적용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 코드레빗 리뷰 반영 (res.ok 체크, SCSS 린트, 에러 로그, Kakao SDK 제거) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 갈등 유형 탭 이름 표시를 role_a 고정에서 현재 사용자 기준으로 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: session.user.id 타입 오류 수정 및 유형 탭 이름 표시 fallback 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: PR #124 리뷰 반영 - ConflictTypeClient 에러 상태 뒤로가기, 타이틀 개인화, 비로그인 버튼 경로 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 새 사건 카테고리 패널 딤 배경 적용, 에러 알림 모달로 변경, 홈 캐릭터 이미지 위치 조정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: closed 상태 판결 결과 미로드, 기본 이미지 확장자 통일, replaceRoleNames 순서 버그 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: 갈등 유형 카드 이미지 max-width 360px 제한 적용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
JudgmentResult,JudgmentTypeResult컴포넌트 추가DisputePage에 서브탭 렌더링 연결 및 판결 완료/종료 상태 노출next.config.tsremotePatterns 추가)ActionPrompt공통 컴포넌트 활용 (공유/다운로드 버튼)width={0} height={0} sizes="100vw")Review Fixes
DisputeParticipantDto, route, 컴포넌트,useActiveCases전체 반영isCompleted에서null케이스 처리 (!!dispute)@include뒤 빈 줄 추가 (declaration-empty-line-before)disputeId기반 직접 API 호출 (새로고침 시 데이터 유실 방지, TanStack Query 캐시로 중복 요청 없음)lib/auth/index.ts(profileImageUrl+deletedAt모두 select)Test Plan
name) 판결 카드에 정상 노출 확인🤖 Generated with Claude Code
Summary by CodeRabbit
릴리스 노트
New Features
Bug Fixes