Skip to content

feat: #267 뱃지 & 레벨 목록 페이지 추가#270

Merged
FLYLIKEB merged 4 commits intomainfrom
feature/issue-267-badge-page
Mar 16, 2026
Merged

feat: #267 뱃지 & 레벨 목록 페이지 추가#270
FLYLIKEB merged 4 commits intomainfrom
feature/issue-267-badge-page

Conversation

@FLYLIKEB
Copy link
Copy Markdown
Owner

@FLYLIKEB FLYLIKEB commented Mar 16, 2026

Summary

  • Closes feat: 뱃지 목록 페이지 추가 (내 차록 뱃지 확인) #267
  • 뱃지 6종과 레벨 3카테고리(차록/게시글/찻장)를 전용 페이지에서 확인 가능
  • 획득/미획득 뱃지 시각적 구분, 레벨 진행률 바 표시
  • 프로필 페이지에서 뱃지 페이지로 이동 링크 추가
  • usersApi.getLevel에 TypeScript 제네릭 타입 추가

Test plan

  • npm run build
  • npm run test:run (Badges 7/7 통과)
  • /badges 페이지 직접 접근 확인
  • 프로필 → 뱃지 링크 이동 확인
  • 비로그인 상태 로그인 유도 확인

🤖 Generated with Claude Code

Summary by CodeRabbit

새로운 기능

  • 사용자가 획득한 뱃지와 각 카테고리별 레벨 정보를 확인할 수 있는 뱃지 페이지 추가
  • 프로필의 뱃지 섹션을 통해 뱃지 페이지로 바로 이동 가능
  • 각 뱃지별 획득 조건과 진행 상황을 시각적으로 표시
  • 미획득 뱃지와 획득한 뱃지의 상태를 구분하여 표시

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 16, 2026

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

Project Deployment Actions Updated (UTC)
cha-log Ready Ready Preview, Comment Mar 16, 2026 4:46am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 16, 2026

Warning

Rate limit exceeded

@FLYLIKEB has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 34 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e9e59351-9253-4342-a6d5-8598e27e836d

📥 Commits

Reviewing files that changed from the base of the PR and between 8bbb2e1 and 47ba0e4.

📒 Files selected for processing (3)
  • src/constants/badges.ts
  • src/pages/Badges.tsx
  • src/pages/__tests__/Badges.test.tsx

Walkthrough

뱃지 목록 페이지 기능을 추가합니다. 새로운 Badges 페이지 컴포넌트를 구현하고, 라우팅을 등록하며, 뱃지 정의 및 레벨 티어 데이터를 상수로 관리합니다. 프로필 페이지에서 뱃지 섹션으로의 네비게이션 링크를 추가합니다.

Changes

Cohort / File(s) Summary
라우팅 및 앱 구조
src/App.tsx
Badges 페이지를 lazy-loaded 컴포넌트로 임포트하고 /badges 경로에 대한 라우트를 추가합니다.
뱃지 데이터 및 상수
src/constants/badges.ts
BadgeDefinition, LevelTier 인터페이스와 ALL_BADGES, NOTE_LEVEL_TIERS, POST_LEVEL_TIERS, CELLAR_LEVEL_TIERS, LEVEL_CATEGORIES 상수를 정의하여 뱃지 및 레벨 데이터를 관리합니다.
API 타입 안전성
src/lib/api/users.api.ts
getLevel API 호출에 UserLevel 제네릭 타입을 추가하여 응답 타입을 명시합니다.
프로필 UI 업데이트
src/components/profile/ProfileStats.tsx
뱃지 섹션을 /badges 경로로의 링크로 감싸고, ChevronRight 아이콘과 조건부 렌더링을 추가하여 뱃지가 없을 때 안내 텍스트를 표시합니다.
뱃지 페이지 구현
src/pages/Badges.tsx
사용자 레벨 데이터를 조회하여 획득한 뱃지와 미획득 뱃지를 구분하여 표시하는 대시보드 페이지를 구현합니다. 레벨 카테고리별 진행률과 뱃지 그리드를 포함합니다.
페이지 테스트
src/pages/__tests__/Badges.test.tsx
인증 상태, 로딩 상태, 뱃지 렌더링, 레벨 진행률 표시 등을 검증하는 포괄적인 테스트 스위트를 추가합니다.

Sequence Diagram

sequenceDiagram
    participant User
    participant App as Badges Page
    participant Auth as useAuth
    participant API as usersApi.getLevel
    participant Toast as Toast Notification

    User->>App: Navigate to /badges
    App->>Auth: Check auth state
    
    alt User not authenticated
        Auth-->>App: user = null
        App->>User: Show login prompt
        User->>App: Click login button
        App->>User: Redirect to login
    else User authenticated
        Auth-->>App: user data available
        App->>App: Show loading indicator
        App->>API: Fetch user level data
        API-->>App: Return UserLevel
        App->>App: Compute earned badges
        App->>App: Render level categories
        App->>App: Render badge grid
        Note over App: Display earned badges with Award icon<br/>Display locked badges with Lock icon
        App->>User: Display badges dashboard
    end
    
    alt API Error
        API-->>Toast: Error occurred
        Toast->>User: Show error message
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 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 The title clearly describes the main change: adding a badges and levels list page (뱃지 & 레벨 목록 페이지 추가), which aligns with issue #267.
Linked Issues check ✅ Passed All requirements from issue #267 are met: badges page created, badges and conditions displayed, earned vs. unearned badges distinguished, and navigation link added from profile page.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #267: new Badges page, badge constants, level data typing, profile integration, and comprehensive tests—no out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/issue-267-badge-page
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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 (1)
src/components/profile/ProfileStats.tsx (1)

