Skip to content

[Feature/#368] 워크스페이스 초대 수락 페이지 연동 - #376

Merged
jjjsun merged 11 commits into
developfrom
feature/#368
Aug 2, 2026
Merged

jjjsun merged 11 commits into
developfrom
feature/#368

Conversation

@jjjsun

@jjjsun jjjsun commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

🚨 관련 이슈

Closed #368

✨ 변경사항

  • 🐞 BugFix Something isn't working
  • 💻 CrossBrowsing Browser compatibility
  • 🌏 Deploy Deploy
  • 🎨 Design Markup & styling
  • 📃 Docs Documentation writing and editing (README.md, etc.)
  • ✨ Feature Feature
  • 🔨 Refactor Code refactoring
  • ⚙️ Setting Development environment setup
  • ✅ Test Test related (storybook, jest, etc.)

✏️ 작업 내용

메일 링크 /invite/{token} 진입 시 초대 수락하는 페이지 연동했습니다.

  • 초대 수락 페이지 UI
    • 로딩: 초대 확인 / 워크스페이스로 이동
    • 로그인됨: 수락 API호출 → orgId 기준으로 현재워크스페이스 저장 →/dashboard로 이동
    • 미로그인: 스패너 + 초 수 카운트다운후(3초) login?returnUrl=/invite/{token}으로 이동
    • 에러: 만료 / 이미 수락 / 이메일 불일치 등 ErrorLayout 안내

💻 작업 화면

image image image image

😅 미완성 작업

  • 회원가입 완료 후 로그인 페이지 미이동 이슈는 다음 후속이슈로 처리 예정입니다 (초대링크테스트도중 확인한 버그. 현재 브랜치와는 내용이 맞지 않아 따로 브랜치파서 진행예정)

📢 논의 사항 및 참고 사항

  • 현재 로컬 메일 링크 origin이 localhost:3000으로 오고 있어서, 프론트에서 test진행할때는 직접 포트 5173으로 바꿔서 진행하면 잘 작동됩니다! 백엔드에게는 배포환경인 whereyouad.com으로 변경요청드린상태입니다 (8/2 02:30 기준- 아직 답변전) → (8/3 10:50 기준 배포환경으로 세팅완료)

  • 초대 링크/멤버 테스트 과정중에 멤버삭제에서 서버500에러가 발생하고 있어서 백엔드에 확인요청해둔상황입니다 (8/2 02:30 기준- 아직 답변전) -> (8/3 10:50 기준 버그 수정 완료)

  • 최대한 많은 에러상황을 테스트중입니다만, 아직 멤버 삭제가 진행되지않아 계정개수한계로 많은 테스트는 하지못했습니다! 멤버분들께서 test중 다른 에러가 발견되면 알려주시면 감사하겠습니다! 바로 수정진행하겠습니다!

💬 리뷰어 가이드 (P-Rules)
P1: 필수 반영 (Critical) - 버그 가능성, 컨벤션 위반. 해결 전 머지 불가.
P2: 적극 권장 (Recommended) - 더 나은 대안 제시. 가급적 반영 권장.
P3: 제안 (Suggestion) - 아이디어 공유. 반영 여부는 드라이버 자율.
P4: 단순 확인/칭찬 (Nit) - 사소한 오타, 칭찬 등 피드백.

Summary by CodeRabbit

Summary by CodeRabbit

  • 새 기능

    • 초대 링크를 통해 워크스페이스 초대를 수락할 수 있습니다.
    • 초대 토큰을 확인하고 수락한 뒤 해당 워크스페이스로 이동합니다.
    • 로그인하지 않은 경우 로그인 후 초대 페이지로 돌아갈 수 있습니다.
    • 초대 토큰 누락 및 수락 실패 상황에 맞는 안내와 이동 버튼을 제공합니다.
  • 버그 수정

    • 오류 메시지의 실제 줄바꿈과 \n 형식이 올바르게 표시됩니다.

@jjjsun
jjjsun requested review from Seojegyeong and YermIm August 1, 2026 17:41
@jjjsun jjjsun self-assigned this Aug 1, 2026
@jjjsun jjjsun added 🎨 Html&css 마크업 & 스타일링 ✨ Feature 기능 개발 📬 API 서버 API 통신 labels Aug 1, 2026
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jjjsun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 12ba9ae2-eebb-42d2-b974-56385c0d3344

📥 Commits

Reviewing files that changed from the base of the PR and between 9f52a1f and c7a55e0.

📒 Files selected for processing (1)
  • src/pages/workspace/InviteAcceptPage.tsx
📝 Walkthrough

Walkthrough

워크스페이스 초대 수락 API와 응답 타입을 추가했습니다. /invite/:token 라우트와 페이지를 구현했습니다. 로그인 상태에 따라 초대를 수락하거나 로그인 페이지로 이동합니다. 오류 유형별 메시지와 여러 줄 텍스트 표시를 지원합니다.

Changes

워크스페이스 초대 수락

Layer / File(s) Summary
초대 수락 API 계약
src/types/workspace/workspace.ts, src/api/workspace/org.ts
TAcceptInvitationResponse 타입과 acceptInvitaton API 함수를 추가했습니다. 함수는 초대 토큰으로 POST 요청을 보내고 응답 데이터를 반환합니다.
초대 페이지 처리 흐름
src/routes/AuthRoutes.tsx, src/pages/workspace/InviteAcceptPage.tsx
invite/:token 라우트를 지연 로딩으로 연결했습니다. 로그인 사용자는 초대를 수락한 뒤 워크스페이스를 저장하고 대시보드로 이동합니다. 비로그인 사용자는 returnUrl과 함께 로그인 페이지로 이동합니다.
초대 오류 및 상태 표시
src/pages/workspace/InviteAcceptPage.tsx, src/components/common/error/ErrorLayout.tsx
만료, 이미 수락됨, 이메일 불일치 및 일반 오류를 구분해 표시합니다. 로딩, 카운트다운 및 처리 중 상태를 렌더링합니다. 실제 개행과 리터럴 \n을 줄바꿈으로 표시합니다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant 사용자
  participant AuthRoutes
  participant InviteAcceptPage
  participant 인증상태
  participant 초대API
  participant 워크스페이스저장소
  participant 쿼리캐시
  participant 대시보드

  사용자->>AuthRoutes: /invite/:token 접근
  AuthRoutes->>InviteAcceptPage: 페이지 렌더링
  InviteAcceptPage->>인증상태: 초기화 및 로그인 상태 확인
  alt 비로그인 상태
    InviteAcceptPage-->>사용자: returnUrl 포함 로그인 페이지로 이동
  else 로그인 상태
    InviteAcceptPage->>초대API: 초대 토큰으로 POST 요청
    초대API-->>InviteAcceptPage: 초대 수락 응답 반환
    InviteAcceptPage->>워크스페이스저장소: orgId 저장
    InviteAcceptPage->>쿼리캐시: 관련 쿼리 무효화
    InviteAcceptPage->>대시보드: 워크스페이스 이동
  end
Loading

Possibly related PRs

Suggested reviewers: yermim, seojegyeong

🚥 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
Title check ✅ Passed 제목이 워크스페이스 초대 수락 페이지 연동이라는 주요 변경사항을 명확하고 간결하게 설명합니다.
Description check ✅ Passed 관련 이슈, 변경사항, 작업 내용, 미완성 작업, 참고 사항을 포함해 템플릿을 대부분 충족합니다.
Linked Issues check ✅ Passed 라우트, 초대 수락 API, 상태별 UI, 로그인 리다이렉트, 워크스페이스 이동, 오류 처리를 모두 구현해 이슈 #368의 목표를 충족합니다.
Out of Scope Changes check ✅ Passed 변경된 API, 타입, 페이지, 라우트, 오류 레이아웃은 모두 초대 수락 흐름 구현 범위에 포함됩니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#368

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.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

📚 Storybook 배포 완료

항목 링크
📖 Storybook https://69a147b60a56365d9e2185ef-rzwchptphj.chromatic.com/
🔍 Chromatic https://www.chromatic.com/build?appId=69a147b60a56365d9e2185ef&number=520

@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: 5

🧹 Nitpick comments (1)
src/pages/workspace/InviteAcceptPage.tsx (1)

188-203: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

카운트다운 문구가 바뀔 때 스크린 리더에 알림이 가지 않습니다.

ErrorLayoutrole="status"로 동적 텍스트 변경을 스크린 리더에 알립니다. 이 블록에는 그런 처리가 없어 {countdown}초 후 로그인 페이지로 이동합니다 텍스트가 매초 바뀌어도 알림이 발생하지 않습니다. 이 divrole="status" 또는 aria-live="polite"를 추가해 주세요.

♻️ 제안 수정
-      <div className="relative flex h-screen w-full flex-col items-center justify-center gap-5 bg-surface-100">
+      <div
+        className="relative flex h-screen w-full flex-col items-center justify-center gap-5 bg-surface-100"
+        role="status"
+      >
🤖 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/pages/workspace/InviteAcceptPage.tsx` around lines 188 - 203, Update the
needLogin countdown container in InviteAcceptPage to expose dynamic countdown
changes to screen readers by adding role="status" or aria-live="polite" to the
existing div, while preserving its current content and layout.
🤖 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 `@src/api/workspace/org.ts`:
- Line 3: Rename TAcceptInvitationResponse in src/types/workspace/workspace.ts
to the required I-prefixed API response type, then update the import in this
file and the acceptInvitaton return type declaration to use the new name
consistently.

In `@src/pages/workspace/InviteAcceptPage.tsx`:
- Around line 105-127: Refactor the invitation acceptance flow in
InviteAcceptPage to use useCoreMutation from customQuery instead of directly
calling acceptInvitaton inside the effect. Move the existing workspace
persistence, query invalidation, success toast, status update, and navigation
into the mutation’s onSuccess handler, and map the API error and error status in
onError; derive loading, success, and failure UI state from the mutation
lifecycle rather than maintaining duplicate manual state.
- Around line 98-127: Update the invite-accept flow before the `accept` function
starts, after the `isLoggedIn` and `processedRef` checks, to set the status to
`"loading"`. This must clear the prior `"needLogin"` state and prevent its
redirect timer while `acceptInvitaton` runs, allowing the existing success and
error paths to determine the final status.
- Around line 82-103: Update processedRef in the invite acceptance effect to
store the previously processed token rather than a boolean. In the effect around
isTokenInitialized and accept(), skip processing only when processedRef.current
equals the current token, then record the current token before accepting so
navigation to a different token runs the acceptance flow again.

In `@src/types/workspace/workspace.ts`:
- Around line 127-132: Rename the API response type TAcceptInvitationResponse to
IAcceptInvitationResponse in workspace.ts, then update the import and all
references in org.ts to use the new name while preserving the existing response
shape.

---

Nitpick comments:
In `@src/pages/workspace/InviteAcceptPage.tsx`:
- Around line 188-203: Update the needLogin countdown container in
InviteAcceptPage to expose dynamic countdown changes to screen readers by adding
role="status" or aria-live="polite" to the existing div, while preserving its
current content and layout.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 94002a62-1ce1-471b-80cf-7168b9ff52cd

📥 Commits

Reviewing files that changed from the base of the PR and between f087cb5 and f515899.

📒 Files selected for processing (5)
  • src/api/workspace/org.ts
  • src/components/common/error/ErrorLayout.tsx
  • src/pages/workspace/InviteAcceptPage.tsx
  • src/routes/AuthRoutes.tsx
  • src/types/workspace/workspace.ts

Comment thread src/api/workspace/org.ts
Comment thread src/pages/workspace/InviteAcceptPage.tsx Outdated
Comment thread src/pages/workspace/InviteAcceptPage.tsx Outdated
Comment thread src/pages/workspace/InviteAcceptPage.tsx Outdated
Comment thread src/types/workspace/workspace.ts

@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: 2

🧹 Nitpick comments (3)
src/pages/workspace/InviteAcceptPage.tsx (3)

29-78: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

오류 코드/메시지 부분 문자열 매칭은 오분류 위험이 있습니다.

getInviteErrorCopycode.includes(...)message.includes(...)로 오류 유형을 판별합니다. 백엔드 오류 코드가 정확히 문서화되지 않은 상태에서 부분 문자열 매칭을 사용하면, 의도치 않은 코드나 메시지가 다른 유형으로 잘못 분류될 수 있습니다. 예를 들어 code.includes("EMAIL")은 이메일 불일치가 아닌 다른 코드에도 매칭될 수 있습니다.

가능하다면 백엔드에서 제공하는 정확한 오류 코드 값과 === 비교를 우선 사용하고, 메시지 매칭은 폴백으로만 사용하는 방식을 권장합니다.


백엔드 초대 수락 API(POST /api/org/invitations/{token})가 만료, 이미 수락됨, 이메일 불일치 오류에 대해 어떤 고정된 code 값을 반환하는지 확인해 주실 수 있나요?

🤖 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/pages/workspace/InviteAcceptPage.tsx` around lines 29 - 78, Update
getInviteErrorCopy to classify invitation errors using the backend’s exact
documented code values with strict equality checks, covering expired,
already-accepted, and email-mismatch cases. Keep message matching only as a
fallback when no recognized code is present, and avoid broad code.includes
checks that can misclassify unrelated errors.

80-131: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

페이지 컴포넌트에 초대 수락 로직이 과도하게 집중되어 있습니다.

InviteAcceptPage에는 mutation 설정, 두 개의 useEffect, processedRef/acceptInviteRef 관리 로직이 모두 한 컴포넌트에 있습니다. 이 로직을 useInviteAccept와 같은 커스텀 훅으로 분리하면 페이지 컴포넌트는 UI 렌더링에만 집중할 수 있고, 로직 단위 테스트도 쉬워집니다.

As per path instructions, "구조와 책임 분리: 페이지에 비즈니스 로직이 과도하지 않은지 확인. 커스텀 훅으로의 분리 여부 검토."

🤖 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/pages/workspace/InviteAcceptPage.tsx` around lines 80 - 131, Extract the
invitation acceptance state, mutation configuration, authentication/token
checks, redirect countdown handling, and related refs/effects from
InviteAcceptPage into a dedicated useInviteAccept hook. Expose the UI state and
handlers/data needed for rendering, while preserving the existing success,
error, navigation, and duplicate-token behavior so InviteAcceptPage is
responsible only for presentation.

Source: Path instructions


194-219: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

로딩/성공 상태 전환을 스크린 리더에 알리는 속성이 없습니다.

needLogin, loading, success 상태 텍스트는 순수 시각적 애니메이션(animate-spin, animate-pulse)으로만 표현되고, 상태 전환을 알리는 aria-live 속성이 없습니다. 스크린 리더 사용자는 로그인 필요 안내, 카운트다운, 수락 완료 등의 변화를 인지하기 어렵습니다.

상태 텍스트를 감싸는 컨테이너에 role="status" aria-live="polite"를 추가해 주세요.

As per path instructions, "접근성: 시맨틱 HTML, ARIA 속성 사용 확인."

♻️ 제안 수정
   if (uiStatus === "needLogin") {
     return (
-      <div className="relative flex h-screen w-full flex-col items-center justify-center gap-5 bg-surface-100">
+      <div
+        className="relative flex h-screen w-full flex-col items-center justify-center gap-5 bg-surface-100"
+        role="status"
+        aria-live="polite"
+      >
   return (
-    <div className="relative flex h-screen w-full items-center justify-center bg-surface-100">
+    <div
+      className="relative flex h-screen w-full items-center justify-center bg-surface-100"
+      role="status"
+      aria-live="polite"
+    >
🤖 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/pages/workspace/InviteAcceptPage.tsx` around lines 194 - 219, 상태 전환을 스크린
리더에 알리도록 InviteAcceptPage의 needLogin 분기와 loading/success 결과 렌더링에서 상태 텍스트를 감싸는
컨테이너에 role="status"와 aria-live="polite"를 추가하세요. 기존 시각적 애니메이션과 메시지 조건은 유지하고, 로그인
안내·카운트다운·수락 완료 및 로딩 상태가 변경될 때 해당 컨테이너가 이를 전달하도록 적용하세요.

Source: Path instructions

🤖 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 `@src/pages/workspace/InviteAcceptPage.tsx`:
- Around line 96-98: Update the mutation configuration in the invitation
acceptance flow around userOnSuccess and saveSelectedWorkspace so
workspace.saved() is not invalidated before the newly selected workspace is
saved. Keep workspace.list() invalidation, and either remove workspace.saved()
from invalidateKeys or explicitly invalidate it after
saveSelectedWorkspace(data.orgId) completes.
- Around line 95-108: Wrap the saveSelectedWorkspace call in the userOnSuccess
handler of useCoreMutation with try/catch so a persistence failure cannot leave
uiStatus stuck at "loading". On failure, set the acceptance error and transition
to "error" via the existing setAcceptError and setUiStatus handlers; only update
the selected organization, show the success toast, mark success, and navigate
after workspace saving succeeds.

---

Nitpick comments:
In `@src/pages/workspace/InviteAcceptPage.tsx`:
- Around line 29-78: Update getInviteErrorCopy to classify invitation errors
using the backend’s exact documented code values with strict equality checks,
covering expired, already-accepted, and email-mismatch cases. Keep message
matching only as a fallback when no recognized code is present, and avoid broad
code.includes checks that can misclassify unrelated errors.
- Around line 80-131: Extract the invitation acceptance state, mutation
configuration, authentication/token checks, redirect countdown handling, and
related refs/effects from InviteAcceptPage into a dedicated useInviteAccept
hook. Expose the UI state and handlers/data needed for rendering, while
preserving the existing success, error, navigation, and duplicate-token behavior
so InviteAcceptPage is responsible only for presentation.
- Around line 194-219: 상태 전환을 스크린 리더에 알리도록 InviteAcceptPage의 needLogin 분기와
loading/success 결과 렌더링에서 상태 텍스트를 감싸는 컨테이너에 role="status"와 aria-live="polite"를
추가하세요. 기존 시각적 애니메이션과 메시지 조건은 유지하고, 로그인 안내·카운트다운·수락 완료 및 로딩 상태가 변경될 때 해당 컨테이너가 이를
전달하도록 적용하세요.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 68e6c7ed-178c-4192-aaa6-4d0cecb066ad

📥 Commits

Reviewing files that changed from the base of the PR and between f515899 and 9f52a1f.

📒 Files selected for processing (1)
  • src/pages/workspace/InviteAcceptPage.tsx

Comment thread src/pages/workspace/InviteAcceptPage.tsx
Comment thread src/pages/workspace/InviteAcceptPage.tsx Outdated
@jjjsun
jjjsun merged commit b1f1119 into develop Aug 2, 2026
3 checks passed
@jjjsun
jjjsun deleted the feature/#368 branch August 2, 2026 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📬 API 서버 API 통신 ✨ Feature 기능 개발 🎨 Html&css 마크업 & 스타일링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ [Feature] 워크스페이스 초대 수락 페이지 연동

2 participants