Skip to content

[Refactor] WTH-358 : 출석 어드민 기수 조회 시 전체 기수 부터 표시되게 수정#89

Merged
nabbang6 merged 6 commits intodevelopfrom
WTH-358/출석-어드민-기수-조회-시-전체-기수-부터-표시되게-수정
Apr 29, 2026

Hidden character warning

The head ref may contain hidden characters: "WTH-358/\ucd9c\uc11d-\uc5b4\ub4dc\ubbfc-\uae30\uc218-\uc870\ud68c-\uc2dc-\uc804\uccb4-\uae30\uc218-\ubd80\ud130-\ud45c\uc2dc\ub418\uac8c-\uc218\uc815"
Merged

[Refactor] WTH-358 : 출석 어드민 기수 조회 시 전체 기수 부터 표시되게 수정#89
nabbang6 merged 6 commits intodevelopfrom
WTH-358/출석-어드민-기수-조회-시-전체-기수-부터-표시되게-수정

Conversation

@nabbang6
Copy link
Copy Markdown
Collaborator

@nabbang6 nabbang6 commented Apr 29, 2026

✅ PR 유형

어떤 변경 사항이 있었나요?

  • 새로운 기능 추가
  • 버그 수정
  • 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
  • 코드 리팩토링
  • 주석 추가 및 수정
  • 문서 수정
  • 빌드 부분 혹은 패키지 매니저 수정
  • 파일 혹은 폴더명 수정
  • 파일 혹은 폴더 삭제

📌 관련 이슈번호

  • Closed

✅ Key Changes

  • 어드민 출석에서 기수 조회 시 전체 기수 확인되도록 수정
  • 전체 기수 조회 시 모든 세션을 불러올 수 있도록 수정
  • 어드민 출석에서 스켈레톤 및 반응형(가로 스크롤) 적용

📸 스크린샷 or 실행영상

2026-04-29.225521.mp4

🎸 기타 사항 or 추가 코멘트

스켈레톤도 빠져 잇길래...
급하게 추가햇습니다...

Summary by CodeRabbit

출시 노트

  • 새 기능

    • 전체 선택 옵션이 추가되었습니다.
  • 개선 사항

    • 데이터 로딩 중 로딩 스켈레톤을 표시합니다.
    • 세션 데이터가 없을 때 개선된 빈 상태 화면을 표시합니다.
    • 페이지 레이아웃과 스타일이 최적화되었습니다.

@nabbang6 nabbang6 requested review from JIN921, dalzzy and woneeeee April 29, 2026 14:03
@nabbang6 nabbang6 self-assigned this Apr 29, 2026
@nabbang6 nabbang6 added the 🔨 Refactor 코드 리팩토링 label Apr 29, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

Warning

Rate limit exceeded

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

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ 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: 35d22e60-a7e9-4a15-bf2d-0eed764b8ecb

📥 Commits

Reviewing files that changed from the base of the PR and between bdc097e and 435155d.

📒 Files selected for processing (3)
  • src/components/admin/attendance/AttendanceCard.tsx
  • src/components/admin/attendance/AttendancePageContent.tsx
  • src/components/admin/attendance/AttendanceSessionCard.tsx
📝 Walkthrough

개요

출석 페이지의 cardinal 선택 처리를 개선하여, null 값으로 "모두 선택" 기능을 지원하도록 변경했습니다. API 계층에서 cardinal 파라미터를 선택적으로 처리하고, 세션 로딩 상태에 따른 UI 분기를 추가했습니다.

변경사항

Cohort / File(s) Summary
UI 컴포넌트
src/components/admin/attendance/AttendancePageContent.tsx
Cardinal 선택 핸들러가 null 값을 수락하도록 변경, CardinalDropdownonSelectAll 콜백 추가. 세션 로딩 상태에 따라 Skeleton 행 또는 실제 세션을 렌더링하는 분기 로직 추가, 레이아웃 최소 너비 및 오버플로우 스타일 조정.
쿼리 훅
src/hooks/queries/admin/useAdminAttendanceQueries.ts
useAdminSessions 쿼리가 cardinalnull일 때도 실행되도록 변경. Cardinal 값이 없을 때 undefined로 처리하여 API 호출 시 null 단언문 제거.
API 계층
src/lib/apis/adminAttendance.ts
getSessions 함수의 cardinal 파라미터를 선택적(cardinal?: number)으로 변경. Cardinal 값이 있을 때만 쿼리 파라미터에 포함하도록 조정.

