feat: 초대 링크 합류 플로우 개선#220
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No description provided. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Walkthrough초대 링크/코드 참여 흐름을 게스트 기반에서 인증 사용자(MEMBER/게스트) 기반으로 전환한다. Changes초대 참여 흐름 전환 및 에러 처리
Sequence Diagram(s)sequenceDiagram
participant User
participant InviteClient
participant JoinPreviewClient
participant usePatchMe
participant usePostJoin
participant TournamentErrorDialog
User->>InviteClient: 초대 링크 접근
InviteClient->>InviteClient: getInvitePreviewByCode()
alt 409 에러
InviteClient->>TournamentErrorDialog: LINK_EXPIRED 표시
else MEMBER identityType
InviteClient->>usePostJoin: postJoin() 직접 호출
usePostJoin-->>InviteClient: 성공 → WELCOME_JOIN 쿼리 포함 생성 화면으로 이동
else 게스트 또는 비회원
InviteClient->>JoinPreviewClient: 닉네임 입력 화면으로 이동
User->>JoinPreviewClient: 닉네임 입력 후 확인
alt 닉네임 변경 있음
JoinPreviewClient->>usePatchMe: patchMeMutation
usePatchMe-->>JoinPreviewClient: onSuccess
end
JoinPreviewClient->>usePostJoin: joinTournament()
alt 409 에러
usePostJoin-->>TournamentErrorDialog: LINK_EXPIRED 표시
else 성공
usePostJoin-->>JoinPreviewClient: WELCOME_JOIN 쿼리 포함 라우팅
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/src/app/tournament/join/[id]/page.tsx (1)
18-39:⚠️ Potential issue | 🟠 Major | ⚡ Quick win초대 코드 필수 계약이 클라이언트에서 보장되지 않습니다.
code가 없는 경우에도 조인 화면이 열리고, 실제 join 요청 본문에서도inviteCode가 생략될 수 있습니다. 초대 링크 기반 참여 플로우 계약이 깨져 400 실패/오동작으로 이어질 수 있어요.
apps/web/src/app/tournament/join/[id]/page.tsx#L18-L39:code가 없거나 공백이면 즉시 차단(notFound()또는 에러 경로)하고,JoinPreviewClient에는 유효한 코드만 전달하세요.apps/web/src/app/tournament/join/[id]/_components/JoinPreviewClient.tsx#L56-L61:body의 조건부 spread를 제거하고inviteCode를 항상 포함해 전송하도록 고정하세요.🤖 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/join/`[id]/page.tsx around lines 18 - 39, The invite code validation is incomplete and breaks the invite-link-based join flow contract. In the page.tsx file at the searchParams destructuring and code validation section, add a check to ensure `code` exists and is not empty before passing it to JoinPreviewClient—call notFound() if the code is missing or blank to prevent opening the join screen without a valid invite code. In the JoinPreviewClient.tsx file at the request body construction around lines 56-61, remove any conditional spread or optional inclusion of inviteCode and ensure inviteCode is always included in the request body to prevent omitting it on the join request.
🧹 Nitpick comments (3)
apps/web/src/app/tournament/[id]/create/_components/TournamentCreateClient.tsx (1)
13-13: ⚡ Quick winimport 규칙을 가이드라인에 맞게 분리해 주세요.
Line 13은 type/value 혼합 import와 상대경로 import를 함께 사용하고 있어,
import type분리 규칙과@/*절대 경로 규칙을 동시에 위반합니다.As per coding guidelines, "
Use import type for type-only imports; disallow mixing type and value imports" 및 "Use absolute path alias@/* for imports instead of relative paths"를 따라야 합니다.제안 수정안
-import { type JoinConfirmPayloadT, consumeJoinConfirmFor } from '../../../join/_utils/joinSession'; +import { consumeJoinConfirmFor } from '`@/app/tournament/join/_utils/joinSession`'; +import type { JoinConfirmPayloadT } from '`@/app/tournament/join/_utils/joinSession`';🤖 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]/create/_components/TournamentCreateClient.tsx at line 13, The import statement on line 13 mixes type and value imports in violation of the type-only import separation rule, and uses a relative path instead of the absolute path alias. Split the single import statement into two separate imports: one using `import type` for the JoinConfirmPayloadT type import, and another for the consumeJoinConfirmFor value import. Additionally, replace the relative path `../../../join/_utils/joinSession` with the corresponding absolute path using the `@/*` alias to comply with the absolute path import rule.Source: Coding guidelines
apps/web/src/components/tournament-error-dialog/index.tsx (2)
5-12: ⚡ Quick win
apps/web/src규칙과 다르게 상대 경로 import를 사용하고 있습니다.이 파일은
apps/web/src하위라서 상대 경로 대신@/*별칭 import로 맞추는 게 좋습니다.제안 수정안
import { FireIconFill, HistoryIconFill, SadIconFill, WarningIconFill } from '`@/assets/icons`'; import ButtonLink from '`@/components/button/ButtonLink`'; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogTitle, +} from '`@/components/dialog`'; import { ROUTES } from '`@/consts/route`'; - -import { - Dialog, - DialogClose, - DialogContent, - DialogDescription, - DialogFooter, - DialogTitle, -} from '../dialog';As per coding guidelines,
apps/web/src/**/*.{ts,tsx}에서는 상대 경로 대신@/*절대 경로를 사용해야 합니다.🤖 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/components/tournament-error-dialog/index.tsx` around lines 5 - 12, The import statement in tournament-error-dialog/index.tsx is using a relative path import from '../dialog' which violates the coding guidelines for apps/web/src. Replace the relative path import with the `@/`* alias import pattern. Change the import statement to use `@/components/dialog` (or the appropriate absolute path alias) instead of the relative '../dialog' path to align with the project's import standards.Source: Coding guidelines
14-18: ⚡ Quick winProps 타입명을 컴포넌트명 기준으로 맞춰주세요.
Props대신TournamentErrorDialogProps로 선언하면 현재 저장소 규칙과 일치합니다.제안 수정안
-type Props = { +type TournamentErrorDialogProps = { type: 'NO_WISH_EXISTS' | 'ALREADY_STARTED' | 'ALREADY_ENDED' | 'LINK_EXPIRED' | 'REQUEST_FAILED'; open: boolean; onOpenChange: (open: boolean) => void; }; -function TournamentErrorDialog({ type, open, onOpenChange }: Props) { +function TournamentErrorDialog({ type, open, onOpenChange }: TournamentErrorDialogProps) {As per coding guidelines, React 컴포넌트 props 타입은
{ComponentName}Props패턴을 사용해야 합니다.Also applies to: 58-58
🤖 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/components/tournament-error-dialog/index.tsx` around lines 14 - 18, The Props type declaration does not follow the repository's naming convention for component props types. Rename the `Props` type to `TournamentErrorDialogProps` to match the pattern of {ComponentName}Props used throughout the codebase. Update this type name both at its declaration (around lines 14-18) and wherever it is used in the file, including line 58 where it appears to be referenced in the component function signature.Source: Coding guidelines
🤖 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/home/_components/invite-code-dialog/InviteCodeDialog.tsx`:
- Line 59: In the InviteCodeDialog component, the error handling for the
fallback case is missing a parent dialog closure. When
`setIsInvalidDialogOpen(true)` is called to open the InvalidCodeDialog, the
parent dialog should also be closed via `onOpenChange(false)` to match the
behavior of the 400/409 error branches. Add the `onOpenChange(false)` call
before `setIsInvalidDialogOpen(true)` to ensure consistent modal state
management across all error scenarios.
In `@apps/web/src/app/invite/`[id]/_components/InviteClient.tsx:
- Around line 47-50: The issue is that when a 409 error is caught and the
tournament error dialog is opened, the loading state is not updated, causing the
loading spinner to remain visible indefinitely. In the InviteClient.tsx file at
lines 47-50 (anchor), after calling setIsTournamentErrorDialogOpen(true), you
must also update the loading state variable to exit the 'loading' state
(typically set it to 'idle' or similar). The same fix must be applied to the
sibling location at lines 79-82 in the same file. Both 409 error handling
branches need the state transition added to prevent the UI from appearing stuck.
---
Outside diff comments:
In `@apps/web/src/app/tournament/join/`[id]/page.tsx:
- Around line 18-39: The invite code validation is incomplete and breaks the
invite-link-based join flow contract. In the page.tsx file at the searchParams
destructuring and code validation section, add a check to ensure `code` exists
and is not empty before passing it to JoinPreviewClient—call notFound() if the
code is missing or blank to prevent opening the join screen without a valid
invite code. In the JoinPreviewClient.tsx file at the request body construction
around lines 56-61, remove any conditional spread or optional inclusion of
inviteCode and ensure inviteCode is always included in the request body to
prevent omitting it on the join request.
---
Nitpick comments:
In
`@apps/web/src/app/tournament/`[id]/create/_components/TournamentCreateClient.tsx:
- Line 13: The import statement on line 13 mixes type and value imports in
violation of the type-only import separation rule, and uses a relative path
instead of the absolute path alias. Split the single import statement into two
separate imports: one using `import type` for the JoinConfirmPayloadT type
import, and another for the consumeJoinConfirmFor value import. Additionally,
replace the relative path `../../../join/_utils/joinSession` with the
corresponding absolute path using the `@/*` alias to comply with the absolute
path import rule.
In `@apps/web/src/components/tournament-error-dialog/index.tsx`:
- Around line 5-12: The import statement in tournament-error-dialog/index.tsx is
using a relative path import from '../dialog' which violates the coding
guidelines for apps/web/src. Replace the relative path import with the `@/`* alias
import pattern. Change the import statement to use `@/components/dialog` (or the
appropriate absolute path alias) instead of the relative '../dialog' path to
align with the project's import standards.
- Around line 14-18: The Props type declaration does not follow the repository's
naming convention for component props types. Rename the `Props` type to
`TournamentErrorDialogProps` to match the pattern of {ComponentName}Props used
throughout the codebase. Update this type name both at its declaration (around
lines 14-18) and wherever it is used in the file, including line 58 where it
appears to be referenced in the component function signature.
🪄 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: 419e912d-82df-4722-bec8-e2dfde7a6e27
📒 Files selected for processing (25)
apps/web/src/apis/client.tsapps/web/src/apis/getNicknameCheck.tsapps/web/src/app/home/_components/invite-code-dialog/InviteCodeDialog.tsxapps/web/src/app/invite/[id]/_components/InviteClient.tsxapps/web/src/app/login/_components/LoginButtons.tsxapps/web/src/app/login/_hooks/usePostGuestLogin.tsapps/web/src/app/mypage/edit/_apis/getNicknameCheck.tsapps/web/src/app/mypage/edit/_components/EditForm.tsxapps/web/src/app/mypage/edit/_hooks/useGetNicknameCheck.tsapps/web/src/app/mypage/edit/_hooks/usePatchMe.tsapps/web/src/app/tournament/[id]/create/_components/TournamentCreateClient.tsxapps/web/src/app/tournament/[id]/create/_components/welcome-join-dialog/WelcomeJoinDialog.tsxapps/web/src/app/tournament/[id]/create/page.tsxapps/web/src/app/tournament/join/[id]/_components/JoinPreviewClient.tsxapps/web/src/app/tournament/join/[id]/page.tsxapps/web/src/app/tournament/join/_apis/postJoin.tsapps/web/src/app/tournament/join/_hooks/usePostJoin.tsapps/web/src/app/tournament/join/_utils/joinSession.tsapps/web/src/components/tournament-error-dialog/index.tsxapps/web/src/consts/api.tsapps/web/src/consts/queryAction.tsapps/web/src/consts/route.tsapps/web/src/hooks/useGetNicknameCheck.tsapps/web/src/hooks/useNicknameValidation.tsapps/web/src/utils/getRouteType.ts
💤 Files with no reviewable changes (5)
- apps/web/src/app/tournament/join/_utils/joinSession.ts
- apps/web/src/app/mypage/edit/_hooks/useGetNicknameCheck.ts
- apps/web/src/app/mypage/edit/_apis/getNicknameCheck.ts
- apps/web/src/app/mypage/edit/_hooks/usePatchMe.ts
- apps/web/src/consts/api.ts
작업 요약
작업 내용
초대 링크 진입 플로우
/invite/{id}?code=검증 후 join 미리보기에서 닉네임 설정 및 참여postJoin후/tournament/{id}/create?action=welcome-join으로 바로 이동useQueryAction+welcome-join쿼리로 합류 후WelcomeJoinDialog바텀시트 노출에러 처리
TournamentErrorDialog공통 컴포넌트 추출LINK_EXPIRED타입 다이얼로그 표시InviteCodeDialog)InviteClient)JoinPreviewClient)인증 / 라우팅
/invite경로MEMBER_AND_GUEST등록 → 비로그인 초대 링크 접근 시 proxy 자동 게스트 로그인sessionStorage에 저장된 redirect 경로로 이동X-Client-Type헤더 추가리팩토링
useNicknameValidation훅 공통화 (join 미리보기, 마이페이지 수정)src/apis,src/hooks공통 모듈 사용postJoinAPI 및usePostJoin훅 추가 (게스트/회원 공통 참여)스크린샷
2026-06-17.12.38.59.mov
연관 이슈
close #207
Summary by CodeRabbit
릴리스 노트