Skip to content

feat: 투표 상세 페이지 구현#4

Open
numeru wants to merge 7 commits intodevelopfrom
feat/vote-detail-page-structured
Open

feat: 투표 상세 페이지 구현#4
numeru wants to merge 7 commits intodevelopfrom
feat/vote-detail-page-structured

Conversation

@numeru
Copy link
Copy Markdown
Collaborator

@numeru numeru commented May 5, 2026

Summary

투표 상세 페이지(/votes/:voteId) 구현에 필요한 전체 스택을 추가합니다.
FSD 아키텍처 계층 순서대로 6개 커밋으로 구성했습니다.

Commit Structure

# 커밋 내용
1 docs FSD 아키텍처 가이드, Auth/Vote API 명세, CLAUDE.md 문서 링크
2 base infra Axios 클라이언트, Modal, Spinner 컴포넌트, Modal 애니메이션 CSS, lock 아이콘
3 auth feature User 타입, GET /api/users/me TanStack Query 훅
4 votes model & API VoteDetail 타입, useVoteDetail 훅, 투표 참여·취소·이모지 뮤테이션, 목업 데이터
5 votes UI VoteDetailPage 및 하위 컴포넌트 9개, AgeBarChart isPrimary → isMyGroup 변경
6 routing TanStack Router 파일 라우트에 HomePage, VoteDetailPage 연결

Key Changes

  • 투표 상세 화면: 헤더(뒤로가기/공유), 본문, 옵션 선택, 이모지 반응, 남은 시간 표시
  • 결과 인사이트: 투표 종료 후 성별/연령대 분포 시각화 (잠금 해제 UX 포함)
  • 재사용 컴포넌트: Modal(포탈·포커스트랩·스크롤락), Spinner — 다른 feature에서 재사용 가능

Test plan

  • /votes/:voteId 진입 시 투표 상세 데이터 정상 표시
  • 옵션 선택 → 참여/취소 뮤테이션 동작
  • 이모지 반응 버튼 동작
  • 투표 종료 상태에서 인사이트 섹션 표시 (잠금/해제)
  • Modal 컴포넌트 진입·퇴출 애니메이션
  • pnpm build 빌드 성공
  • pnpm lint Biome 통과

🤖 Generated with Claude Code

numeru and others added 6 commits May 5, 2026 20:07
프로젝트 아키텍처(FSD)와 인증/투표 API 명세를 문서화합니다.
신규 개발자 온보딩 및 API 계약 공유를 위해 CLAUDE.md에 문서 링크를 추가합니다.

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

여러 feature에서 재사용 가능한 기반 레이어를 구성합니다.
- base/api: Axios 인스턴스(credentials, JSON 헤더 기본값)
- base/ui/Modal: 포탈 기반 모달(포커스 트랩, 스크롤 락, 진입/퇴출 애니메이션)
- base/ui/Spinner: 로딩 상태 표시 컴포넌트
- global CSS: Modal 전용 keyframe 애니메이션 추가
- lock.svg: 잠금 콘텐츠 UI용 아이콘

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
투표 결과 인사이트(성별/연령대 분포)에서 로그인 사용자 정보를 활용하기 위해
인증 기능의 기반 계층을 구성합니다.
- model/types.ts: User 인터페이스(닉네임, 성별, 생년월일, 상태 등)
- api/userQuery.ts: GET /api/users/me TanStack Query 훅

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
투표 상세 페이지에 필요한 데이터 계층 전체를 구성합니다.

타입:
- model/types.ts: VoteDetail, VoteOption, EmojiType 등 도메인 타입
- model/resultTypes.ts: VoteResult, InsightUnlocked/InsightLocked 타입

비즈니스 로직:
- model/useVoteDetail.ts: 상세 조회 + 참여/취소/이모지 뮤테이션 통합 훅
- model/voteDetailUtils.ts: 남은 시간 계산, 옵션 정렬 등 순수 유틸

API:
- api/voteDetailQuery.ts: GET /api/votes/{voteId}
- api/voteResultQuery.ts: GET /api/votes/{voteId}/result
- api/voteParticipate.ts: POST/DELETE 투표 참여·취소
- api/voteEmoji.ts: PUT 이모지 반응
- api/mock*.ts: 개발용 목업 데이터

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
투표 상세 페이지를 구성하는 UI 컴포넌트 계층입니다.

컴포넌트 구조 (VoteDetailPage가 최상위 조합):
- VoteHeader: 뒤로가기 / 제목 / 공유 버튼
- VoteContent: 투표 제목, 작성 시각, 본문, 썸네일
- VoteOptionsSection: 옵션 선택 + VoteBar(퍼센트 시각화)
- VoteReactionBar: LIKE·SAD·ANGRY·WOW 이모지 반응
- VoteTimeRemaining: 마감까지 남은 시간
- VoteInsightSection: 투표 종료 후 성별/연령대 분포 분석
- LockedContentOverlay: 인사이트 잠금 해제 유도 오버레이

함께 수정:
- base/ui/AgeBarChart: isPrimary → isMyGroup으로 변수명 변경
  (현재 사용자의 연령대 그룹을 강조하는 의미를 명확히 표현)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TanStack Router 파일 기반 라우팅에 페이지를 연결합니다.
- /home → HomePage
- /votes/:voteId → VoteDetailPage (voteId 파라미터 전달)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@numeru
Copy link
Copy Markdown
Collaborator Author

numeru commented May 5, 2026

Code review

Found 1 issue:

  1. voteUserType always resolves to "member-not-voted" for logged-in users on ONGOING votes because result (from voteResultQueryOptions) is only fetched when isEnded === true — so result?.myVote.voted is always undefined on a live vote. The voted state for ONGOING votes is available on data?.myVote.voted (the vote detail query), which the rest of the hook already uses correctly (e.g. handleOptionClick on line 121 checks data?.myVote.voted). Fix: use data?.myVote.voted as the source for voteUserType.

const participateMutation = useMutation({
mutationFn: (optionId: number) => participateVote(voteId, optionId),
onMutate: async (optionId) => {
await queryClient.cancelQueries({ queryKey });

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

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.

1 participant