예상 코드 리뷰 난이도

🎯 3 (중간 난이도) | ⏱️ ~25분

관련 가능성 있는 PR

제안 라벨

📬 API

제안 검토자

  • JIN921
  • dalzzy
  • woneeeee

시 🐰

Cardinal이 텅 비어도 괜찮아 🌙
Null을 받아들이는 날
모두 함께 선택되고 ✨
로딩 중엔 Skeleton이 춤을 추고
세션들이 반짝반짝 나타나네! 🎉

🚥 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 PR 제목이 변경 사항의 주요 내용을 명확하게 요약하고 있습니다. 출석 어드민 기수 조회 시 전체 기수부터 표시되도록 수정된 것이 핵심 변경사항입니다.
Description check ✅ Passed PR 설명이 템플릿 구조를 따르고 있으며, PR 유형(코드 리팩토링)을 명시했고 주요 변경사항과 스크린샷을 포함하고 있습니다. 다만 관련 이슈번호가 입력되지 않았습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 WTH-358/출석-어드민-기수-조회-시-전체-기수-부터-표시되게-수정

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
Review rate limit: 0/1 reviews remaining, refill in 41 minutes and 35 seconds.

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

Copy link
Copy Markdown

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/admin/attendance/AttendancePageContent.tsx (2)

46-49: ⚠️ Potential issue | 🔴 Critical

더티 상태에서 “전체 기수(null)” 변경이 적용되지 않습니다.

Line 46 조건(pendingCardinalId !== null) 때문에, “전체 기수”를 선택하고 확인해도 setSelectedCardinalId가 호출되지 않습니다. 변경 목적을 직접 깨는 로직 버그입니다.

