Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
202 commits
Select commit Hold shift + click to select a range
338fb9c
chore: initialize project folder structure (#1)
evenif99 Jun 14, 2026
721c696
docs: add CLAUDE.md with project rules and work guidelines (#2)
evenif99 Jun 14, 2026
5f5b229
infra: setup project config and install dependencies (#3)
evenif99 Jun 14, 2026
de0f4d9
docs: add base documentation structure (#4)
evenif99 Jun 14, 2026
8a17ac0
docs: add domain document drafts for all MVP domains (#5)
evenif99 Jun 14, 2026
3a9791d
infra: add Next.js App Router entry files and SCSS base structure (#6)
evenif99 Jun 14, 2026
bb0f645
Infra/init next setup (#7)
evenif99 Jun 14, 2026
9a6fbe5
Update README.md (#8)
evenif99 Jun 14, 2026
d47aeb8
docs(infra): confirm Supabase as project infrastructure (#9)
evenif99 Jun 15, 2026
1e585ac
chore(github): add collaboration templates and policy (#10)
evenif99 Jun 15, 2026
0d55c19
docs(env): document environment variable management (#11)
evenif99 Jun 15, 2026
8db7957
docs(calendar): confirm MUI date picker usage (#12)
evenif99 Jun 15, 2026
cd3c931
chore(deps): install MUI X Date Pickers and peer dependencies (#13)
evenif99 Jun 15, 2026
cfa2d30
Update README.md (#15)
evenif99 Jun 15, 2026
4894aae
fix: resolve ESLint and TypeScript config warnings (#20)
evenif99 Jun 15, 2026
dc802bd
infra: add MVP Prisma schema with NextAuth and TALKY-OWL models (#21)
evenif99 Jun 15, 2026
d7de797
infra: align project structure with guide v2 (#22)
evenif99 Jun 15, 2026
3e234e4
infra: rename src/app/page to src/app/(page) for correct Next.js rout…
evenif99 Jun 15, 2026
132544f
[Style] 디자인 토큰 및 전역 스타일 설정 (#25)
lyla-bae Jun 16, 2026
a41ad81
style: 디자인 시스템 기반 설정 (#27)
lyla-bae Jun 16, 2026
84091bd
Feature/common component jw (#28)
evenif99 Jun 16, 2026
333873b
fix: :root {} 시맨틱 토큰을 _global.scss로 분리 (#29)
lyla-bae Jun 16, 2026
241ec4e
feat(common): 공통 UI 컴포넌트 추가 및 MUI 정책 적용 (#30)
evenif99 Jun 17, 2026
1cf99eb
feat: 사건 목록 공통 UI 컴포넌트 추가 (Tab, StatusBadge) (#31)
wjdals21 Jun 17, 2026
1b6f964
fix(common): ActionPrompt message 제거 및 Textarea 글자수 카운터 위치 수정 (#32)
evenif99 Jun 17, 2026
2d10c75
feat: 공통 및 dispute·judgment DTO 타입 정의
juahcheon Jun 17, 2026
aeb02d5
feat: dispute 도메인 공유 상수·헬퍼·mapper 추가
juahcheon Jun 17, 2026
5cba696
feat: 사건 목록 조회·생성·수정·삭제 API 구현
juahcheon Jun 17, 2026
8897de1
feat: AI 판결 요청·결과 조회 API 구현
juahcheon Jun 17, 2026
e687e01
feat: 공통 UI 컴포넌트 - StatusBadge, Tab, 진행 상태 (#33)
wjdals21 Jun 17, 2026
39b9581
Merge branch 'dev' of https://github.com/I5-Project/TALKY-OWL into fe…
juahcheon Jun 17, 2026
cfea865
feat: Prisma 클라이언트, NextAuth Kakao OAuth 설정 및 핸들러 추가
juahcheon Jun 17, 2026
d56e5a1
chore: 빌드 스크립트에 prisma generate 추가
juahcheon Jun 17, 2026
33c43bb
docs: MVP 전체 API 명세서 작성 (API_SPEC.md) (#36)
evenif99 Jun 17, 2026
4ff949c
feat: Spinner, Avatar, AvatarGroup 공통 컴포넌트 추가 (#37)
lyla-bae Jun 17, 2026
0e061f6
feat: 공통 UI 컴포넌트 - CategoryFilter, CategoryIcon, Tab, StatusBadge (#38)
wjdals21 Jun 17, 2026
7b877e9
fix(common): BottomNavigation 아이콘 MUI MD2 기본 스타일로 수정 (#39)
evenif99 Jun 17, 2026
aa27da3
feat: 사건·방 도메인 타입 정의 및 API 구현 (#40)
juahcheon Jun 17, 2026
8bad421
fix: API 라우트 경로 v1 버전 세그먼트 제거 (#42)
evenif99 Jun 17, 2026
569d321
fix(docs): 서비스 흐름 기반 문서 구조 수정 및 페이지 문서 생성 (#43)
evenif99 Jun 17, 2026
7b70fb0
fix: personal-analyses 페이지 및 API 폴더 삭제 (#45)
evenif99 Jun 17, 2026
d7f47d4
feat: 통계 API 구현 (GET /api/statistics/categories) (#44)
wjdals21 Jun 17, 2026
40975bb
feat: Header variant 분리 (logo/title) 및 홈 화면 적용 (#47)
wjdalss21 Jun 18, 2026
e2384b2
feat: 사건작성 페이지 구현 (disputes/[id]/statement) (#46)
juahcheon Jun 18, 2026
e606322
docs: 단독 판결 MVP 포함 및 관련 정책 업데이트 (#51)
evenif99 Jun 18, 2026
535b719
Feature/verdict record display - 캘린더 페이지 ui 제작 (#41)
SG-Develope Jun 18, 2026
8b7bff4
feat: 사건작성(진술서) 페이지 구현 및 욕설 감지 필터 연동 (#49)
juahcheon Jun 18, 2026
6691e76
feat: 카카오 로그인 기능 구현 (#50)
evenif99 Jun 18, 2026
686b9d7
docs: 단독/1:1 판결 공통 진입 흐름 반영 및 관련 문서 일괄 수정 (#54)
evenif99 Jun 18, 2026
162e88b
fix: Login 페이지 hydration removeChild 에러 수정 (#55)
evenif99 Jun 18, 2026
0c033b3
fix: statements submittedAt 멱등성 보장, 에러 로깅, moderation JSON 파싱 에러 처리 (…
juahcheon Jun 18, 2026
560d9b7
feat: 홈 화면 진행중인 사건 섹션 구현 (#52)
wjdalss21 Jun 18, 2026
06041f4
feat: 사건조회 페이지 구현 (진행중/진행완료, 1인/2인 분기) (#53)
juahcheon Jun 18, 2026
0244e21
feat: 초대 참여 페이지 퍼블리싱 및 공통 UI 컴포넌트 추가 (#57)
lyla-bae Jun 18, 2026
cbfd654
feat: 이용약관, 개인정보처리방침 페이지 추가 (#58)
evenif99 Jun 18, 2026
4497d87
fix(auth): 카카오 로그인 시 UUID 형식 검증 오류 수정 (#59)
evenif99 Jun 18, 2026
b265353
fix(auth): 카카오 로그인 리다이렉트 오류 수정 (SessionProvider 추가) (#61)
evenif99 Jun 19, 2026
77a1ee6
feat: 홈 화면 새 사건 버튼, 카테고리 모달, 서비스 정보 푸터 구현 (#62)
wjdalss21 Jun 19, 2026
87cb9f9
refactor: 진술 제출 시 dispute 상태 동기화 및 판결 조건 수정 (#67)
juahcheon Jun 19, 2026
94e1168
feat(mypage): 마이페이지 UI/레이아웃 및 기능 구현 (#63)
evenif99 Jun 19, 2026
8148bc4
feat: 홈 화면 개선 — DB 닉네임 인사말, 통계 API, 새 사건 버튼 연결 (#68)
wjdalss21 Jun 19, 2026
b8d7623
feat: 사건기록 페이지 구현 (#65)
wjdalss21 Jun 19, 2026
b251350
feat: 감정일기 상세 페이지 ui 구현 (#64)
SG-Develope Jun 19, 2026
8b36ccf
feat: AI 판결 스키마 분리 및 판결 로직 구현 (#70)
juahcheon Jun 19, 2026
84e3871
fix: seed ConflictTypeGroup 추가 및 판결 매퍼 타입 오류 수정 (#75)
juahcheon Jun 19, 2026
c59c87d
feat: 마이페이지 개인정보 수정 페이지 구현 (#71)
evenif99 Jun 19, 2026
00924a7
fix: Prisma schema 중복 UserTermsAgreement 모델 제거 (#77)
evenif99 Jun 19, 2026
6d1a8ca
fix(prisma): 중복 UserTermsAgreement 모델 제거 및 SCSS mixin 수정 (#78)
evenif99 Jun 19, 2026
01e088c
feat: 새 사건 버튼 — POST /api/rooms 연결 및 roomId 전달 (#73)
wjdalss21 Jun 19, 2026
a6b441e
feat: 초대 링크 발급·참여 API 구현 및 프론트 연결 (#69)
lyla-bae Jun 19, 2026
aa1f436
feat(auth): 카카오 로그인 시 약관 동의 레코드 저장 구현 (#72)
evenif99 Jun 19, 2026
8cdf581
feat: 사건조회 페이지 분기 UI 및 AI 판결 프롬프트 개선 (#79)
juahcheon Jun 19, 2026
f644ee5
fix: 진술 저장 API 에러 메시지 노출 (#80)
juahcheon Jun 19, 2026
c6221fc
fix(auth): 카카오 로그인 시 kakao_id 중복 유니크 제약 위반 해결 (#82)
evenif99 Jun 19, 2026
89d9c6f
fix: 홈 진행중인 사건 API 연동 및 UI 수정 (#83)
wjdalss21 Jun 20, 2026
84bd0d0
Revert "fix: 홈 진행중인 사건 API 연동 및 UI 수정 (#83)" (#84)
wjdalss21 Jun 20, 2026
31f4782
feat: name/nickname 표시 정책 적용 (#74)
evenif99 Jun 20, 2026
0d65f44
fix: 홈 진행중인 사건 API 연동 및 UI 수정 (#85)
wjdalss21 Jun 20, 2026
08816e4
perf: 홈 로딩 시 session API 중복 호출 제거 (#86)
evenif99 Jun 20, 2026
e412502
feat(diary): 감정일기 작성 페이지 및 CategoryFilter emotion 모드 추가 (#81)
SG-Develope Jun 20, 2026
094b3e2
refactor(api): 중복 users/me API 라우트 제거 (#89)
evenif99 Jun 20, 2026
0624cd6
feat(mypage): 회원탈퇴 전 약관 안내 페이지 추가 (#87)
evenif99 Jun 20, 2026
cec2189
fix(mypage): 프로필 이미지 미표시, 이름 기본값, MBTI 미설정 문구 수정 (#88)
evenif99 Jun 20, 2026
6c80b15
feat: 판결 결과 페이지 구현 (판결/유형 탭, JudgmentResult, JudgmentTypeResult) (#90)
wjdalss21 Jun 20, 2026
161411b
fix: ai_room 이름 변경, 초대 링크 버그 수정, 판결받기 버튼 개선 (#92)
lyla-bae Jun 20, 2026
c61d04e
fix: disputes/[id] 페이지 UI 및 판결 플로우 수정 (#91)
juahcheon Jun 20, 2026
bed7aab
fix(auth): 탈퇴 회원이 동일 카카오 계정으로 재가입 가능하도록 수정 (#94)
evenif99 Jun 20, 2026
5246856
fix: 사건조회 UI 개선 및 AI 판결 플로우 버그 수정 (#95)
juahcheon Jun 20, 2026
6aa65eb
fix: dispute UI 버그 수정 및 AI 판결 플로우 개선 (#96)
juahcheon Jun 20, 2026
72d96d7
feat: 사건기록 페이지 API 연동 및 홈 UI 개선 (#97)
wjdalss21 Jun 20, 2026
3f758cf
feat: 달력 월별 조회 및 감정일기 날짜별 조회 API 구현
SG-Develope Jun 20, 2026
ba7c079
refactor: diary , calendar 에러 응답처리
SG-Develope Jun 22, 2026
886f8ef
feat: 달력 월별 조회 및 감정일기 날짜별 조회 API 구현 (#98)
SG-Develope Jun 22, 2026
42e1668
chore: 이미지 에셋 SVG 전환 및 메타데이터 업데이트 (#99)
lyla-bae Jun 22, 2026
c917423
feat(about): 서비스 소개 페이지 구현 - 스프라이트 애니메이션, iris-out 전환, gsap 순차 등장
evenif99 Jun 22, 2026
223053b
fix: UI 구조 개선 및 진술 수정 기능 (#100)
juahcheon Jun 22, 2026
03ecc9c
Merge remote-tracking branch 'origin/dev' into feature/about-page
evenif99 Jun 22, 2026
1e05a65
feat(about): Hide bottom navigation on about page
evenif99 Jun 22, 2026
35e3b81
fix(style): Remove temporary dev border from container (#101)
evenif99 Jun 22, 2026
6d1c4a6
fix: API 성능 개선 및 UI 버그 수정 (#103)
juahcheon Jun 22, 2026
9b3298a
fix(about): CodeRabbit 리뷰 반영 - stylelint, 메모리 누수, 경로 매칭 수정
evenif99 Jun 22, 2026
b5d4395
fix(auth): 탈퇴 회원 카카오 재가입 허용 (#102)
evenif99 Jun 22, 2026
b35583b
feat: 2인 판결결과 UI 및 진술 탭 참여자 정보 개선 (#104)
wjdalss21 Jun 22, 2026
1ea54d1
feat(about): 서비스 소개 페이지 디자인 리뉴얼 - 이미지 기반 재구성
evenif99 Jun 22, 2026
dcd8e6e
fix(about): SpriteAnimation sed 중복 삽입 수정
evenif99 Jun 22, 2026
6e47202
feat(about): 피그마 디자인 기반 서비스 소개 페이지 전면 재구성
evenif99 Jun 22, 2026
f4e2134
fix(about): Hero 누끼 폰 이미지 + 수직 리볼빙 텍스트 애니메이션 구현
evenif99 Jun 22, 2026
d861696
fix(about): Hero 레이아웃 피그마 일치 - 좌측 리볼빙/중앙 폰/우측 텍스트
evenif99 Jun 22, 2026
31c500a
fix(about): Hero 좌우 텍스트 크기 통일 + 폰 위치 고정
evenif99 Jun 22, 2026
1544cac
fix(about): Hero 피그마 레이아웃 일치 - 위치/크기/배경 수정
evenif99 Jun 22, 2026
ca5637b
fix(about): 전체 페이지 비율 피그마 일치 - Hero 축소 및 섹션 간격 조정
evenif99 Jun 22, 2026
1419b89
fix(about): Hero 폰 이미지를 투명 누끼(11.png)로 교체
evenif99 Jun 22, 2026
b2fd2ca
fix(about): Hero 축소 + 텍스트 중앙 배치 + 크기 증가
evenif99 Jun 22, 2026
c7a34fb
fix(about): Hero 좌우 텍스트 정렬 + 크기 증가 + 말해부엉 색 조합
evenif99 Jun 22, 2026
0eea4c1
fix(about): 폰 고정 + 좌우 텍스트 줄 맞춤 + 커스텀 헤더
evenif99 Jun 22, 2026
80b0c92
fix(about): about 경로에서 기본 헤더 완전 제거
evenif99 Jun 22, 2026
651a693
fix(about): 좌우 텍스트 줄 맞춤 + 우측 텍스트 폰 침범 방지
evenif99 Jun 22, 2026
78ac48b
fix(about): 좌측 텍스트 밀림 수정 + 우측 텍스트 위치 조정
evenif99 Jun 22, 2026
9be7edb
fix(about): 리볼빙 텍스트 부드러운 슬라이드 애니메이션 복원
evenif99 Jun 22, 2026
90e5c2f
fix(about): 좌측 텍스트 중앙 방향으로 위치 조정
evenif99 Jun 22, 2026
3ac7dfe
fix(about): 리볼빙 텍스트 끊김 없는 무한 루프로 변경
evenif99 Jun 22, 2026
1f9a214
fix(about): 리볼빙 텍스트 항상 표시 유지 + active만 슬라이드 전환
evenif99 Jun 22, 2026
0bb91f0
fix(about): 리볼빙 애니메이션을 순차 콜백 방식으로 변경
evenif99 Jun 22, 2026
21faa89
fix(about): 탭3-5 Showcase 피그마 비율 맞춤
evenif99 Jun 22, 2026
51ca37e
fix(about): 탭3/5 폰 목업 하단 잘림 완화 - 전체 폰 표시
evenif99 Jun 22, 2026
cf1bada
fix(about): 탭3 CSS 폰 목업 제거 → 누끼 이미지(12.png)로 교체
evenif99 Jun 22, 2026
d040737
fix(about): 탭3 폰 이미지 하단까지 닿도록 margin-bottom -80px 적용
evenif99 Jun 22, 2026
49382d6
fix(about): 탭4 감정일기 레이아웃 변경 - 텍스트 왼쪽, 폰 오른쪽
evenif99 Jun 22, 2026
1395a40
fix(about): 탭4 폰 왼쪽 + 텍스트 오른쪽 배치로 수정
evenif99 Jun 22, 2026
f752b41
fix(about): 탭4 폰 이미지를 13.png 누끼로 교체 + 하단 잘림 처리
evenif99 Jun 22, 2026
610ebfb
fix(about): 탭5 폰 이미지를 14.png로 교체 + 상단 잘림 처리
evenif99 Jun 22, 2026
6024ab4
Merge remote-tracking branch 'origin/dev' into feature/about-page
evenif99 Jun 22, 2026
19916c2
fix: 사건 생성 플로우 개선 및 UI/성능 수정 (#107)
juahcheon Jun 22, 2026
3118a85
feat(about): 탭2 피그마 일치 - 동물 캐릭터 배치 + 카드별 아이콘 분리
evenif99 Jun 22, 2026
7770955
fix(about): 탭2 동물 캐릭터 위치 피그마 일치 조정
evenif99 Jun 22, 2026
b114795
chore(about): 서비스 소개 페이지 이미지 에셋 추가
evenif99 Jun 22, 2026
c079671
fix(mypage): 마이페이지 UI 개선 (#105)
evenif99 Jun 22, 2026
a221ce3
feat: 카테고리 사건 제한, 사건기록 무한스크롤, statistics API 최적화 (#106)
wjdalss21 Jun 22, 2026
96b439c
fix: api/user/me PATCH 중복 프로필 이미지 업로드 로직 제거 (#108)
evenif99 Jun 22, 2026
72a7d57
fix(auth): 비회원 보호 페이지 접근 시 로그인 리다이렉트 적용 (#109)
evenif99 Jun 22, 2026
b1bb80e
feat: 감정일기 수정 및 작성 페이지 api 연동
SG-Develope Jun 22, 2026
c877697
feat: 감정일기 수정 , 조회 api 추가
SG-Develope Jun 22, 2026
3ac101e
fix(auth): 콜백 URL 절대경로 처리로 로그인 후 원래 페이지 복귀 수정 (#114)
evenif99 Jun 22, 2026
9b9a054
Merge branch 'dev' of https://github.com/I5-Project/TALKY-OWL into fe…
SG-Develope Jun 23, 2026
5d0617b
refactor : diary route 예외처리 추가
SG-Develope Jun 23, 2026
81daa87
fix: API 라우트 미들웨어 리다이렉트 제거 (#120)
juahcheon Jun 23, 2026
bfd1cf0
Merge pull request #113 from I5-Project/feature/calendar-daily-record…
SG-Develope Jun 23, 2026
3c14a06
chore(about): framer-motion 패키지 설치
lyla-bae Jun 23, 2026
8b75347
feat(about): 랜딩 페이지 1400px 레이아웃 확장 및 타이포 스케일 조정
lyla-bae Jun 23, 2026
f63e05f
feat(about): GSAP 제거 → Framer Motion으로 전환
lyla-bae Jun 23, 2026
0be7ae2
style(variables): font-weight-extrabold 토큰 추가 및 포맷 정리
lyla-bae Jun 23, 2026
a001a86
fix(layout): about 페이지 container 클래스 분리 처리
lyla-bae Jun 23, 2026
37baaa1
chore(about): 랜딩 페이지 목업 이미지 에셋 추가
lyla-bae Jun 23, 2026
31fbe99
chore(about): 구버전 이미지 에셋 제거
lyla-bae Jun 23, 2026
c12b5e0
feat(about): 히어로 배경 이미지 추가 및 heroRight 애니메이션 제거
lyla-bae Jun 23, 2026
17a2f00
style(about): 피처카드 레이아웃 및 헤더 버튼 스타일 정리
lyla-bae Jun 23, 2026
69a37aa
chore(about): 동물 캐릭터 이미지 에셋 교체
lyla-bae Jun 23, 2026
cedee05
style(about): 피처카드 동물 캐릭터 배치 개선
lyla-bae Jun 23, 2026
6544275
style(about): showcase 레이아웃 개선 및 목업 이미지 비율 수정
lyla-bae Jun 23, 2026
b5776c7
fix(about): 푸터 서비스 소개 링크 추가 및 래퍼 div 적용
lyla-bae Jun 23, 2026
8a8bcd3
feat(about): Framer Motion 스크롤 애니메이션 및 반응형 레이아웃 적용
lyla-bae Jun 23, 2026
dbe1bed
fix(about): 피처 카드 hover 추가 및 미사용 CSS 정리
lyla-bae Jun 23, 2026
24f03ff
chore(about): 애니메이션 duration 조정 및 카피라이트 수정
lyla-bae Jun 23, 2026
e8722fd
feat(about): 헤더 로고 클릭 시 메인 페이지 이동 링크 추가
lyla-bae Jun 23, 2026
b387913
feat(about): 서비스 소개 페이지 리뉴얼 - Framer Motion 애니메이션 및 반응형 레이아웃 (#93)
evenif99 Jun 23, 2026
444213e
feat: 판결 결과 유형 공유 페이지 분리 및 비회원 접근 구현 (#124)
wjdalss21 Jun 23, 2026
bdc61b0
feat(chatbot): 마이페이지 고객문의 챗봇 구현 (#125)
evenif99 Jun 23, 2026
ebc8e23
feat(diary): 동일 카테고리 하루 최대 2건 초과 시 등록 차단 (#126)
SG-Develope Jun 23, 2026
9d1b8ab
fix: 판결 결과 버그 수정 및 홈 UI 개선 (#127)
wjdalss21 Jun 23, 2026
46aad7f
@ (#128)
evenif99 Jun 23, 2026
85f0eda
fix: Gemini 모델 fallback 및 타임아웃 조정 (#129)
juahcheon Jun 23, 2026
0267a4a
@ (#130)
evenif99 Jun 23, 2026
e9083e1
fix: Gemini deprecated 모델 제거 및 2.5-flash 단일 모델 재시도 로직 적용 (#131)
evenif99 Jun 23, 2026
89cf4aa
fix: 마이페이지 MBTI 텍스트 정렬 수정 (#132)
evenif99 Jun 23, 2026
570f199
refactor(diary): 중복 Date 생성 제거 및 updateMany를 update로 교체 (#133)
juahcheon Jun 23, 2026
584d593
fix: 푸터 고객문의 링크 제거 (#134)
evenif99 Jun 23, 2026
051e64e
fix: 홈 일기 박스 링크 /diary/new → /diary/create 수정 (#135)
wjdalss21 Jun 23, 2026
ae3b6ea
refactor(ui): 전체 UI 스타일 개편 (#138)
lyla-bae Jun 24, 2026
b075658
feat: 404/500/global 에러 페이지 구현 (#139)
wjdalss21 Jun 24, 2026
bf2610d
refactor(ui): 전체 UI 스타일 개편 (재PR) (#140)
lyla-bae Jun 24, 2026
2ededcf
chore: 일기 감정별 부엉이캐릭터 이미지 업로드
lyla-bae Jun 24, 2026
4f55177
Merge pull request #142 from I5-Project/chore/static-images
lyla-bae Jun 24, 2026
166dd25
fix: 에러 페이지 및 갈등 유형 공유 페이지 개선 (#141)
wjdalss21 Jun 24, 2026
fe73a19
feat(about): CTA 버튼 로그인 상태에 따라 라우팅 분기
lyla-bae Jun 25, 2026
baf6d2b
Merge branch 'dev' of https://github.com/I5-Project/TALKY-OWL into fe…
lyla-bae Jun 25, 2026
3b77f34
docs: README.md 프로젝트 현황 기반 전면 개편 (#144)
evenif99 Jun 25, 2026
e2e7793
Merge pull request #145 from I5-Project/feature/about-page
lyla-bae Jun 25, 2026
0e7972e
docs: 프로젝트 아키텍처, 디자인 시스템, ERD 문서 추가 (#146)
evenif99 Jun 25, 2026
ea5dc93
feat : 사건 판결 선물추천기능 추가 (#143)
SG-Develope Jun 25, 2026
da9c31e
fix(loading): 부엉이 캐릭터 스피너로 로딩 페이지 교체 (#147)
lyla-bae Jun 25, 2026
323ae94
fix: NEXT_PUBLIC_BASE_URL을 NEXT_PUBLIC_APP_URL로 통일 (#149)
evenif99 Jun 25, 2026
c81dbee
fix: OG 메타태그 head 주입 (#152)
wjdalss21 Jun 26, 2026
3953166
feat: 로그인 캐릭터 이미지 교체 및 그라데이션 배경 적용 (#154)
evenif99 Jun 26, 2026
ba2e026
fix: 이미지 공유 및 저장 기능 개선 (#153)
wjdalss21 Jun 26, 2026
be133c1
chore: trigger dev deployment (#155)
evenif99 Jun 26, 2026
fd984f0
fix: dev ← main 머지 충돌 해결 (#157)
evenif99 Jun 26, 2026
72a49cb
@ (#160)
evenif99 Jun 26, 2026
0da2b5f
fix: 공유 링크 페이지 이미지 저장 기기 분기 및 CORS 수정 (#159)
wjdalss21 Jun 26, 2026
634285f
fix: dev ← main 머지 충돌 해결 (#162)
evenif99 Jun 26, 2026
80b7ad8
fix: JudgmentTypeResult 불필요 주석 제거 (PR #161 충돌 해소) (#165)
evenif99 Jun 29, 2026
ddf08d7
fix: MBTI 동기화 및 진술 흐름 개선 (#166)
juahcheon Jul 1, 2026
2a18780
Merge remote-tracking branch 'origin/dev' into fix/sync-dev-to-main
evenif99 Jul 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions src/app/(page)/disputes/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export default function DisputePage({ params }: { params: Promise<{ id: string }
const [isRefreshing, setIsRefreshing] = React.useState(false);

React.useEffect(() => {
if (judgmentError && !judgmentErrorModal) {
if (judgmentError && !judgmentErrorModal && dispute?.status !== 'closed') {
setJudgmentErrorMessage(
judgmentErrorData instanceof Error
? judgmentErrorData.message
Expand Down Expand Up @@ -172,7 +172,8 @@ export default function DisputePage({ params }: { params: Promise<{ id: string }
showToast('초대 링크 발급에 실패했어요.');
return;
}
await navigator.clipboard.writeText(data.data.inviteUrl);
const category = dispute.categoryGroup.toLowerCase()
await navigator.clipboard.writeText(`${data.data.inviteUrl}?category=${category}`);
showToast('초대 링크가 복사되었어요!');
} catch {
showToast('초대 링크 발급에 실패했어요.');
Expand Down Expand Up @@ -308,7 +309,7 @@ export default function DisputePage({ params }: { params: Promise<{ id: string }
className={`${styles.statementCard}${myRole === 'role_a' && !isCompleted ? ` ${styles.statementCardEditable}` : ''}`}
onClick={
myRole === 'role_a' && !isCompleted
? () => router.push(`/disputes/${id}/statement?edit=true`)
? () => router.push(`/disputes/${id}/statement?category=${dispute.categoryGroup}&edit=true`)
: undefined
}
{...(myRole === 'role_a' && !isCompleted
Expand All @@ -318,7 +319,7 @@ export default function DisputePage({ params }: { params: Promise<{ id: string }
onKeyDown: (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
router.push(`/disputes/${id}/statement?edit=true`);
router.push(`/disputes/${id}/statement?category=${dispute.categoryGroup}&edit=true`);
}
},
}
Expand All @@ -337,9 +338,7 @@ export default function DisputePage({ params }: { params: Promise<{ id: string }
className={styles.statementAvatarImg}
/>
</div>
{participantA?.mbti && (
<span className={styles.statementMbti}>{participantA.mbti}</span>
)}
<span className={styles.statementMbti}>{participantA?.mbti ?? 'MBTI 미설정'}</span>
</div>
</div>
)}
Expand All @@ -348,7 +347,7 @@ export default function DisputePage({ params }: { params: Promise<{ id: string }
className={`${styles.statementCard}${myRole === 'role_b' && !isCompleted ? ` ${styles.statementCardEditable}` : ''}`}
onClick={
myRole === 'role_b' && !isCompleted
? () => router.push(`/disputes/${id}/statement?edit=true`)
? () => router.push(`/disputes/${id}/statement?category=${dispute.categoryGroup}&edit=true`)
: undefined
}
{...(myRole === 'role_b' && !isCompleted
Expand All @@ -358,7 +357,7 @@ export default function DisputePage({ params }: { params: Promise<{ id: string }
onKeyDown: (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
router.push(`/disputes/${id}/statement?edit=true`);
router.push(`/disputes/${id}/statement?category=${dispute.categoryGroup}&edit=true`);
}
},
}
Expand All @@ -377,9 +376,7 @@ export default function DisputePage({ params }: { params: Promise<{ id: string }
className={styles.statementAvatarImg}
/>
</div>
{participantB?.mbti && (
<span className={styles.statementMbti}>{participantB.mbti}</span>
)}
<span className={styles.statementMbti}>{participantB?.mbti ?? 'MBTI 미설정'}</span>
</div>
</div>
)}
Expand Down Expand Up @@ -447,7 +444,7 @@ export default function DisputePage({ params }: { params: Promise<{ id: string }
disabled={!canJudge}
onClick={() => (isSolo ? setShowSoloModal(true) : void runJudge())}
>
판결받기
{dispute.status === 'opponent_joined' ? '상대방이 작성 중...' : '판결받기'}
</Button>
</div>
</div>
Expand Down
10 changes: 10 additions & 0 deletions src/app/(page)/disputes/[id]/statement/StatementPage.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@
background-color: var(--bg-page);
}

.footerRow {
display: flex;
flex-direction: row;
gap: fn.r(12);

> * {
flex: 1;
}
}

.modalOverlay {
position: fixed;
inset: 0;
Expand Down
114 changes: 88 additions & 26 deletions src/app/(page)/disputes/[id]/statement/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useHeaderStore } from '@/stores/headerStore'
import { useDispute } from '@/domains/dispute/dispute.hooks'
import { useUserMe } from '@/domains/user/hooks'
import Button from '@/components/ui/Button'
import Spinner from '@/components/ui/Spinner'
import Select from '@/components/ui/Select'
import Textarea from '@/components/ui/Textarea'
import { CATEGORY_ICON_MAP, CATEGORY_LABEL_MAP } from '@/components/ui/CategoryIcon'
Expand Down Expand Up @@ -62,39 +63,82 @@ export default function StatementPage({
const [isLoading, setIsLoading] = React.useState(false)
const [filterMessage, setFilterMessage] = React.useState<string | null>(null)
const [showPersonalInfoWarning, setShowPersonalInfoWarning] = React.useState(false)
const [savedDisputeId, setSavedDisputeId] = React.useState<string | null>(null)

const SAVING_MESSAGES = ['나쁜 말을 검열 중입니다', '내용을 저장 중입니다', 'AI가 분석 중입니다', '조금만 기다려주세요']
const [savingMsgIdx, setSavingMsgIdx] = React.useState(0)
React.useEffect(() => {
if (!isLoading) return
const timer = setInterval(() => setSavingMsgIdx((i) => (i + 1) % SAVING_MESSAGES.length), 2000)
return () => clearInterval(timer)
}, [isLoading])

const handleCancel = () => {
fetch(`/api/rooms/${id}`, { method: 'DELETE', keepalive: true }).catch(() => {})
router.push('/')
}

const handleSave = async () => {
if (isLoading) return
setIsLoading(true)
setFilterMessage(null)

if (mbti !== (userMe?.mbti ?? '')) {
const form = new FormData()
form.append('mbti', mbti)
await fetch('/api/user/me', { method: 'PATCH', body: form })
}

try {
const res = await fetch(`/api/disputes/${id}/statements`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content }),
})
const json = await res.json() as { success: boolean; data?: { hasPersonalInfo?: boolean }; error?: { code?: string; message?: string } }

if (!json.success) {
setIsLoading(false)
const AI_EXTRACTION_CODES = ['AI_EXTRACTION_FAILED', 'AI_EXTRACTION_TIMEOUT', 'AI_EXTRACTION_PARSE_ERROR']
if (json.error?.code && AI_EXTRACTION_CODES.includes(json.error.code)) {
alert(json.error.message ?? 'AI 분석에 실패했습니다. 다시 시도해주세요.')
if (isEditMode) {
const res = await fetch(`/api/disputes/${id}/statements`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content }),
})
const json = await res.json() as { success: boolean; data?: { hasPersonalInfo?: boolean }; error?: { code?: string; message?: string } }

if (!json.success) {
setIsLoading(false)
setFilterMessage(json.error?.message ?? '저장 중 오류가 발생했습니다. 다시 시도해주세요.')
return
}
setFilterMessage(json.error?.message ?? '저장 중 오류가 발생했습니다. 다시 시도해주세요.')
return
}

if (json.data?.hasPersonalInfo) {
setIsLoading(false)
setShowPersonalInfoWarning(true)
return
}
if (json.data?.hasPersonalInfo) {
setIsLoading(false)
setShowPersonalInfoWarning(true)
return
}

router.push(`/disputes/${id}`)
} else {
const res = await fetch('/api/disputes', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ roomId: id, categoryGroup: category, content }),
})
const json = await res.json() as { success: boolean; data?: { id: string; hasPersonalInfo?: boolean }; error?: { code?: string; message?: string } }

if (!json.success) {
setIsLoading(false)
const AI_EXTRACTION_CODES = ['AI_EXTRACTION_FAILED', 'AI_EXTRACTION_TIMEOUT', 'AI_EXTRACTION_PARSE_ERROR']
if (json.error?.code && AI_EXTRACTION_CODES.includes(json.error.code)) {
alert(json.error.message ?? 'AI 분석에 실패했습니다. 다시 시도해주세요.')
return
}
setFilterMessage(json.error?.message ?? '저장 중 오류가 발생했습니다. 다시 시도해주세요.')
return
}

// 성공 시 isLoading을 false로 바꾸지 않음 — 페이지가 unmount될 때까지 스피너 유지
router.push(`/disputes/${id}`)
if (json.data?.hasPersonalInfo) {
setSavedDisputeId(json.data.id)
setIsLoading(false)
setShowPersonalInfoWarning(true)
return
}

router.push(`/disputes/${json.data!.id}`)
}
} catch {
setIsLoading(false)
setFilterMessage('네트워크 오류가 발생했습니다. 다시 시도해주세요.')
Expand All @@ -116,6 +160,17 @@ export default function StatementPage({

const Icon = CATEGORY_ICON_MAP[category]

if (isLoading) {
return (
<div className={styles.savingScreen}>
<div className={styles.savingContent}>
<Spinner />
<p className={styles.savingText}>{SAVING_MESSAGES[savingMsgIdx]}</p>
</div>
</div>
)
}

return (
<div className={styles.page}>

Expand Down Expand Up @@ -156,9 +211,16 @@ export default function StatementPage({
</div>

<div className={styles.footer}>
<Button onClick={handleSave} disabled={!content.trim() || isLoading}>
{isLoading ? '저장 중...' : isEditMode ? '수정저장' : '진술저장'}
</Button>
<div className={styles.footerRow}>
{!isEditMode && (
<Button variant="outline" onClick={() => void handleCancel()} disabled={isLoading}>
취소
</Button>
)}
<Button onClick={() => void handleSave()} disabled={!content.trim() || isLoading}>
{isLoading ? '저장 중...' : isEditMode ? '수정저장' : '진술저장'}
</Button>
</div>
</div>

{showPersonalInfoWarning && (
Expand All @@ -170,7 +232,7 @@ export default function StatementPage({
진술 내용을 다시 확인해주세요.
</p>
<div className={styles.modalActions}>
<Button onClick={() => router.push(`/disputes/${id}`)}>
<Button onClick={() => router.push(`/disputes/${isEditMode ? id : savedDisputeId!}`)}>
계속 진행
</Button>
<Button variant="outline" onClick={() => setShowPersonalInfoWarning(false)}>
Expand Down
13 changes: 10 additions & 3 deletions src/app/(page)/join/[token]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';

import React from 'react';
import { useEffect, useState } from 'react';
import { useRouter, useParams } from 'next/navigation';
import Button from '@/components/ui/Button';
Expand All @@ -15,10 +16,15 @@ interface JoinInfo {

type JoinState = 'loading' | 'invite' | 'error' | 'closed' | 'expired';

export default function JoinPage() {
export default function JoinPage({
searchParams,
}: {
searchParams: Promise<{ category?: string }>
}) {
const router = useRouter();
const params = useParams();
const token = params.token as string;
const { category } = React.use(searchParams);

const [state, setState] = useState<JoinState>('loading');
const [joinInfo, setJoinInfo] = useState<JoinInfo | null>(null);
Expand Down Expand Up @@ -79,15 +85,16 @@ export default function JoinPage() {
return;
}

router.push(`/disputes/${data.data.disputeId}/statement`);
const cat = category ?? joinInfo?.categoryGroup?.toLowerCase() ?? 'romance'
router.push(`/disputes/${data.data.roomId}/statement?category=${cat}`);
} catch {
setState('error');
} finally {
setIsJoining(false);
}
};

const goToMain = () => router.push('/home');
const goToMain = () => router.push('/');

const renderContent = () => {
if (state === 'loading') return null;
Expand Down
Loading