Skip to content

20260403 fe add adminpage absent list#351

Merged
discipline24 merged 9 commits into
mainfrom
20260403-FE-ADD-ADMINPAGE-ABSENT-LIST
Apr 3, 2026
Merged

20260403 fe add adminpage absent list#351
discipline24 merged 9 commits into
mainfrom
20260403-FE-ADD-ADMINPAGE-ABSENT-LIST

Conversation

@yyunee
Copy link
Copy Markdown
Contributor

@yyunee yyunee commented Apr 3, 2026

  1. 결석 및 지각 집계 모달 (AbsenceSummaryModal) 추가
    특정 세션 내 모든 유저의 결석(ABSENT) 및 지각(LATE) 횟수를 한눈에 파악할 수 있는 요약 모달을 구현했습니다.

주요 로직: 결석 또는 지각 기록이 최소 1회 이상 있는 유저만 필터링하여 표시합니다.
결석 횟수 내림차순, 지각 횟수 내림차순으로 자동 정렬하여 효율적인 관리가 가능합니다.

AttendanceManagementCard 헤더에 '결석 인원 모아보기' 버튼을 통해 접근할 수 있습니다.

  1. 출석부 자동 정렬 기능 개선
    관리자가 주목해야 할 인원을 상단에 배치하도록 AttendanceManagementCard 내 userRows 정렬 로직을 강화했습니다.

정렬 우선순위: 출석 상태: 오늘(또는 마지막) 회차의 상태가 결석 > 지각 > 기타 순으로 상단에 노출됩니다.
역할(Role): 동일 상태 내에서는 소유자 > 관리자 > 팀원 순으로 정렬됩니다.
이름: 모든 조건이 같을 경우 가나다순으로 정렬됩니다.

image

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 결석 및 지각 집계를 한눈에 보는 요약 모달 추가
  • 개선사항

    • 로그인/회원가입 흐름이 이전 페이지로 복귀하는 returnUrl을 보존하도록 개선
    • 출석 목록 정렬 로직 개선(결석/지각 우선 정렬 포함)
    • 피드백 모달에 “피드백은 익명으로 저장됩니다.” 설명 추가
    • 다양한 화면에서 더 정확한 뷰포트 높이 처리를 위한 CSS 개선
  • 버그 수정

    • 모바일 뷰포트 높이 관련 표시 안정성 개선

@yyunee yyunee requested a review from discipline24 as a code owner April 3, 2026 06:46
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 3, 2026

Walkthrough

뷰포트 높이 조정용 --vh 변수 추가, 인증 실패 시 원래 경로를 returnUrl로 보존해 로그인 리다이렉트 처리, 결석 집계 모달(AbsenceSummaryModal) 신규 추가, 피드백 모달 문구 수정이 적용되었습니다.

Changes

Cohort / File(s) Summary
앱 루트 뷰포트 변수
frontend/src/App.jsx, frontend/src/index.css, frontend/src/components/Layout.jsx
window.innerHeight로 --vh 계산/설정(useEffect) 및 min-height/height에 calc(var(--vh, 1vh) * 100) 추가
전역/페이지 CSS 뷰포트 보정
frontend/src/pages/.../Home.module.css, frontend/src/pages/.../LoginAndSignUp.module.css, frontend/src/pages/.../AdminHome.module.css, frontend/src/pages/.../AdminDashboard.module.css, frontend/src/pages/.../Board.module.css, frontend/src/pages/external/External.module.css, frontend/src/components/Sidebar.module.css
여러 CSS 파일의 100vh/min-height/heightcalc(var(--vh, 1vh) * 100) 형태로 변경
인증/리다이렉트(returnUrl) 변경
frontend/src/components/AdminRoute.jsx, frontend/src/components/protectedRoute.jsx, frontend/src/hooks/useAuthGuard.js, frontend/src/components/login/LoginForm.jsx, frontend/src/components/signup/SignUpForm.jsx
useLocation 사용으로 pathname+search를 인코딩한 returnUrl/login에 포함해 리다이렉트; 401 검사에 error.response.status 추가
출석 관리 — 결석 집계 기능 추가
frontend/src/components/attendancemanage/AbsenceSummaryModal.jsx, frontend/src/components/attendancemanage/AbsenceSummaryModal.module.css, frontend/src/components/attendancemanage/AttendanceManagementCard.jsx, frontend/src/components/attendancemanage/AttendanceManagementCard.module.css
새 AbsenceSummaryModal 컴포넌트 및 스타일 추가, AttendanceManagementCard에 모달 통합 버튼 추가 및 정렬 로직(현재 라운드 기반) 변경, 신규 버튼 스타일 추가
피드백 문구 변경
frontend/src/components/Sidebar.jsx
피드백 모달 설명에 “피드백은 익명으로 저장됩니다.” 문구 추가

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