🔧 제안 수정안
-  const [pendingCardinalId, setPendingCardinalId] = useState<number | null>(null);
+  const [pendingCardinalId, setPendingCardinalId] = useState<number | null | undefined>(
+    undefined,
+  );

  const confirmCardinalChange = () => {
    setDirtyCardIds(new Set());
    setCardinalDialogOpen(false);
-    if (pendingCardinalId !== null) {
+    if (pendingCardinalId !== undefined) {
       setSelectedCardinalId(pendingCardinalId);
-      setPendingCardinalId(null);
+      setPendingCardinalId(undefined);
     }
  };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/admin/attendance/AttendancePageContent.tsx` around lines 46 -
49, The condition currently prevents applying a "null" selection because it only
runs when pendingCardinalId !== null; change the guard to allow null values
(e.g., check for undefined instead) or simply always apply the pending value:
replace the if (pendingCardinalId !== null) {
setSelectedCardinalId(pendingCardinalId); setPendingCardinalId(null); } with a
check like if (pendingCardinalId !== undefined) {
setSelectedCardinalId(pendingCardinalId); setPendingCardinalId(null); }
(referencing pendingCardinalId, setSelectedCardinalId, setPendingCardinalId).

22-41: ⚠️ Potential issue | 🟡 Minor

useCallback 제거를 권장합니다.

React Compiler가 활성화된 환경에서 AttendanceSessionCardCardinalDropdown 모두 React.memo를 사용하지 않으므로, 이 콜백들의 참조 안정성은 성능 최적화에 영향을 주지 않습니다. React Compiler가 자동으로 함수 최적화를 처리하므로 일반 함수로 구현하는 것이 더 단순합니다. 프로젝트 가이드라인(useMemo, useCallback, React.memo는 실제 필요한 경우를 제외하고 불필요)에 따라 두 useCallback을 제거하고 일반 함수로 변경하세요.

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

In `@src/components/admin/attendance/AttendancePageContent.tsx` around lines 22 -
41, The two callbacks handleDirtyChange and handleCardinalSelect should be
converted from useCallback hooks to plain functions because their memoization
provides no benefit (AttendanceSessionCard and CardinalDropdown are not
memoized); replace the const handleDirtyChange = useCallback(...) and const
handleCardinalSelect = useCallback(...) with regular function declarations/const
arrow functions that call setDirtyCardIds, setPendingCardinalId,
setCardinalDialogOpen, and setSelectedCardinalId directly, and remove the
empty/dependency arrays—keep the same parameter names and behavior so closures
(isDirty, setDirtyCardIds, etc.) still work.
🤖 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/components/admin/attendance/AttendancePageContent.tsx`:
- Around line 56-90: The code uses hardcoded Tailwind utilities (pb-[64px],
h-[72px], min-w-172.5) inside AttendancePageContent JSX (affecting the Card,
Skeleton and empty-state div and the container wrapping AttendanceSessionCard),
which violates the design-token rule; replace those ad-hoc classes with the
appropriate design-token classes (e.g., spacing, height, min-width tokens) or
the component CVA token variants used elsewhere (follow patterns in Card,
Skeleton, AttendanceSessionCard props) and if a required token doesn't exist,
stop and propose adding a new token to the design system for review before
introducing it; ensure all replacements use the token names rather than
bracketed values and update the components (Skeleton, Card,
AttendanceSessionCard usage) to accept token-based classnames/props if needed.

---

Outside diff comments:
In `@src/components/admin/attendance/AttendancePageContent.tsx`:
- Around line 46-49: The condition currently prevents applying a "null"
selection because it only runs when pendingCardinalId !== null; change the guard
to allow null values (e.g., check for undefined instead) or simply always apply
the pending value: replace the if (pendingCardinalId !== null) {
setSelectedCardinalId(pendingCardinalId); setPendingCardinalId(null); } with a
check like if (pendingCardinalId !== undefined) {
setSelectedCardinalId(pendingCardinalId); setPendingCardinalId(null); }
(referencing pendingCardinalId, setSelectedCardinalId, setPendingCardinalId).
- Around line 22-41: The two callbacks handleDirtyChange and
handleCardinalSelect should be converted from useCallback hooks to plain
functions because their memoization provides no benefit (AttendanceSessionCard
and CardinalDropdown are not memoized); replace the const handleDirtyChange =
useCallback(...) and const handleCardinalSelect = useCallback(...) with regular
function declarations/const arrow functions that call setDirtyCardIds,
setPendingCardinalId, setCardinalDialogOpen, and setSelectedCardinalId directly,
and remove the empty/dependency arrays—keep the same parameter names and
behavior so closures (isDirty, setDirtyCardIds, etc.) still work.
🪄 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: a12135ad-ea8f-4829-b923-8fff3f07c319

📥 Commits

Reviewing files that changed from the base of the PR and between bf9db21 and bdc097e.

📒 Files selected for processing (3)
  • src/components/admin/attendance/AttendancePageContent.tsx
  • src/hooks/queries/admin/useAdminAttendanceQueries.ts
  • src/lib/apis/adminAttendance.ts

Comment on lines +56 to +90
<div className="flex min-w-0 flex-col gap-400 p-700">
<CardinalDropdown
cardinals={cardinals}
activeCardinal={activeCardinal}
onSelect={handleCardinalSelect}
onSelectAll={() => handleCardinalSelect(null)}
/>

{sessions.length > 0 ? (
<Card className="mt-400 gap-400 px-600 pt-600 pb-[64px]">
{sessions.map((session) => (
<AttendanceSessionCard
key={session.id}
sessionId={session.id}
date={formatKoreanDate(new Date(session.start))}
title={session.title}
isCurrentWeek={session.isCurrentWeek}
onDirtyChange={handleDirtyChange}
/>
))}
{isLoading ? (
<Card className="mt-400 gap-400 overflow-x-auto px-600 pt-600 pb-[64px]">
<div className="min-w-172.5">
{Array.from({ length: 4 }, (_, i) => (
<Skeleton key={i} className="mt-400 h-[72px] w-full first:mt-0 rounded-md" />
))}
</div>
</Card>
) : sessions.length > 0 ? (
<Card className="mt-400 gap-400 overflow-x-auto px-600 pt-600 pb-[64px]">
<div className="flex min-w-172.5 flex-col gap-400">
{sessions.map((session) => (
<AttendanceSessionCard
key={session.id}
sessionId={session.id}
date={formatKoreanDate(new Date(session.start))}
title={session.title}
isCurrentWeek={session.isCurrentWeek}
onDirtyChange={handleDirtyChange}
/>
))}
</div>
</Card>
) : (
<Card className="mt-400 flex items-center justify-center px-600 py-800">
<span className="typo-body1 text-text-alternative">
{activeCardinal ? '등록된 정기모임이 없습니다.' : '기수를 선택해 주세요.'}
</span>
<Card className="mt-400 flex items-center justify-center overflow-x-auto px-600 py-800">
<div className="min-w-172.5 text-center">
<span className="typo-body1 text-text-alternative">등록된 정기모임이 없습니다.</span>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

하드코딩된 Tailwind 값 사용(pb-[64px], h-[72px], min-w-172.5)은 토큰 규칙 위반입니다.

Line 65, Line 66, Line 68, Line 73, Line 74, Line 88, Line 89의 임의값 클래스는 디자인 토큰 우선 원칙과 충돌합니다. 토큰 클래스로 치환하고, 필요한 토큰이 없다면 먼저 토큰 추가 여부를 합의해 주세요.

As per coding guidelines Use Tailwind CSS v4 with class-variance-authority (cva) for styling and Always use design token classes first; no hardcoded values. Ask user before adding new tokens.

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

In `@src/components/admin/attendance/AttendancePageContent.tsx` around lines 56 -
90, The code uses hardcoded Tailwind utilities (pb-[64px], h-[72px],
min-w-172.5) inside AttendancePageContent JSX (affecting the Card, Skeleton and
empty-state div and the container wrapping AttendanceSessionCard), which
violates the design-token rule; replace those ad-hoc classes with the
appropriate design-token classes (e.g., spacing, height, min-width tokens) or
the component CVA token variants used elsewhere (follow patterns in Card,
Skeleton, AttendanceSessionCard props) and if a required token doesn't exist,
stop and propose adding a new token to the design system for review before
introducing it; ensure all replacements use the token names rather than
bracketed values and update the components (Skeleton, Card,
AttendanceSessionCard usage) to accept token-based classnames/props if needed.

…into WTH-358/출석-어드민-기수-조회-시-전체-기수-부터-표시되게-수정
@github-actions
Copy link
Copy Markdown

🤖 Claude 테스트 제안

모델: claude-sonnet-4-6 | 토큰: 0 입력 / 0 출력

변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.

src/components/admin/attendance/AttendancePageContent.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/hooks/queries/admin/useAdminAttendanceQueries.ts

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/lib/apis/adminAttendance.ts

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


이 코멘트는 Claude API를 통해 자동 생성되었습니다. 반드시 검토 후 사용하세요.

@github-actions
Copy link
Copy Markdown

PR 테스트 결과

Jest: 통과

🎉 모든 테스트를 통과했습니다!

@github-actions
Copy link
Copy Markdown

PR 검증 결과

TypeScript: 통과
ESLint: 통과
Prettier: 통과
Build: 통과

🎉 모든 검증을 통과했습니다!

@github-actions
Copy link
Copy Markdown

구현한 기능 Preview: https://weeth-cqaa86t5r-weethsite-4975s-projects.vercel.app

@github-actions
Copy link
Copy Markdown

🤖 Claude 테스트 제안

모델: claude-sonnet-4-6 | 토큰: 0 입력 / 0 출력

변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.

src/components/admin/attendance/AttendanceCard.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/admin/attendance/AttendancePageContent.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/components/admin/attendance/AttendanceSessionCard.tsx

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/hooks/queries/admin/useAdminAttendanceQueries.ts

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


src/lib/apis/adminAttendance.ts

오류: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.


이 코멘트는 Claude API를 통해 자동 생성되었습니다. 반드시 검토 후 사용하세요.

@github-actions
Copy link
Copy Markdown

PR 테스트 결과

Jest: 통과

🎉 모든 테스트를 통과했습니다!

@github-actions
Copy link
Copy Markdown

PR 검증 결과

TypeScript: 통과
ESLint: 통과
Prettier: 통과
Build: 통과

🎉 모든 검증을 통과했습니다!

@github-actions
Copy link
Copy Markdown

구현한 기능 Preview: https://weeth-m91p18cjg-weethsite-4975s-projects.vercel.app

@nabbang6 nabbang6 merged commit 5eda075 into develop Apr 29, 2026
5 checks passed
@nabbang6 nabbang6 deleted the WTH-358/출석-어드민-기수-조회-시-전체-기수-부터-표시되게-수정 branch May 3, 2026 08:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 Refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants