Skip to content

fix: QA 통합 — 영수증 공유/친구 목록 모달/홈·보관함·로그인 보정#210

Merged
ychany merged 18 commits into
devfrom
fix/202-qa-fixes
Jun 16, 2026
Merged

fix: QA 통합 — 영수증 공유/친구 목록 모달/홈·보관함·로그인 보정#210
ychany merged 18 commits into
devfrom
fix/202-qa-fixes

Conversation

@ychany

@ychany ychany commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

작업 내용

QA 라운드에서 발견된 이슈들을 카테고리별로 묶어 처리.

영수증 결과 페이지

  • 토너먼트 결과 영수증 이미지 공유 기능 구현 (Web Share API + 다운로드 fallback)
  • html2canvashtml-to-image 교체 — Tailwind v4 의 lab() 컬러 미지원 이슈 해결
  • 영수증 캡처 시 wrapper 가 아닌 실제 종이 element 를 직접 캡처해 일부만 잡히던 문제 수정
  • 결과 페이지의 공유/전체 결과 보기 카드가 화면 끝에 붙던 레이아웃 보정
  • "홈으로 가기" 버튼을 공통 Button 컴포넌트로 교체

보관함 / 더보기 메뉴

  • 토너먼트 카드 더보기에 친구 목록 보기 모달 추가
    • group-result 기반 lazy fetch (모달 열릴 때만 호출)
    • 본인 우선 정렬 + "나" 배지 (고정 SVG 아이콘)
    • 초대 친구 1명 이상일 때만 노출, 최대 높이 약 400px + 내부 스크롤
  • IN_PROGRESS 토너먼트는 참여자 API 부재로 임시 미노출 (별도 API 도메인 필요 — 후속 작업)
  • 더보기 메뉴 "결과 공유하기" → "결과 확인하기" 로 라벨/아이콘(영수증) 변경, 단순 결과 페이지 진입으로 단순화
  • 보관함 토너먼트 카드 — 홈과 동일하게 실제 사용자 이미지 사용

홈 / 로그인

  • 진행 중인 토너먼트가 없을 때 섹션 자체 숨김 처리
  • 로그인 화면 상단 간격 보정 + min-h-dvh 통일

기타

  • profile-circled-filled 아이콘 추가 (친구 목록 본인 배지용)
  • iOS splash screen 컨트롤러 사소 정리

연관 이슈

closes #202

Summary by CodeRabbit

  • 새로운 기능

    • 토너먼트 참여자 목록 조회 기능 추가
    • 영수증 이미지 공유 기능 강화 및 자동 공유 옵션 추가
  • 버그 수정

    • 영수증 이미지 캡처 안정성 개선
    • 로그인 페이지 레이아웃 및 높이 조정
  • UI/UX 개선

    • 토너먼트 카드에 참여자 수 정보 표시
    • 결과 페이지 레이아웃 및 버튼 스타일 개선
    • 결과 공유 메뉴 인터페이스 재구성

@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
depromeet Ready Ready Preview, Comment Jun 16, 2026 7:22am

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ychany, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 42 minutes and 40 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 31219c95-f9e1-460b-a632-83338cc15551

📥 Commits

Reviewing files that changed from the base of the PR and between 122591d and 46079e4.

📒 Files selected for processing (4)
  • apps/web/src/app/tournament/[id]/loading/_components/TournamentBracketAnimation.tsx
  • apps/web/src/app/tournament/[id]/loading/page.tsx
  • apps/web/src/app/tournament/[id]/match/_components/RoundTransitionSheet.tsx
  • apps/web/src/app/tournament/[id]/result/_components/ResultClient.tsx

Walkthrough

토너먼트 카드에 participantCount prop을 추가해 친구 목록 다이얼로그(FriendListDialog)를 조건부로 노출하고, MorePopover 메뉴를 재구성한다. 영수증 이미지 캡처 구현을 html2canvas에서 html-to-imagetoBlob으로 교체하며, ResultClientSHARE_RECEIPT 쿼리 액션 기반 자동 공유 실행 흐름을 추가한다.

Changes

Tournament Friend List & Receipt Share Refactor