FE

Suggested reviewers

  • discipline24
  • DongEun02
  • gxuoo

Poem

🐰 화면 높이를 재고, 길을 잃지 않게,
로그인에 길을 남기고, 돌아올 수 있게,
결석을 모아 보여주니 한눈에 쏙,
피드백은 익명으로, 마음 편히 남기고,
토끼가 깡총, 코드도 깡총 — 완성! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 '20260403 fe add adminpage absent list'로, 변경 사항의 핵심인 AbsenceSummaryModal 추가와 자동 정렬 개선을 명확하게 반영하고 있으나, 날짜 형식(20260403)과 브랜치명 형식이 포함되어 있어 약간 부정확합니다.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 20260403-FE-ADD-ADMINPAGE-ABSENT-LIST
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch 20260403-FE-ADD-ADMINPAGE-ABSENT-LIST

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

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

🧹 Nitpick comments (2)
frontend/src/components/attendancemanage/AbsenceSummaryModal.module.css (2)

6-6: vh 대신 --vh fallback 패턴으로 맞추는 것을 권장합니다.

이 PR에서 다른 레이아웃들이 calc(var(--vh, 1vh) * 100)으로 통일되고 있어, 여기만 100vh/85vh를 유지하면 모바일(특히 주소창 확장/축소)에서 높이 계산이 어긋날 수 있습니다.

