[FE] 314 기능개선전체 전반적 fe uiux 개선#315
Hidden character warning
Conversation
Walkthrough여러 UI/스타일과 접근 제어를 변경합니다: 다수 모달의 z-index 통일(3000), 로그인/회원가입 비밀번호 가시성 토글 추가, 출석관리 역할 기반 메뉴 표시 및 여러 출석관리 컴포넌트·테이블의 레이아웃·페이징·정렬 로직 개선, 게시판 관련 외부 클릭 감지 및 댓글 메뉴 토글 개선. Changes
Sequence Diagram(s)(생성 조건 미충족 — 생략) Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Possibly related PRs
Suggested labels
Suggested reviewers
시
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 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 Tip You can get early access to new features in CodeRabbit.Enable the |
There was a problem hiding this comment.
Pull request overview
모바일(핸드폰) 기준으로 출석/게시판/모달/로그인·회원가입 등 주요 화면의 UI·UX를 개선하고, 비밀번호 표시 토글 및 권한별 사이드바 노출 제한을 반영하는 프론트엔드 변경입니다.
Changes:
- 출석 관리/조회 화면의 모바일 레이아웃 및 테이블 스크롤/고정 헤더 등 반응형 UI 개선
- 로그인/회원가입 폼에 비밀번호 보기/숨기기 토글 및 비밀번호 확인 불일치 안내 추가
- 모달/오버레이 z-index 상향 및 사이드바 메뉴를 역할 기반으로 제한
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/pages/PostDetail.module.css | PostDetail 모바일 패딩/콘텐츠 폭 변수 조정 |
| frontend/src/pages/PostDetail.jsx | 게시글/댓글 메뉴 외부 클릭 시 닫기 처리 추가 |
| frontend/src/pages/Board.jsx | 게시판 페이지네이션 페이지당 아이템 수 변경(4→10) |
| frontend/src/pages/AttendanceManage.module.css | 출석관리 페이지 레이아웃(플렉스/그리드) 및 오버플로우 개선 |
| frontend/src/components/signup/SignUpForm.jsx | 비밀번호 토글, 비밀번호 확인 일치/불일치 메시지 추가 |
| frontend/src/components/quantbot/ReportModal.css | 모달 overlay z-index 상향 |
| frontend/src/components/mypage/EditProfileModal.module.css | 프로필 수정 모달 z-index 상향 |
| frontend/src/components/mypage/ActivityModal.module.css | 활동 모달 z-index 상향 |
| frontend/src/components/login/LoginForm.jsx | 로그인 비밀번호 토글 추가 |
| frontend/src/components/backtest/BacktestTemplateSaveModal.module.css | 저장 모달 z-index 상향 |
| frontend/src/components/attendancemanage/SessionSettingCard.module.css | 세션 설정 카드 입력 폭/반응형 정리 및 오버플로우 개선 |
| frontend/src/components/attendancemanage/SessionSettingCard.jsx | 세션 설정 입력에 compact 스타일 클래스 적용 |
| frontend/src/components/attendancemanage/SessionManagementCard.module.css | 세션 관리 카드 헤더/테이블 스크롤 및 반응형 정리 |
| frontend/src/components/attendancemanage/SessionManagementCard.jsx | 공통 헤더에 반응형 헤더 스타일 결합 |
| frontend/src/components/attendancemanage/RoundDayPicker.jsx | 회차 추가 모달의 종료시간 기본 계산 로직 변경 |
| frontend/src/components/attendancemanage/AttendanceManagementCard.module.css | 출석부 테이블 고정 헤더/컬럼 폭 및 스크롤 UX 개선 |
| frontend/src/components/attendancemanage/AttendanceManagementCard.jsx | 테이블 헤더 스타일 클래스화 및 역할 표시 라벨링 추가 |
| frontend/src/components/attendance/SessionManage.module.css | 출석 조회 테이블 래퍼 추가로 가로 스크롤 UX 개선 |
| frontend/src/components/attendance/SessionManage.jsx | 테이블을 스크롤 래퍼로 감싸 모바일 대응 |
| frontend/src/components/VerificationModal.module.css | 오버레이/모달 최대높이 및 모바일 safe-area 대응, z-index 상향 |
| frontend/src/components/Sidebar.jsx | 출석관리 메뉴를 역할 기반으로 조건부 노출 |
| frontend/src/components/LoginAndSignUpForm.module.css | 비밀번호 토글 UI 및 비밀번호 일치 메시지 스타일 추가 |
| frontend/src/components/Board/PostDetail/CommentSection.jsx | 댓글 메뉴 버튼 토글 동작(열기/닫기) 개선 |
| frontend/src/components/Board/Modal.module.css | 게시판 모달 overlay z-index 상향 |
| frontend/src/components/Board/CreateSubBoardModal.module.css | 서브보드 생성 모달 z-index 상향 |
| frontend/src/components/AdminMemberManage/AdminMemberManage.module.css | 관리자 회원관리 모달 z-index 상향 |
| frontend/src/components/AdminMemberApproval/AdminMemberApproval.module.css | 관리자 가입승인 모달 z-index 상향 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
frontend/src/components/attendancemanage/SessionSettingCard.jsx (1)
94-102:⚠️ Potential issue | 🟡 Minor
maxLength속성이type="number"입력에서는 동작하지 않습니다.Line 99의
maxLength="3"은type="number"입력 필드에서 무시됩니다. 3자리 제한이 필요하다면max속성이나onChange핸들러에서 유효성 검사를 추가해야 합니다.🔧 max 속성을 사용한 수정 제안
<input type="number" id="sessionAvailableTime" className={styles.compactMinuteInput} value={allowedMinutes} - maxLength="3" + min="1" + max="999" onChange={(e) => setAllowedMinutes(e.target.value)} placeholder="분(MM)" />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/SessionSettingCard.jsx` around lines 94 - 102, The number input with id "sessionAvailableTime" in SessionSettingCard.jsx uses maxLength="3" which is ignored for type="number"; change to a proper numeric limit by adding a max="999" attribute and enforce validation in the onChange handler: when handling e.target.value in the setAllowedMinutes call, coerce/validate the value (e.g., strip non-digits, limit length to 3 or clamp to 0–999) before calling setAllowedMinutes so the stored state respects the 3-digit constraint. Ensure you update the input attributes and the onChange logic that references allowedMinutes and setAllowedMinutes.frontend/src/pages/AttendanceManage.module.css (1)
34-38:⚠️ Potential issue | 🟠 MajorCSS 그리드 영역이 JSX 구조와 맞지 않습니다.
.cardLayout은 3개의 그리드 영역(settings,session,roster)을 정의하지만 실제로는 2개의 직접 자식 요소(.leftColumn과AttendanceManagementCard)만 존재합니다. 또한SessionSettingCard,SessionManagementCard,AttendanceManagementCard가.settings,.session,.roster클래스를 적용하지 않아 그리드 레이아웃이 의도대로 작동하지 않을 수 있습니다.이를 해결하려면 다음 중 하나를 수행해야 합니다:
- 컴포넌트에 해당하는 그리드 영역 클래스를 적용하거나
- CSS 그리드 정의를 JSX 구조에 맞게 조정하기
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/pages/AttendanceManage.module.css` around lines 34 - 38, .cardLayout defines three grid areas ('settings','session','roster') but JSX only renders two direct children (.leftColumn and AttendanceManagementCard) and the child components (SessionSettingCard, SessionManagementCard, AttendanceManagementCard) do not have the corresponding area classes, so the grid won't lay out as intended; fix by either adding the grid-area classes to the rendered elements (apply className="settings" to the container wrapping SessionSettingCard/SessionManagementCard and className="session"/"roster" where appropriate, or add className="settings"/"session"/"roster" to those component root elements) or simplify .cardLayout to match the actual JSX structure (remove unused grid-template-areas or combine them), targeting the .cardLayout, .leftColumn, SessionSettingCard, SessionManagementCard, and AttendanceManagementCard symbols to implement the change.
🧹 Nitpick comments (18)
frontend/src/pages/PostDetail.module.css (1)
860-869: 모바일 반응형 스타일이 적절하게 추가되었습니다.브레이크포인트
767px이 기존 태블릿 쿼리min-width: 768px과 잘 맞물리며, 모바일에서 콘텐츠 너비를 100%로 확장하는 것은 좋은 UX 개선입니다.한 가지 참고사항: CSS Modules에서
:root는 스코핑되지 않고 전역으로 적용됩니다. 현재는--width-content가 이 파일에서만 정의되어 문제가 없지만, 향후 다른 CSS 모듈에서 동일한 변수를 정의하면 충돌이 발생할 수 있습니다. 필요시.postDetail내에서 직접 값을 사용하거나 더 구체적인 변수명을 고려해 볼 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/pages/PostDetail.module.css` around lines 860 - 869, The CSS uses a global :root custom property (--width-content) inside the mobile media query which can conflict with other CSS Modules later; change the rule so the variable is scoped or inlined—either move the value into .postDetail (e.g., set .postDetail { --postDetail-width-content: 100%; } and use that locally) or rename the variable to a more specific name (e.g., --postDetail-width-content) and update all references, and ensure the media query remains `@media` (max-width: 767px) for .postDetail.frontend/src/components/Board/Modal.module.css (1)
11-11:z-index매직넘버는 공용 토큰으로 통합하는 걸 권장합니다.Line 11처럼
3000이 여러 파일에 반복되어 있어, 다음 레이어 충돌 시 수정 범위가 커질 수 있습니다. 공용 CSS 변수로 통일하면 유지보수가 쉬워집니다.♻️ 제안 수정안
.overlay { position: fixed; @@ - z-index: 3000; + z-index: var(--z-modal-overlay); }/* 공통 루트 스타일(예: 전역 stylesheet)에 1회 정의 */ :root { --z-modal-overlay: 3000; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/Board/Modal.module.css` at line 11, Replace the hardcoded z-index value in Modal.module.css (the CSS rule containing "z-index: 3000;") with a shared CSS custom property to avoid magic numbers; add a global variable (e.g. --z-modal-overlay) in your root/global stylesheet and update the Modal.module.css rule to use that variable instead of 3000 so all components reference the same token.frontend/src/components/login/LoginForm.jsx (1)
102-109: 토글 버튼에 상태(aria-pressed)를 함께 노출해 주세요.라벨 변경만으로도 동작은 전달되지만, 토글 버튼 패턴에서는 pressed 상태를 같이 주는 편이 더 명확합니다.
접근성 속성 보강 예시
<button type="button" className={styles.passwordToggleButton} onClick={() => setShowPassword((prev) => !prev)} aria-label={showPassword ? '비밀번호 숨기기' : '비밀번호 보기'} + aria-pressed={showPassword} >🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/login/LoginForm.jsx` around lines 102 - 109, The password toggle button in LoginForm.jsx should expose its pressed state via aria-pressed; update the button that uses setShowPassword and showPassword (className styles.passwordToggleButton) to include aria-pressed={showPassword} so the attribute reflects the boolean state, ensuring it stays a proper toggle button for assistive tech.frontend/src/components/signup/SignUpForm.jsx (2)
296-308: 일치/불일치 안내 문구에aria-live를 추가해 주세요.문구가 동적으로 바뀌는 영역이라 스크린리더가 변경을 읽어줄 수 있도록 live region 지정이 있으면 좋습니다.
접근성 보강 예시
{hasConfirmPasswordInput && ( <p className={`${styles.passwordMatchMessage} ${ isPasswordMatch ? styles.passwordMatchMessageSuccess : styles.passwordMatchMessageError }`} + role="status" + aria-live="polite" >🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/signup/SignUpForm.jsx` around lines 296 - 308, The password match message block (controlled by hasConfirmPasswordInput and isPasswordMatch) is a dynamic live region for screen readers; add an aria-live attribute (e.g., aria-live="polite") to the outer <p> and consider aria-atomic="true" so updates are fully announced, keeping the existing classNames (styles.passwordMatchMessage, styles.passwordMatchMessageSuccess, styles.passwordMatchMessageError) and message logic intact; ensure you update the JSX for the <p> rendered by the conditional that references hasConfirmPasswordInput and isPasswordMatch.
248-265: 토글 입력 UI 중복은 공통 컴포넌트로 추출을 고려해도 좋겠습니다.동일 패턴이 반복되어 있어
PasswordFieldWithToggle형태로 분리하면 유지보수가 쉬워집니다.Also applies to: 279-295
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/signup/SignUpForm.jsx` around lines 248 - 265, Extract the repeated password input + toggle block into a reusable component (e.g., PasswordFieldWithToggle) and replace both occurrences in SignUpForm.jsx with that component; the new component should accept props for value, onChange (use handlePasswordChange), id, placeholder, autoComplete and any className (use styles.inputWithToggle and styles.passwordToggleButton) and internally manage its own showPassword state and render Eye / EyeOff icons accordingly, preserving aria-label behavior and button type="button".frontend/src/components/LoginAndSignUpForm.module.css (1)
87-106: 키보드 사용자용 포커스 스타일을 명시해 주세요.현재 hover 상태만 정의되어 있어, 버튼 포커스 표시를 명시하면 접근성이 더 안정적입니다.
접근성 보강 예시
.passwordToggleButton:hover { color: `#111827`; } +.passwordToggleButton:focus-visible { + outline: 2px solid `#1d80f4`; + outline-offset: 2px; + border-radius: 6px; +} + .passwordToggleButton svg { pointer-events: none; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/LoginAndSignUpForm.module.css` around lines 87 - 106, The .passwordToggleButton styles only define hover state; add explicit keyboard focus styles so keyboard users can see focus—implement .passwordToggleButton:focus and/or .passwordToggleButton:focus-visible rules (matching or complementing the hover color change) that provide a clear, high-contrast visible indicator (e.g., outline or box-shadow) while preserving the existing layout and sizing for the passwordToggleButton element.frontend/src/components/attendancemanage/SessionSettingCard.module.css (1)
97-107: 반응형 입력 필드 너비 제어 클래스가 추가되었습니다.
clamp()함수를 사용한 유연한 너비 조절이 좋습니다. 다만!important사용이 많아 향후 스타일 오버라이드 시 유지보수가 어려울 수 있습니다. 가능하다면 CSS 특이성(specificity)을 활용한 방식을 고려해보세요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/SessionSettingCard.module.css` around lines 97 - 107, The current .compactTextInput and .compactMinuteInput rules rely on multiple !important flags which make future overrides fragile; remove the !important declarations and instead increase selector specificity (for example by scoping under the parent component class or combining selectors like .sessionSettingCard .compactTextInput / .sessionSettingCard .compactMinuteInput) or adjust the CSS module export so the styles win without !important, keeping the clamp(...) values intact and preserving width/min-width/max-width behavior.frontend/src/components/attendancemanage/AttendanceManagementCard.jsx (1)
45-64: 역할 표시 라벨 헬퍼 함수가 잘 구현되었습니다.백엔드
SessionRoleenum(OWNER,MANAGER,PARTICIPANT)과 매핑되어 한글 라벨을 반환합니다. 다만,includes('MANAGE')방식의 부분 문자열 매칭은 의도치 않은 매칭을 유발할 수 있습니다.♻️ 정확한 매칭을 위한 개선 제안
const getRoleDisplayLabel = (role) => { const roleText = String(role || '').trim(); const normalized = roleText.toUpperCase(); if (normalized.includes('OWNER')) { return '소유자'; } - if (normalized.includes('MANAGE')) { + if (normalized.includes('MANAGER') || normalized === 'MANAGE') { return '관리자'; } if ( normalized.includes('PARTICIPANT') ) { return '팀원'; } return roleText || '팀원'; };🤖 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 45 - 64, getRoleDisplayLabel currently uses substring checks (e.g., normalized.includes('MANAGE')) which can produce false positives; change the matching to exact enum comparisons on the normalized role (e.g., compare normalized === 'OWNER' / 'MANAGER' / 'PARTICIPANT' or use a strict set lookup) so the function maps only the intended backend SessionRole values to Korean labels; update getRoleDisplayLabel to normalize role and then do exact matches (or a lookup map) and keep the fallback to roleText || '팀원'.frontend/src/pages/AttendanceManage.module.css (1)
52-61:.roster > *선택자 범위 확인이 필요합니다.
.roster클래스가 실제로 사용되지 않는다면 이 규칙은 적용되지 않습니다. 현재 JSX 구조에서AttendanceManagementCard가.roster클래스 없이 직접 렌더링되고 있어,width: 100%규칙이 의도한 대로 적용되지 않을 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/pages/AttendanceManage.module.css` around lines 52 - 61, The `.roster > *` CSS rule is not applying because the rendered JSX doesn’t use the `.roster` class; check where AttendanceManagementCard is rendered and either (a) add the roster module class to the container element that wraps AttendanceManagementCard (so `.roster > * { width:100% }` applies), or (b) change the selector in AttendanceManage.module.css to target the actual class name used in the JSX (the wrapper/component class around AttendanceManagementCard) so child elements get width:100%; update the JSX/class names accordingly and verify the layout.frontend/src/components/attendancemanage/AttendanceManagementCard.module.css (4)
1-13: 중복된.attendanceManagementCardContainer선택자가 존재합니다.Lines 1-13과 Lines 534-547에서 동일한 선택자가 두 번 정의되어 있습니다. 두 정의를 하나로 병합하여 유지보수성을 개선하세요. 현재 구조에서는 나중 정의가 이전 속성을 덮어쓰기 때문에 의도치 않은 스타일 손실이 발생할 수 있습니다.
Also applies to: 534-547
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/AttendanceManagementCard.module.css` around lines 1 - 13, Duplicate .attendanceManagementCardContainer rules exist; merge them into one definition by consolidating all properties from both occurrences (lines showing .attendanceManagementCardContainer) into a single block, remove the later duplicate, and ensure any conflicting properties are resolved by choosing the intended value (prefer the later value if that was intentional). Update any comments and run a quick UI check to confirm box-shadow, border, padding, background, transition, overflow, and sizing behave as expected.
381-406: 테이블 컬럼 너비가 중복 정의되어 있습니다.Lines 381-406에서 정의한 너비 규칙이 Lines 642-658에서 다른 값으로 재정의됩니다. 예: 2번째 컬럼이
120px에서76px로 변경. 의도적인 변경이라면 이전 정의를 정리하세요.Also applies to: 642-658
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/AttendanceManagementCard.module.css` around lines 381 - 406, There are duplicate column-width rules for the table (selectors like .table thead th:nth-child(1) / tbody td:nth-child(1) through .table thead th:nth-child(n + 5) / tbody td:nth-child(n + 5)) that conflict with another block (e.g., the 2nd column defined as 120px here but redefined as 76px later); pick the intended widths and remove or consolidate the redundant CSS block so only one authoritative set of widths remains (either keep the 381–406 definitions and delete the later overrides, or merge the final values into this set), ensuring selectors (.table thead th:nth-child(n) and .table tbody td:nth-child(n)) match exactly and preserve min-width where needed.
136-139: 여러!important선언을 제거하세요.
text-align: center !important(Lines 138, 268, 278)이 여러 곳에서 사용됩니다. 이는 specificity 문제를 우회하는 안티패턴입니다. CSS 선택자 구조를 개선하거나 클래스 조합을 통해 specificity를 자연스럽게 높이세요.Also applies to: 268-275, 277-279
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/AttendanceManagementCard.module.css` around lines 136 - 139, Remove the !important usages on .checkboxHeader and .checkboxCell by increasing selector specificity or adding a dedicated utility class; for example, replace the rules using ".checkboxHeader, .checkboxCell { text-align: center !important; }" with a more specific selector such as ".attendanceCard .checkboxHeader, .attendanceCard .checkboxCell { text-align: center; }" or add a new ".centerText" class with "text-align: center;" and apply it in the component JSX where CheckboxHeader/CheckboxCell are rendered; ensure any conflicting rules (other selectors targeting these elements) are adjusted or removed so the new non-!important rules take effect.
200-206: z-index 값을 체계적으로 관리하세요.z-index 값이 1, 2, 30, 40, 120, 220 등으로 산발적으로 사용됩니다. 예측 가능한 스태킹 컨텍스트를 위해 CSS 변수나 주석으로 z-index 계층을 문서화하세요.
💡 권장 패턴 예시
:root { --z-base: 1; --z-sticky-header: 30; --z-dropdown: 100; --z-modal: 200; }Also applies to: 238-238, 252-252, 270-270, 274-274, 315-315, 321-321, 550-550
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/AttendanceManagementCard.module.css` around lines 200 - 206, 파일 전반에 흩어진 하드코딩된 z-index 값을 시스템화해야 합니다: 루트에 :root { --z-base:1; --z-sticky-header:30; --z-dropdown:100; --z-modal:200; } 같은 CSS 변수를 정의하고 기존의 고정 값들을 해당 변수로 대체하세요 (예: .attendanceSelectWrap.open의 z-index: 40 → z-index: var(--z-dropdown)). 같은 방식으로 파일 내 다른 셀렉터들(문제된 위치들에서 사용한 z-index 1,2,30,40,120,220 등)을 찾아 적절한 변수로 매핑하고 주석으로 계층 설명을 추가해 스태킹 컨텍스트를 문서화하세요.frontend/src/components/attendancemanage/SessionManagementCard.module.css (5)
513-521:!important사용을 피하세요.
flex-wrap: nowrap !important;는 specificity 문제를 암시합니다.!important는 디버깅을 어렵게 하고 향후 스타일 오버라이드를 복잡하게 만듭니다. 선택자 specificity를 조정하거나 CSS 구조를 재검토하세요.♻️ 권장 수정안
.headerControls { - flex-wrap: nowrap !important; + flex-wrap: nowrap; width: 100%; min-width: 0; overflow-x: auto; overflow-y: hidden; padding-bottom: 2px; margin-left: 0; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/SessionManagementCard.module.css` around lines 513 - 521, The .headerControls rule in SessionManagementCard.module.css uses "flex-wrap: nowrap !important;" which should be removed; instead, eliminate the !important and resolve the specificity conflict by making the selector more specific (e.g., target the parent + .headerControls or add a dedicated modifier class used in the component) or by placing the rule later in the stylesheet/module so it naturally overrides the competing rule; update the component markup if needed to add the modifier class (referencing .headerControls) so the plain "flex-wrap: nowrap" applies without !important.
1-13: 중복된.sessionManagementCardContainer선택자가 존재합니다.동일한 선택자가 두 번 정의되어 있습니다 (Lines 1-13, Lines 471-478). 나중에 정의된 규칙이 이전 규칙을 덮어씁니다. 유지보수성을 위해 하나의 선택자로 통합하는 것이 좋습니다.
Also applies to: 471-478
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/SessionManagementCard.module.css` around lines 1 - 13, There are duplicate .sessionManagementCardContainer rules; consolidate them by locating both definitions for the .sessionManagementCardContainer selector, merge their CSS properties into a single rule (preserve all unique declarations and resolve any conflicting values by choosing the intended one), remove the redundant duplicate block, and ensure the final single .sessionManagementCardContainer contains the combined styles so the later rule no longer silently overrides the earlier one.
168-193: 테이블 컬럼 너비 정의가 중복되어 충돌합니다.Lines 168-193에서 백분율 기반 너비(
width: 22%등)로 정의한 후, Lines 562-598에서 픽셀 기반 고정 너비(width: 96px등)로 재정의합니다. 의도적인 변경이라면 이전 정의를 제거하세요.Also applies to: 562-598
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/SessionManagementCard.module.css` around lines 168 - 193, The CSS sets column widths twice (percent-based selectors like ".table thead th:nth-child(1)"/"...td:nth-child(1)" and later pixel-based selectors for the same nth-child columns), causing conflicting rules; pick one sizing strategy and remove the other to avoid override conflicts—either keep the percent-based rules (remove the pixel-based block around the later ".table thead th:nth-child(n)" / ".table tbody td:nth-child(n)" rules with widths like 96px) or replace the percent rules with the pixel ones so only one set remains, and if you must keep both, make intent explicit by renaming classes or increasing specificity (e.g., add a modifier class to the table) so selectors don't collide.
86-92:.table선택자의 너비 전략이 중복 정의되어 있습니다.Lines 86-92에서
min-width: 600px로 정의되었다가 Lines 541-544에서width: max-content; min-width: 100%로 재정의됩니다. CSS 캐스케이드로 인해 나중 정의가 적용되지만, 코드 가독성과 유지보수를 위해 하나로 통합하세요.Also applies to: 541-544
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/SessionManagementCard.module.css` around lines 86 - 92, The .table selector has conflicting width rules defined in two places (one set using width: 100%; min-width: 600px and the other using width: max-content; min-width: 100%); pick the intended sizing strategy and consolidate into a single .table rule: remove the duplicate/contradicting declaration and keep only the correct combination (e.g., width: 100% with min-width: 600px OR width: max-content with min-width: 100%), update any layout assumptions in related CSS if needed, and ensure only the chosen properties remain so the cascade is not relied upon to resolve contradictions.
315-355: 미디어 쿼리 순서 및 중복에 주의하세요.
min-width와max-width미디어 쿼리가 혼재되어 있고 일부 브레이크포인트에서 규칙이 중복됩니다. 예를 들어 Lines 315-355의@media (min-width: 768px)와 Lines 632-670의@media (max-width: 768px)가 768px에서 충돌할 수 있습니다. 일관된 모바일 퍼스트 또는 데스크톱 퍼스트 전략을 사용하세요.Also applies to: 632-670, 672-692
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/attendancemanage/SessionManagementCard.module.css` around lines 315 - 355, There are overlapping min-width and max-width media queries around 768px causing duplicate/conflicting rules (see selectors like .sessionManagementCardContainer, .selectGroup, .sessionSelect, .tableGroup, .table thead th, .table tbody td, .menuButton, .noData). Pick a consistent strategy (mobile-first using only min-width or desktop-first using only max-width), consolidate duplicated rules across the `@media` (min-width: 768px) and `@media` (max-width: 768px) blocks into a single breakpoint block, and remove/merge conflicting declarations so the final CSS for each selector appears only once per breakpoint; if you must keep both styles, shift one breakpoint off 768px (e.g., use max-width: 767px or min-width: 769px) to eliminate the 768px overlap.
🤖 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/RoundDayPicker.jsx`:
- Line 8: DEFAULT_END_TIME_MINUTES is hard-coded to 60 and causes closeAt to be
computed incorrectly, ignoring per-session allowedMinutes; update the logic so
handleComplete uses the actual session.allowedMinutes when computing closeAt
instead of DEFAULT_END_TIME_MINUTES: remove reliance on DEFAULT_END_TIME_MINUTES
in RoundDayPicker.jsx (and any uses at lines referenced), read the
allowedMinutes from the selected session object, compute end time = start time +
session.allowedMinutes, and pass that computed closeAt to the API (preserving
timezone/formatting used by AttendanceContext.jsx and
utils/attendanceManage.js).
In `@frontend/src/components/mypage/EditProfileModal.module.css`:
- Around line 10-12: In EditProfileModal.module.css remove the stray blank line
between the two declarations so the block reads "padding: 20px; z-index: 3000;"
(i.e., place the z-index declaration immediately after the padding declaration)
to satisfy the declaration-empty-line-before rule; if the blank line was
intentional, instead add a stylelint disable comment for
declaration-empty-line-before scoped to the z-index line.
In `@frontend/src/components/VerificationModal.module.css`:
- Around line 604-608: The overlay currently uses a fixed padding-bottom which
ignores the mobile safe-area inset and can cause extra scroll; change the
.overlay padding-bottom to account for env(safe-area-inset-bottom) (e.g., use
max(12px, env(safe-area-inset-bottom))) and also update any modal container
max-height calculation (the rule that subtracts fixed vertical offsets) to
include subtracting env(safe-area-inset-bottom) so the modal's max-height
accounts for the bottom inset and prevents unwanted extra scrolling.
---
Outside diff comments:
In `@frontend/src/components/attendancemanage/SessionSettingCard.jsx`:
- Around line 94-102: The number input with id "sessionAvailableTime" in
SessionSettingCard.jsx uses maxLength="3" which is ignored for type="number";
change to a proper numeric limit by adding a max="999" attribute and enforce
validation in the onChange handler: when handling e.target.value in the
setAllowedMinutes call, coerce/validate the value (e.g., strip non-digits, limit
length to 3 or clamp to 0–999) before calling setAllowedMinutes so the stored
state respects the 3-digit constraint. Ensure you update the input attributes
and the onChange logic that references allowedMinutes and setAllowedMinutes.
In `@frontend/src/pages/AttendanceManage.module.css`:
- Around line 34-38: .cardLayout defines three grid areas
('settings','session','roster') but JSX only renders two direct children
(.leftColumn and AttendanceManagementCard) and the child components
(SessionSettingCard, SessionManagementCard, AttendanceManagementCard) do not
have the corresponding area classes, so the grid won't lay out as intended; fix
by either adding the grid-area classes to the rendered elements (apply
className="settings" to the container wrapping
SessionSettingCard/SessionManagementCard and className="session"/"roster" where
appropriate, or add className="settings"/"session"/"roster" to those component
root elements) or simplify .cardLayout to match the actual JSX structure (remove
unused grid-template-areas or combine them), targeting the .cardLayout,
.leftColumn, SessionSettingCard, SessionManagementCard, and
AttendanceManagementCard symbols to implement the change.
---
Nitpick comments:
In `@frontend/src/components/attendancemanage/AttendanceManagementCard.jsx`:
- Around line 45-64: getRoleDisplayLabel currently uses substring checks (e.g.,
normalized.includes('MANAGE')) which can produce false positives; change the
matching to exact enum comparisons on the normalized role (e.g., compare
normalized === 'OWNER' / 'MANAGER' / 'PARTICIPANT' or use a strict set lookup)
so the function maps only the intended backend SessionRole values to Korean
labels; update getRoleDisplayLabel to normalize role and then do exact matches
(or a lookup map) and keep the fallback to roleText || '팀원'.
In
`@frontend/src/components/attendancemanage/AttendanceManagementCard.module.css`:
- Around line 1-13: Duplicate .attendanceManagementCardContainer rules exist;
merge them into one definition by consolidating all properties from both
occurrences (lines showing .attendanceManagementCardContainer) into a single
block, remove the later duplicate, and ensure any conflicting properties are
resolved by choosing the intended value (prefer the later value if that was
intentional). Update any comments and run a quick UI check to confirm
box-shadow, border, padding, background, transition, overflow, and sizing behave
as expected.
- Around line 381-406: There are duplicate column-width rules for the table
(selectors like .table thead th:nth-child(1) / tbody td:nth-child(1) through
.table thead th:nth-child(n + 5) / tbody td:nth-child(n + 5)) that conflict with
another block (e.g., the 2nd column defined as 120px here but redefined as 76px
later); pick the intended widths and remove or consolidate the redundant CSS
block so only one authoritative set of widths remains (either keep the 381–406
definitions and delete the later overrides, or merge the final values into this
set), ensuring selectors (.table thead th:nth-child(n) and .table tbody
td:nth-child(n)) match exactly and preserve min-width where needed.
- Around line 136-139: Remove the !important usages on .checkboxHeader and
.checkboxCell by increasing selector specificity or adding a dedicated utility
class; for example, replace the rules using ".checkboxHeader, .checkboxCell {
text-align: center !important; }" with a more specific selector such as
".attendanceCard .checkboxHeader, .attendanceCard .checkboxCell { text-align:
center; }" or add a new ".centerText" class with "text-align: center;" and apply
it in the component JSX where CheckboxHeader/CheckboxCell are rendered; ensure
any conflicting rules (other selectors targeting these elements) are adjusted or
removed so the new non-!important rules take effect.
- Around line 200-206: 파일 전반에 흩어진 하드코딩된 z-index 값을 시스템화해야 합니다: 루트에 :root {
--z-base:1; --z-sticky-header:30; --z-dropdown:100; --z-modal:200; } 같은 CSS 변수를
정의하고 기존의 고정 값들을 해당 변수로 대체하세요 (예: .attendanceSelectWrap.open의 z-index: 40 →
z-index: var(--z-dropdown)). 같은 방식으로 파일 내 다른 셀렉터들(문제된 위치들에서 사용한 z-index
1,2,30,40,120,220 등)을 찾아 적절한 변수로 매핑하고 주석으로 계층 설명을 추가해 스태킹 컨텍스트를 문서화하세요.
In `@frontend/src/components/attendancemanage/SessionManagementCard.module.css`:
- Around line 513-521: The .headerControls rule in
SessionManagementCard.module.css uses "flex-wrap: nowrap !important;" which
should be removed; instead, eliminate the !important and resolve the specificity
conflict by making the selector more specific (e.g., target the parent +
.headerControls or add a dedicated modifier class used in the component) or by
placing the rule later in the stylesheet/module so it naturally overrides the
competing rule; update the component markup if needed to add the modifier class
(referencing .headerControls) so the plain "flex-wrap: nowrap" applies without
!important.
- Around line 1-13: There are duplicate .sessionManagementCardContainer rules;
consolidate them by locating both definitions for the
.sessionManagementCardContainer selector, merge their CSS properties into a
single rule (preserve all unique declarations and resolve any conflicting values
by choosing the intended one), remove the redundant duplicate block, and ensure
the final single .sessionManagementCardContainer contains the combined styles so
the later rule no longer silently overrides the earlier one.
- Around line 168-193: The CSS sets column widths twice (percent-based selectors
like ".table thead th:nth-child(1)"/"...td:nth-child(1)" and later pixel-based
selectors for the same nth-child columns), causing conflicting rules; pick one
sizing strategy and remove the other to avoid override conflicts—either keep the
percent-based rules (remove the pixel-based block around the later ".table thead
th:nth-child(n)" / ".table tbody td:nth-child(n)" rules with widths like 96px)
or replace the percent rules with the pixel ones so only one set remains, and if
you must keep both, make intent explicit by renaming classes or increasing
specificity (e.g., add a modifier class to the table) so selectors don't
collide.
- Around line 86-92: The .table selector has conflicting width rules defined in
two places (one set using width: 100%; min-width: 600px and the other using
width: max-content; min-width: 100%); pick the intended sizing strategy and
consolidate into a single .table rule: remove the duplicate/contradicting
declaration and keep only the correct combination (e.g., width: 100% with
min-width: 600px OR width: max-content with min-width: 100%), update any layout
assumptions in related CSS if needed, and ensure only the chosen properties
remain so the cascade is not relied upon to resolve contradictions.
- Around line 315-355: There are overlapping min-width and max-width media
queries around 768px causing duplicate/conflicting rules (see selectors like
.sessionManagementCardContainer, .selectGroup, .sessionSelect, .tableGroup,
.table thead th, .table tbody td, .menuButton, .noData). Pick a consistent
strategy (mobile-first using only min-width or desktop-first using only
max-width), consolidate duplicated rules across the `@media` (min-width: 768px)
and `@media` (max-width: 768px) blocks into a single breakpoint block, and
remove/merge conflicting declarations so the final CSS for each selector appears
only once per breakpoint; if you must keep both styles, shift one breakpoint off
768px (e.g., use max-width: 767px or min-width: 769px) to eliminate the 768px
overlap.
In `@frontend/src/components/attendancemanage/SessionSettingCard.module.css`:
- Around line 97-107: The current .compactTextInput and .compactMinuteInput
rules rely on multiple !important flags which make future overrides fragile;
remove the !important declarations and instead increase selector specificity
(for example by scoping under the parent component class or combining selectors
like .sessionSettingCard .compactTextInput / .sessionSettingCard
.compactMinuteInput) or adjust the CSS module export so the styles win without
!important, keeping the clamp(...) values intact and preserving
width/min-width/max-width behavior.
In `@frontend/src/components/Board/Modal.module.css`:
- Line 11: Replace the hardcoded z-index value in Modal.module.css (the CSS rule
containing "z-index: 3000;") with a shared CSS custom property to avoid magic
numbers; add a global variable (e.g. --z-modal-overlay) in your root/global
stylesheet and update the Modal.module.css rule to use that variable instead of
3000 so all components reference the same token.
In `@frontend/src/components/login/LoginForm.jsx`:
- Around line 102-109: The password toggle button in LoginForm.jsx should expose
its pressed state via aria-pressed; update the button that uses setShowPassword
and showPassword (className styles.passwordToggleButton) to include
aria-pressed={showPassword} so the attribute reflects the boolean state,
ensuring it stays a proper toggle button for assistive tech.
In `@frontend/src/components/LoginAndSignUpForm.module.css`:
- Around line 87-106: The .passwordToggleButton styles only define hover state;
add explicit keyboard focus styles so keyboard users can see focus—implement
.passwordToggleButton:focus and/or .passwordToggleButton:focus-visible rules
(matching or complementing the hover color change) that provide a clear,
high-contrast visible indicator (e.g., outline or box-shadow) while preserving
the existing layout and sizing for the passwordToggleButton element.
In `@frontend/src/components/signup/SignUpForm.jsx`:
- Around line 296-308: The password match message block (controlled by
hasConfirmPasswordInput and isPasswordMatch) is a dynamic live region for screen
readers; add an aria-live attribute (e.g., aria-live="polite") to the outer <p>
and consider aria-atomic="true" so updates are fully announced, keeping the
existing classNames (styles.passwordMatchMessage,
styles.passwordMatchMessageSuccess, styles.passwordMatchMessageError) and
message logic intact; ensure you update the JSX for the <p> rendered by the
conditional that references hasConfirmPasswordInput and isPasswordMatch.
- Around line 248-265: Extract the repeated password input + toggle block into a
reusable component (e.g., PasswordFieldWithToggle) and replace both occurrences
in SignUpForm.jsx with that component; the new component should accept props for
value, onChange (use handlePasswordChange), id, placeholder, autoComplete and
any className (use styles.inputWithToggle and styles.passwordToggleButton) and
internally manage its own showPassword state and render Eye / EyeOff icons
accordingly, preserving aria-label behavior and button type="button".
In `@frontend/src/pages/AttendanceManage.module.css`:
- Around line 52-61: The `.roster > *` CSS rule is not applying because the
rendered JSX doesn’t use the `.roster` class; check where
AttendanceManagementCard is rendered and either (a) add the roster module class
to the container element that wraps AttendanceManagementCard (so `.roster > * {
width:100% }` applies), or (b) change the selector in
AttendanceManage.module.css to target the actual class name used in the JSX (the
wrapper/component class around AttendanceManagementCard) so child elements get
width:100%; update the JSX/class names accordingly and verify the layout.
In `@frontend/src/pages/PostDetail.module.css`:
- Around line 860-869: The CSS uses a global :root custom property
(--width-content) inside the mobile media query which can conflict with other
CSS Modules later; change the rule so the variable is scoped or inlined—either
move the value into .postDetail (e.g., set .postDetail {
--postDetail-width-content: 100%; } and use that locally) or rename the variable
to a more specific name (e.g., --postDetail-width-content) and update all
references, and ensure the media query remains `@media` (max-width: 767px) for
.postDetail.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5d08c1e0-2042-4c9a-8589-a4e64fe6ab4c
📒 Files selected for processing (27)
frontend/src/components/AdminMemberApproval/AdminMemberApproval.module.cssfrontend/src/components/AdminMemberManage/AdminMemberManage.module.cssfrontend/src/components/Board/CreateSubBoardModal.module.cssfrontend/src/components/Board/Modal.module.cssfrontend/src/components/Board/PostDetail/CommentSection.jsxfrontend/src/components/LoginAndSignUpForm.module.cssfrontend/src/components/Sidebar.jsxfrontend/src/components/VerificationModal.module.cssfrontend/src/components/attendance/SessionManage.jsxfrontend/src/components/attendance/SessionManage.module.cssfrontend/src/components/attendancemanage/AttendanceManagementCard.jsxfrontend/src/components/attendancemanage/AttendanceManagementCard.module.cssfrontend/src/components/attendancemanage/RoundDayPicker.jsxfrontend/src/components/attendancemanage/SessionManagementCard.jsxfrontend/src/components/attendancemanage/SessionManagementCard.module.cssfrontend/src/components/attendancemanage/SessionSettingCard.jsxfrontend/src/components/attendancemanage/SessionSettingCard.module.cssfrontend/src/components/backtest/BacktestTemplateSaveModal.module.cssfrontend/src/components/login/LoginForm.jsxfrontend/src/components/mypage/ActivityModal.module.cssfrontend/src/components/mypage/EditProfileModal.module.cssfrontend/src/components/quantbot/ReportModal.cssfrontend/src/components/signup/SignUpForm.jsxfrontend/src/pages/AttendanceManage.module.cssfrontend/src/pages/Board.jsxfrontend/src/pages/PostDetail.jsxfrontend/src/pages/PostDetail.module.css
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/AttendanceManagementCard.jsx`:
- Around line 157-175: The header "select all" and related selection logic
currently uses attendanceData.userRows (all users) while the table renders
paginatedUserRows; update toggleAllUsers, the header checkbox
checked/indeterminate calculations, and any selection-count logic to operate on
paginatedUserRows (derived from sortedUserRows using currentPage and
USERS_PER_PAGE) instead of attendanceData.userRows so the selection scope
matches the visible page; also adjust any other places referencing
attendanceData.userRows for selection (see occurrences near the other mentions)
to use paginatedUserRows or subsets thereof.
- Around line 45-64: getRoleDisplayLabel currently checks for
OWNER/MANAGE/PARTICIPANT tokens but backend sends roles as Korean strings
("관리자"/"일반") and there is a separate getRoleSortPriority mapping for "세션 생성자";
update getRoleDisplayLabel (and the similar logic around lines 72-84) to
normalize incoming role value and map the exact backend strings ("세션 생성자",
"관리자", "일반") to the correct display labels ("소유자"/"관리자"/"팀원") so display and
getRoleSortPriority use the same canonical set of role identifiers; ensure
trimming/upper/lower normalization is consistent before comparisons and fall
back to '팀원' when unknown.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7a93edc6-cd71-4d3f-9a7d-3a04fe1e26bd
📒 Files selected for processing (4)
frontend/src/components/VerificationModal.module.cssfrontend/src/components/attendancemanage/AddUsersModal.jsxfrontend/src/components/attendancemanage/AttendanceManagementCard.jsxfrontend/src/components/attendancemanage/AttendanceManagementCard.module.css
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/components/VerificationModal.module.css
출석 조회 목록 및 관리 핸드폰 기준 ui 적용
기타 모바일 반응형 ui 적용
비밀번호 입력 시 확인 기능 추가 및 회원가입 시 비밀번호 확인 불일치 시 문구로 확인 가능하게 수정
권한별 사이드바 목록 제한 반영 등
Summary by CodeRabbit
릴리스 노트
새로운 기능
버그 수정
스타일