Layer / File(s) Summary
participantCount prop 계약 및 callsite 연결
apps/web/src/components/tournament-card/index.tsx, apps/web/src/app/home/_components/TournamentList.tsx, apps/web/src/app/archive/_components/TournamentHistoryContent.tsx
TournamentCardPropsparticipantCount?: number를 추가하고, 홈·아카이브 페이지의 TournamentCard 호출부에서 participantProfileImages.length를 전달하도록 수정한다. 아카이브에는 Dicebear 아바타 URL을 imageUrl에서 제외하는 isGeneratedAvatar 헬퍼와, 빈 데이터 시 null 반환 로직도 포함된다.
FriendListDialog 신규 컴포넌트 및 useGetGroupResult enabled 옵션
apps/web/src/app/tournament/[id]/result/_hooks/useGetGroupResult.ts, apps/web/src/assets/icons/outline/index.ts, apps/web/src/components/tournament-card/FriendListDialog.tsx
useGetGroupResultUseGetGroupResultOptionsTenabled 파라미터를 추가한다. FriendListDialogopen 시에만 그룹 결과를 조회하고, chosenByuserId 기준 중복 제거·isMe 우선 정렬 후 FriendListBody/FriendRow로 렌더링한다. ProfileCircledFilledIconOutline 아이콘 export도 추가된다.
MorePopover 메뉴 재구성 및 FriendListDialog 연결
apps/web/src/components/tournament-card/MorePopover.tsx
participantCount >= 2 조건으로 친구 목록 메뉴를 조건부 노출한다. 기존 "결과 공유하기"(LinkIconFill)를 "결과 확인하기"(ReciptIconFill + 라우팅)로 교체하고, FriendListDialog를 상태와 연결해 렌더링한다.
영수증 캡처를 html-to-image로 교체 및 ResultClient 공유 자동 실행
apps/web/package.json, apps/web/src/app/tournament/[id]/result/_utils/shareReceiptImage.ts, apps/web/src/app/tournament/[id]/result/_components/ReceiptDrawMachine.tsx, apps/web/src/app/tournament/[id]/result/_components/ResultClient.tsx, apps/web/src/consts/queryAction.ts
html2canvashtml-to-image로 교체하고, shareReceiptImage에서 off-screen 클론·데이터URL 변환 단계를 제거해 toBlob 직접 호출로 단순화한다. ReceiptDrawMachinefirstElementChild를 반환하도록 변경된다. ResultClientSHARE_RECEIPT 액션 수신 시 2초 지연 자동 공유를 추가하고, 공유 버튼·그룹 결과 영역에 mx-5 여백 및 Button 컴포넌트 교체가 포함된다.
레이아웃/스타일 및 코드 형식 정리
apps/web/src/app/login/page.tsx, apps/web/src/app/tournament/[id]/create/_components/TournamentCreateClient.tsx, apps/app/hooks/useSplashScreenController.tsx
로그인 페이지 컨테이너 클래스 조정(min-h-dvh, pb-10, mt-15), TournamentCreateClient 클래스 순서 재배치, useSplashScreenController import/선언 단일 라인 정리 등 동작 변경 없는 형식 조정이다.

Sequence Diagram(s)

sequenceDiagram
  participant User as 사용자
  participant MorePopover
  participant FriendListDialog
  participant useGetGroupResult
  participant ResultClient
  participant shareReceiptImage as shareReceiptImage (html-to-image)

  rect rgba(100, 149, 237, 0.5)
    note over User, FriendListDialog: 친구 목록 보기 흐름 (COMPLETED, participantCount >= 2)
    User->>MorePopover: "친구 목록 보기" 클릭
    MorePopover->>FriendListDialog: open=true, tournamentId 전달
    FriendListDialog->>useGetGroupResult: enabled=true 로 그룹 결과 조회
    useGetGroupResult-->>FriendListDialog: items[].chosenBy 반환
    FriendListDialog-->>User: userId 중복 제거·isMe 우선 정렬된 친구 목록 표시
  end

  rect rgba(144, 238, 144, 0.5)
    note over User, shareReceiptImage: 영수증 공유 자동 실행 흐름 (?action=share-receipt)
    User->>ResultClient: 페이지 진입 (share-receipt 액션)
    ResultClient->>ResultClient: 2초 대기 (슬라이드 종료 타이밍)
    ResultClient->>shareReceiptImage: getReceiptPaperElement().firstElementChild 전달
    shareReceiptImage->>shareReceiptImage: html-to-image toBlob(element, pixelRatio)
    shareReceiptImage-->>User: 다운로드 or Web Share API 실행
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • depromeet/PIKI-Client#196: shareReceiptImage.ts의 html2canvas 기반 캡처 구조를 최초 도입한 PR로, 이번 PR에서 해당 구현을 html-to-image로 직접 교체한다.
  • depromeet/PIKI-Client#111: ReceiptDrawMachine.tsx의 영수증 종이 DOM 렌더링 방식을 수정한 PR로, 이번 PR의 firstElementChild 캡처 대상 변경과 직접 연관된다.
  • depromeet/PIKI-Client#135: QUERY_ACTION 상수를 확장한 PR로, 이번 PR에서 SHARE_RECEIPT 액션 추가와 같은 코드 경로를 공유한다.