🔧 제안 수정안
 .modalOverlay {
@@
-  height: 100vh;
+  height: calc(var(--vh, 1vh) * 100);
@@
 .modalContent {
@@
-  max-height: 85vh;
+  max-height: calc(var(--vh, 1vh) * 85);

Also applies to: 20-20

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

In `@frontend/src/components/attendancemanage/AbsenceSummaryModal.module.css` at
line 6, Replace the literal viewport height usage in
AbsenceSummaryModal.module.css (the rule that currently has "height: 100vh;")
with the --vh fallback pattern used elsewhere; e.g. set height to calc(var(--vh,
1vh) * 100) (or calc(var(--vh, 1vh) * 85) if the intended height was 85vh) so
the component follows the same mobile address-bar-safe sizing convention.

24-24: 코드베이스의 keyframe 명명 규칙을 일관되게 적용해주세요.

현재 파일의 modalAppear는 camelCase를 사용하고 있으며, 코드베이스의 다른 파일들(fadeIn, slideIn 등)도 동일한 패턴을 따르고 있습니다. Stylelint 기본 설정은 kebab-case(modal-appear)를 권장하므로, 일관된 명명 규칙을 적용하거나 Stylelint 설정을 명시적으로 조정하는 것이 좋습니다.

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

In `@frontend/src/components/attendancemanage/AbsenceSummaryModal.module.css` at
line 24, Rename the keyframe name from modalAppear to kebab-case modal-appear
and update all references accordingly: change any animation: modalAppear to
animation: modal-appear and rename the corresponding `@keyframes` modalAppear {
... } block to `@keyframes` modal-appear { ... }; ensure any other usages (e.g.,
animation-name, shorthand declarations) in the project that reference
modalAppear are updated to modal-appear to keep naming consistent with stylelint
conventions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/components/attendancemanage/AbsenceSummaryModal.jsx`:
- Around line 22-27: The modal markup in AbsenceSummaryModal.jsx lacks semantic
accessibility attributes and the close button is missing an explicit type;
update the modal container div (e.g., the element currently rendered as <div
className={styles.modalContent}>) to include role="dialog", aria-modal="true",
and aria-labelledby pointing to the heading by giving the <h2> an id (e.g.,
id="absence-summary-title"), and ensure the overlay and content keep
e.stopPropagation() behavior; also change the close button element (the one with
className={styles.closeButton}) to include type="button" to prevent accidental
form submits and add an accessible label (aria-label="Close" or use the heading
id) as needed.

In `@frontend/src/components/attendancemanage/AttendanceManagementCard.jsx`:
- Around line 172-175: The current selection uses UTC-based todayStr and an
unsorted array slice, causing off-by-one picks; instead compute the local date
string using the same locale format used to store roundDate (e.g., new
Date().toLocaleDateString('sv-SE')) and use that as todayStr when matching; also
ensure attendanceData.rounds is deterministically ordered before picking
fallback by sorting attendanceData.rounds by their roundDate (lexicographic sort
is fine for 'YYYY-MM-DD' strings) and then select targetRound by finding a round
with roundDate === todayStr or falling back to the last element of the sorted
array; update the code around todayStr, targetRound and any direct
attendanceData.rounds indexing accordingly.

In
`@frontend/src/components/attendancemanage/AttendanceManagementCard.module.css`:
- Around line 628-648: Add visible keyboard focus styles for the
.absenceSummaryButton so keyboard users can see focus: implement :focus and
preferably :focus-visible rules that mirror hover/active states while adding a
high-contrast outline or subtle box-shadow (e.g., 2px solid or 3px ring) and
ensure focus styles respect existing border-radius and color contrast; update
the CSS selectors .absenceSummaryButton:focus and
.absenceSummaryButton:focus-visible and ensure the focus state does not rely
solely on :hover or :active.

In `@frontend/src/hooks/useAuthGuard.js`:
- Around line 18-24: The 401 check in the useAuthGuard hook is brittle because
it inspects error.status directly; update the conditional to check
error.response?.status (using optional chaining) so token-refresh axios errors
are detected consistently (match AdminRoute pattern). Locate the block that does
the 401 handling inside useAuthGuard (the branch that calls toast.error,
computes returnUrl and calls nav(`/login?returnUrl=${returnUrl}`)) and replace
the error.status check with error.response?.status (or a combined check if
needed) to ensure reliable detection of HTTP 401 responses from axios errors.

---

Nitpick comments:
In `@frontend/src/components/attendancemanage/AbsenceSummaryModal.module.css`:
- Line 6: Replace the literal viewport height usage in
AbsenceSummaryModal.module.css (the rule that currently has "height: 100vh;")
with the --vh fallback pattern used elsewhere; e.g. set height to calc(var(--vh,
1vh) * 100) (or calc(var(--vh, 1vh) * 85) if the intended height was 85vh) so
the component follows the same mobile address-bar-safe sizing convention.
- Line 24: Rename the keyframe name from modalAppear to kebab-case modal-appear
and update all references accordingly: change any animation: modalAppear to
animation: modal-appear and rename the corresponding `@keyframes` modalAppear {
... } block to `@keyframes` modal-appear { ... }; ensure any other usages (e.g.,
animation-name, shorthand declarations) in the project that reference
modalAppear are updated to modal-appear to keep naming consistent with stylelint
conventions.
🪄 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: e226f687-2ba1-4434-a537-da1afbe746b4

📥 Commits

Reviewing files that changed from the base of the PR and between ebb967b and 18c0b60.

📒 Files selected for processing (20)
  • frontend/src/App.jsx
  • frontend/src/components/AdminRoute.jsx
  • frontend/src/components/Layout.jsx
  • frontend/src/components/Sidebar.jsx
  • frontend/src/components/Sidebar.module.css
  • frontend/src/components/attendancemanage/AbsenceSummaryModal.jsx
  • frontend/src/components/attendancemanage/AbsenceSummaryModal.module.css
  • frontend/src/components/attendancemanage/AttendanceManagementCard.jsx
  • frontend/src/components/attendancemanage/AttendanceManagementCard.module.css
  • frontend/src/components/login/LoginForm.jsx
  • frontend/src/components/protectedRoute.jsx
  • frontend/src/components/signup/SignUpForm.jsx
  • frontend/src/hooks/useAuthGuard.js
  • frontend/src/index.css
  • frontend/src/pages/AdminDashboard.module.css
  • frontend/src/pages/AdminHome.module.css
  • frontend/src/pages/Board.module.css
  • frontend/src/pages/Home.module.css
  • frontend/src/pages/LoginAndSignUp.module.css
  • frontend/src/pages/external/External.module.css

Comment thread frontend/src/components/attendancemanage/AbsenceSummaryModal.jsx
Comment thread frontend/src/components/attendancemanage/AttendanceManagementCard.jsx Outdated
Comment thread frontend/src/hooks/useAuthGuard.js Outdated
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.

🧹 Nitpick comments (1)
frontend/src/components/attendancemanage/AttendanceManagementCard.jsx (1)

618-624: 조건부 렌더링과 isOpen prop이 중복됩니다.

isAbsenceModalOpen &&로 조건부 렌더링하면서 동시에 isOpen={isAbsenceModalOpen} prop을 전달하고 있습니다. 현재 패턴에서는 모달이 렌더링될 때 isOpen이 항상 true입니다.

모달 컴포넌트가 닫힘 애니메이션을 사용한다면, 조건부 렌더링 대신 항상 렌더링하고 isOpen으로 visibility를 제어하는 것이 좋습니다. 그렇지 않다면 isOpen prop을 제거하고 조건부 렌더링만 사용하여 단순화할 수 있습니다.

♻️ 옵션 1: 조건부 렌더링 제거 (애니메이션 필요 시)
-      {isAbsenceModalOpen && (
-        <AbsenceSummaryModal
-          isOpen={isAbsenceModalOpen}
-          onClose={() => setIsAbsenceModalOpen(false)}
-          userRows={attendanceData.userRows}
-        />
-      )}
+      <AbsenceSummaryModal
+        isOpen={isAbsenceModalOpen}
+        onClose={() => setIsAbsenceModalOpen(false)}
+        userRows={attendanceData.userRows}
+      />
♻️ 옵션 2: isOpen prop 제거 (애니메이션 불필요 시)
       {isAbsenceModalOpen && (
         <AbsenceSummaryModal
-          isOpen={isAbsenceModalOpen}
           onClose={() => setIsAbsenceModalOpen(false)}
           userRows={attendanceData.userRows}
         />
       )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/attendancemanage/AttendanceManagementCard.jsx` around
lines 618 - 624, The code redundantly both conditionally renders
AbsenceSummaryModal with "isAbsenceModalOpen &&" and also passes
isOpen={isAbsenceModalOpen}; choose one approach: either always render
<AbsenceSummaryModal ... userRows={attendanceData.userRows}
isOpen={isAbsenceModalOpen} onClose={() => setIsAbsenceModalOpen(false)} />
(remove the leading "isAbsenceModalOpen &&" so the modal can run close
animations) or remove the isOpen prop and keep conditional rendering (keep
"isAbsenceModalOpen && <AbsenceSummaryModal userRows={attendanceData.userRows}
onClose={() => setIsAbsenceModalOpen(false)} />") and update the component
accordingly; make the change around the AbsenceSummaryModal usage and ensure
setIsAbsenceModalOpen and isAbsenceModalOpen remain the single source of truth
for visibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/src/components/attendancemanage/AttendanceManagementCard.jsx`:
- Around line 618-624: The code redundantly both conditionally renders
AbsenceSummaryModal with "isAbsenceModalOpen &&" and also passes
isOpen={isAbsenceModalOpen}; choose one approach: either always render
<AbsenceSummaryModal ... userRows={attendanceData.userRows}
isOpen={isAbsenceModalOpen} onClose={() => setIsAbsenceModalOpen(false)} />
(remove the leading "isAbsenceModalOpen &&" so the modal can run close
animations) or remove the isOpen prop and keep conditional rendering (keep
"isAbsenceModalOpen && <AbsenceSummaryModal userRows={attendanceData.userRows}
onClose={() => setIsAbsenceModalOpen(false)} />") and update the component
accordingly; make the change around the AbsenceSummaryModal usage and ensure
setIsAbsenceModalOpen and isAbsenceModalOpen remain the single source of truth
for visibility.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5e01f4d7-03f2-4495-86c0-6f09cf40339f

📥 Commits

Reviewing files that changed from the base of the PR and between 18c0b60 and 9d14905.

📒 Files selected for processing (4)
  • frontend/src/components/AdminRoute.jsx
  • frontend/src/components/attendancemanage/AbsenceSummaryModal.jsx
  • frontend/src/components/attendancemanage/AttendanceManagementCard.jsx
  • frontend/src/hooks/useAuthGuard.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/src/hooks/useAuthGuard.js
  • frontend/src/components/AdminRoute.jsx
  • frontend/src/components/attendancemanage/AbsenceSummaryModal.jsx

Copy link
Copy Markdown
Contributor

@discipline24 discipline24 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다~

@discipline24 discipline24 merged commit 2bbca4c into main Apr 3, 2026
1 check passed
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.

3 participants