48-64: 링크 접근성 힌트를 조금만 보강하면 더 좋습니다.

현재도 동작은 좋습니다. 다만 링크 목적을 명확히 하기 위해 aria-labelfocus-visible 스타일을 추가해두면 접근성이 더 좋아집니다.

✏️ 제안 diff
-          <Link to="/badges" className="flex items-center justify-between group">
+          <Link
+            to="/badges"
+            aria-label="뱃지 및 레벨 페이지로 이동"
+            className="flex items-center justify-between group rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
+          >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/profile/ProfileStats.tsx` around lines 48 - 64, The Link
component rendering the badges (the <Link ...> that wraps the userLevel.badges
list and ChevronRight) should include an explicit aria-label describing the link
target (e.g., "View badges" or localized text) and a visible focus style for
keyboard users; update the Link props to add aria-label and augment its
className with a focus-visible utility (or a11y-focused CSS class) so keyboard
focus shows a clear outline (e.g., focus-visible:ring / focus-visible:outline)
while keeping existing styles, ensuring the change is applied to the Link that
contains userLevel.badges and the ChevronRight.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pages/Badges.tsx`:
- Around line 64-67: The progressPercent calculation currently uses info.count /
info.nextThreshold which ignores the current tier start and overstates progress;
change progressPercent (and the similar calculation at the other occurrence) to
compute the progress within the current tier by subtracting the current-tier
threshold start: let start = info.prevThreshold ?? info.currentThreshold ?? 0;
let range = info.nextThreshold - start; let progress = Math.max(0, info.count -
start); set progressPercent = range > 0 ? Math.round((progress / range) * 100) :
100 and clamp to 0–100. Update both occurrences (the progressPercent assignment
and the duplicate at the later location) and keep references to
info.nextThreshold and info.count.

---

Nitpick comments:
In `@src/components/profile/ProfileStats.tsx`:
- Around line 48-64: The Link component rendering the badges (the <Link ...>
that wraps the userLevel.badges list and ChevronRight) should include an
explicit aria-label describing the link target (e.g., "View badges" or localized
text) and a visible focus style for keyboard users; update the Link props to add
aria-label and augment its className with a focus-visible utility (or
a11y-focused CSS class) so keyboard focus shows a clear outline (e.g.,
focus-visible:ring / focus-visible:outline) while keeping existing styles,
ensuring the change is applied to the Link that contains userLevel.badges and
the ChevronRight.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 983210ed-7873-453c-90d3-7d9b71c6bdb1

📥 Commits

Reviewing files that changed from the base of the PR and between 022b5ed and 8bbb2e1.

📒 Files selected for processing (6)
  • src/App.tsx
  • src/components/profile/ProfileStats.tsx
  • src/constants/badges.ts
  • src/lib/api/users.api.ts
  • src/pages/Badges.tsx
  • src/pages/__tests__/Badges.test.tsx

Comment thread src/pages/Badges.tsx
Comment on lines +64 to +67
const progressPercent =
info.nextThreshold !== null && info.nextThreshold > 0
? Math.round((info.count / info.nextThreshold) * 100)
: 100;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

진행률 계산이 현재 레벨 구간 기준이 아니라 과대 표기됩니다.

count / nextThreshold는 현재 레벨 시작점을 반영하지 않아, 레벨업 직후에도 진행률이 높게 보입니다. 현재 티어 threshold를 빼서 구간 진행률로 계산하는 편이 정확합니다.

🐛 제안 diff
-            const progressPercent =
-              info.nextThreshold !== null && info.nextThreshold > 0
-                ? Math.round((info.count / info.nextThreshold) * 100)
-                : 100;
+            const currentThreshold = tiers.find((tier) => tier.level === info.level)?.threshold ?? 0;
+            const progressPercent =
+              info.nextThreshold !== null && info.nextThreshold > currentThreshold
+                ? Math.round(((info.count - currentThreshold) / (info.nextThreshold - currentThreshold)) * 100)
+                : 100;
@@
-                <Progress value={Math.min(progressPercent, 100)} className="h-2" />
+                <Progress value={Math.max(0, Math.min(progressPercent, 100))} className="h-2" />

Also applies to: 78-78

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Badges.tsx` around lines 64 - 67, The progressPercent calculation
currently uses info.count / info.nextThreshold which ignores the current tier
start and overstates progress; change progressPercent (and the similar
calculation at the other occurrence) to compute the progress within the current
tier by subtracting the current-tier threshold start: let start =
info.prevThreshold ?? info.currentThreshold ?? 0; let range = info.nextThreshold
- start; let progress = Math.max(0, info.count - start); set progressPercent =
range > 0 ? Math.round((progress / range) * 100) : 100 and clamp to 0–100.
Update both occurrences (the progressPercent assignment and the duplicate at the
later location) and keep references to info.nextThreshold and info.count.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@FLYLIKEB FLYLIKEB merged commit f4847e3 into main Mar 16, 2026
3 checks passed
@FLYLIKEB FLYLIKEB deleted the feature/issue-267-badge-page branch March 16, 2026 04:48
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.

feat: 뱃지 목록 페이지 추가 (내 차록 뱃지 확인)

1 participant