Suggested reviewers

  • kanghaeun

Poem

🐰 토끼가 영수증을 찍었어요~
html2canvas는 이제 안녕!
html-to-image로 쏙 바꿔서
친구 목록도 빠끔 열리고
공유 버튼 딸깍, 2초 뒤에 짜잔!
🎉 버그 없는 봄날이 왔어요 🌸

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 주요 변경 사항인 영수증 공유, 친구 목록 모달, 홈/보관함/로그인 화면 보정 작업을 명확하게 요약하고 있습니다.
Linked Issues check ✅ Passed 연결된 이슈 #202는 QA 진행 중 발견된 전반적인 버그/UI/UX 항목들을 통합 트리아지하는 메타 트래커입니다. PR의 변경 사항들(영수증 공유 기능, 친구 목록 모달, 레이아웃 조정)은 모두 이러한 QA 통합 이슈의 범위 내 개선 사항들입니다.
Out of Scope Changes check ✅ Passed 모든 변경 사항이 QA 통합 이슈 #202의 범위 내 개선 사항들입니다. 영수증 공유(html-to-image 라이브러리 교체), 친구 목록 모달, 레이아웃 조정, 스플래시 스크린 정리 등이 모두 QA 발견 사항 대응으로 관련성 있습니다.

✏️ 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/202-qa-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/web/src/app/archive/_components/TournamentHistoryContent.tsx (1)

9-11: ⚡ Quick win

isGeneratedAvatar 헬퍼 중복 정의 → 공통 유틸로 추출 권장

TournamentHistoryContent.tsxTournamentList.tsx 두 파일 모두에서 동일한 isGeneratedAvatar 유틸리티 함수를 정의하고 있습니다. 공통 유틸 파일로 추출하면 일관성과 유지보수성이 향상됩니다.

  • apps/web/src/app/archive/_components/TournamentHistoryContent.tsx#L9-L11: 공통 유틸로 이동 후 import
  • apps/web/src/app/home/_components/TournamentList.tsx#L7-L9: 공통 유틸로 이동 후 import
♻️ 제안: `@/utils/avatar.ts` 생성 및 양쪽 파일에서 import
// apps/web/src/utils/avatar.ts
/** 비회원의 서버 생성 Dicebear 아바타 URL 여부 판별 */
export const isGeneratedAvatar = (url: string) => url.includes('api.dicebear.com');

양쪽 파일 수정:

- const isGeneratedAvatar = (url: string) => url.includes('api.dicebear.com');
+ import { isGeneratedAvatar } from '`@/utils/avatar`';
🤖 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 `@apps/web/src/app/archive/_components/TournamentHistoryContent.tsx` around
lines 9 - 11, The isGeneratedAvatar function is currently defined in two
separate files:
apps/web/src/app/archive/_components/TournamentHistoryContent.tsx (lines 9-11)
and apps/web/src/app/home/_components/TournamentList.tsx (lines 7-9). Extract
this duplicate function into a shared utility file at
apps/web/src/utils/avatar.ts, then replace both local function definitions with
imports from this new utility file. This will ensure consistency and improve
maintainability across the codebase.
apps/web/src/app/tournament/[id]/result/_components/ReceiptDrawMachine.tsx (1)

34-36: ⚡ Quick win

타입을 HTMLElement로 변경해 안정성을 높이세요.

현재 HTMLDivElement로 타입 단언하고 있지만, ReceiptPaper 컴포넌트가 항상 div를 루트로 렌더링한다는 보장이 없습니다. 실제 소비측(shareReceiptImage)은 HTMLElement만 필요하므로, 더 일반적인 타입을 사용하는 것이 안전합니다.

♻️ 제안하는 수정
 /** 외부에서 영수증 종이 DOM 을 캡처할 때 사용 (예: 영수증 이미지 공유) */
 export type ReceiptDrawMachineHandleT = {
-  getReceiptPaperElement: () => HTMLDivElement | null;
+  getReceiptPaperElement: () => HTMLElement | null;
 };
       () => ({
         // 캡처 대상은 wrapper(transform 으로 애니메이션 / clip-path 마스크 영향) 가 아니라
         // 그 안의 실제 영수증 종이 element.
         getReceiptPaperElement: () =>
-          (receiptPaperRef.current?.firstElementChild as HTMLDivElement | null) ?? null,
+          (receiptPaperRef.current?.firstElementChild as HTMLElement | null) ?? null,
       }),

Also applies to: 48-51

🤖 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 `@apps/web/src/app/tournament/`[id]/result/_components/ReceiptDrawMachine.tsx
around lines 34 - 36, Change the return type of the getReceiptPaperElement
method in the ReceiptDrawMachineHandleT type definition from HTMLDivElement to
HTMLElement to improve type stability and flexibility, since the ReceiptPaper
component does not guarantee that a div element will be the root element, and
the actual consumer (shareReceiptImage) only requires the more general
HTMLElement type. This change should be applied wherever
ReceiptDrawMachineHandleT is defined or used to ensure type consistency.
🤖 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 `@apps/web/src/app/tournament/`[id]/result/_components/ResultClient.tsx:
- Around line 62-67: The setTimeout in the useQueryAction onAction callback is
not being cleaned up when the component unmounts, which can cause
handleShareReceiptImage to be called after unmount. Fix this by either creating
a mounted state ref (isMountedRef) that tracks component lifecycle and checking
it before calling handleShareReceiptImage inside the setTimeout callback, or by
moving the timer management logic into a separate useEffect hook where the
timeout can be properly canceled in the cleanup function. The current
implementation in the ResultClient component has no mechanism to prevent the
queued timeout from executing after unmount.

---

Nitpick comments:
In `@apps/web/src/app/archive/_components/TournamentHistoryContent.tsx`:
- Around line 9-11: The isGeneratedAvatar function is currently defined in two
separate files:
apps/web/src/app/archive/_components/TournamentHistoryContent.tsx (lines 9-11)
and apps/web/src/app/home/_components/TournamentList.tsx (lines 7-9). Extract
this duplicate function into a shared utility file at
apps/web/src/utils/avatar.ts, then replace both local function definitions with
imports from this new utility file. This will ensure consistency and improve
maintainability across the codebase.

In `@apps/web/src/app/tournament/`[id]/result/_components/ReceiptDrawMachine.tsx:
- Around line 34-36: Change the return type of the getReceiptPaperElement method
in the ReceiptDrawMachineHandleT type definition from HTMLDivElement to
HTMLElement to improve type stability and flexibility, since the ReceiptPaper
component does not guarantee that a div element will be the root element, and
the actual consumer (shareReceiptImage) only requires the more general
HTMLElement type. This change should be applied wherever
ReceiptDrawMachineHandleT is defined or used to ensure type consistency.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b747b779-40e2-4de1-8a69-2b386689956b

📥 Commits

Reviewing files that changed from the base of the PR and between 36f8020 and 122591d.

⛔ Files ignored due to path filters (2)
  • apps/web/src/assets/icons/outline/profile-circled-filled.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (15)
  • apps/app/hooks/useSplashScreenController.tsx
  • apps/web/package.json
  • apps/web/src/app/archive/_components/TournamentHistoryContent.tsx
  • apps/web/src/app/home/_components/TournamentList.tsx
  • apps/web/src/app/login/page.tsx
  • apps/web/src/app/tournament/[id]/create/_components/TournamentCreateClient.tsx
  • apps/web/src/app/tournament/[id]/result/_components/ReceiptDrawMachine.tsx
  • apps/web/src/app/tournament/[id]/result/_components/ResultClient.tsx
  • apps/web/src/app/tournament/[id]/result/_hooks/useGetGroupResult.ts
  • apps/web/src/app/tournament/[id]/result/_utils/shareReceiptImage.ts
  • apps/web/src/assets/icons/outline/index.ts
  • apps/web/src/components/tournament-card/FriendListDialog.tsx
  • apps/web/src/components/tournament-card/MorePopover.tsx
  • apps/web/src/components/tournament-card/index.tsx
  • apps/web/src/consts/queryAction.ts

@ychany ychany self-assigned this Jun 16, 2026
@ychany
ychany merged commit a1260cd into dev Jun 16, 2026
5 checks passed
@ychany
ychany deleted the fix/202-qa-fixes branch June 16, 2026 07:28
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.

[QA] 진행 통합 트래킹 이슈

1 participant