[FE] SISC1-216 [FEAT] 외부페이지 제작(동아리소개, 임원소개, 운용포트폴리오)#175
Conversation
Walkthrough외부 페이지용 React 컴포넌트(Filter, Info, MemberCard, PortfolioItem)와 대응 CSS 모듈을 추가하고, Intro·Leaders·Portfolio 페이지를 Filter/Info/MemberCard/PortfolioItem으로 연동하며 External.module.css와 MonthlyReport.module.css를 확장했습니다. executivesByGeneration 유틸도 추가되었습니다. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
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 |
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (6)
frontend/src/components/external/Filter.module.css (2)
1-6: 고정 너비가 작은 화면에서 문제를 일으킬 수 있습니다.
.wrap에width: 220px로 고정 너비가 설정되어 있습니다. 모바일이나 좁은 뷰포트에서 레이아웃이 깨지거나 콘텐츠가 잘릴 수 있습니다.max-width를 사용하거나 미디어 쿼리로 반응형으로 만드는 것을 고려해보세요.
66-68: 스크롤바를 숨기면 사용성이 저하될 수 있습니다.웹킷 스크롤바를 완전히 숨기면 사용자가 스크롤 가능한 콘텐츠가 있다는 것을 인지하기 어렵습니다. 특히 필터 아이템이 많을 경우 문제가 될 수 있습니다. 스크롤바를 얇게 스타일링하거나 다른 시각적 단서를 제공하는 것을 고려해보세요.
frontend/src/components/external/Info.jsx (1)
3-17: 팀 정보 데이터를 외부 파일로 분리하는 것을 고려하세요.
teamInfo객체가 컴포넌트 내부에 하드코딩되어 있어 유지보수가 어렵습니다.executiveByGeneration.js처럼 별도의 데이터 파일로 분리하면:
- 데이터 관리가 용이
- 컴포넌트 코드가 간결
- 향후 API 연동 시 마이그레이션이 쉬움
frontend/src/pages/external/Portfolio.jsx (1)
7-28: mock 데이터를 별도 파일로 분리하는 것을 고려하세요.현재 mockPortfolio가 컴포넌트 내부에 정의되어 있습니다. Leaders.jsx에서 사용하는 executivesByGeneration.js처럼 별도의 유틸리티 파일로 분리하면 일관성과 유지보수성이 향상됩니다.
🔎 데이터 분리 예시
frontend/src/utils/mockPortfolio.js생성:export const mockPortfolio = [ { id: 1, role: '운영진', time: '2', title: '자산 배분 전략 및 성과 보고서', }, // ... 나머지 항목들 ];Portfolio.jsx에서 import:
+import { mockPortfolio } from '../../utils/mockPortfolio'; import { useState } from 'react'; -const mockPortfolio = [ - { - role: '운영진', - ... - }, -]; - const Portfolio = () => {frontend/src/components/external/MemberCard.module.css (1)
14-18: 고정된 카드 크기가 작은 화면에서 문제가 될 수 있습니다.카드의 너비와 높이가 고정값(260px x 340px)으로 설정되어 있어 모바일 기기나 작은 화면에서 레이아웃이 깨질 수 있습니다. max-width 또는 상대 단위 사용을 고려하세요.
🔎 반응형 개선 예시
.card { - width: 260px; - height: 340px; + width: 100%; + max-width: 260px; + aspect-ratio: 260 / 340; background-color: #f4f4f4; }또는 컨테이너 기준 상대 크기:
.card { - width: 260px; - height: 340px; + width: clamp(200px, 100%, 260px); + height: clamp(265px, calc(100% * 340 / 260), 340px); background-color: #f4f4f4; }frontend/src/pages/external/External.module.css (1)
32-36: 고정 패딩이 작은 화면에서 레이아웃 문제를 일으킬 수 있습니다..info와 .portfolio 섹션에 고정 패딩(80px 100px)이 적용되어 있어 모바일 기기에서 콘텐츠 영역이 너무 좁아질 수 있습니다. 반응형 패딩 사용을 고려하세요.
🔎 반응형 패딩 개선 예시
.info { display: flex; - padding: 80px 100px; + padding: clamp(20px, 5vw, 80px) clamp(20px, 8vw, 100px); gap: 45px; } .portfolio { display: flex; flex-direction: column; justify-content: center; - padding: 80px 100px; + padding: clamp(20px, 5vw, 80px) clamp(20px, 8vw, 100px); gap: 45px; }또는 미디어 쿼리 사용:
.info, .portfolio { padding: 80px 100px; } @media (max-width: 768px) { .info, .portfolio { padding: 40px 20px; } }Also applies to: 68-74
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
frontend/src/components/external/Filter.jsx(1 hunks)frontend/src/components/external/Filter.module.css(1 hunks)frontend/src/components/external/Info.jsx(1 hunks)frontend/src/components/external/Info.module.css(1 hunks)frontend/src/components/external/MemberCard.jsx(1 hunks)frontend/src/components/external/MemberCard.module.css(1 hunks)frontend/src/components/external/PortfolioItem.jsx(1 hunks)frontend/src/components/external/PortfolioItem.module.css(1 hunks)frontend/src/pages/external/External.module.css(2 hunks)frontend/src/pages/external/Intro.jsx(1 hunks)frontend/src/pages/external/Leaders.jsx(1 hunks)frontend/src/pages/external/MonthlyReport.module.css(1 hunks)frontend/src/pages/external/Portfolio.jsx(1 hunks)frontend/src/utils/executiveByGeneration.js(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
frontend/src/pages/external/Leaders.jsx (4)
frontend/src/pages/external/Intro.jsx (1)
selected(18-18)frontend/src/components/external/Filter.jsx (1)
Filter(3-31)frontend/src/components/external/MemberCard.jsx (1)
MemberCard(3-19)frontend/src/utils/executiveByGeneration.js (2)
executivesByGeneration(1-23)executivesByGeneration(1-23)
frontend/src/pages/external/Portfolio.jsx (3)
frontend/src/components/Board/SearchBar.jsx (1)
SearchBar(5-38)frontend/src/components/external/PortfolioItem.jsx (1)
PortfolioItem(4-19)frontend/src/components/stockgame/Pagination.jsx (1)
Pagination(3-77)
frontend/src/pages/external/Intro.jsx (3)
frontend/src/pages/external/Leaders.jsx (1)
selected(10-10)frontend/src/components/external/Filter.jsx (1)
Filter(3-31)frontend/src/components/external/Info.jsx (1)
Info(19-26)
🪛 Biome (2.1.2)
frontend/src/components/external/MemberCard.jsx
[error] 8-8: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
🔇 Additional comments (7)
frontend/src/components/external/Info.module.css (1)
1-21: LGTM!CSS 모듈 스타일이 깔끔하고 일관성 있게 작성되었습니다.
word-break: keep-all은 한국어 텍스트에 적합한 설정입니다.frontend/src/pages/external/MonthlyReport.module.css (1)
12-12: LGTM!
background-size: cover추가로 헤더 배경 이미지가 컨테이너를 올바르게 채우도록 개선되었습니다.frontend/src/components/external/PortfolioItem.module.css (1)
1-50: LGTM!포트폴리오 아이템의 레이아웃과 스타일링이 명확하고 일관성 있게 정의되었습니다.
frontend/src/pages/external/Leaders.jsx (2)
7-7: cohort 배열 생성이 올바르게 동작합니다.24개 기수를 역순으로 생성하는 로직이 정확합니다.
10-10: 초기 상태 설정을 검증하세요.
cohort[0]을 초기값으로 사용하는 것은 좋지만,executivesByGeneration에 해당 데이터가 존재하는지 확인해야 합니다. 위의 데이터 누락 이슈가 해결되면 이 부분도 안전해집니다.frontend/src/components/external/Filter.jsx (1)
16-16: 현재 코드는 안전하므로 변경이 필요하지 않습니다.
cohort배열은Array.from({ length: 24 }, (_, i) => \${24 - i}기`)로 생성되어 '24기'부터 '1기'까지 고유한 값들을 가지며,teams배열도 모두 고유한 팀 이름으로 구성되어 있습니다. 따라서 현재key={label}` 사용은 안전하며 React 경고가 발생하지 않습니다.재사용성을 위해서는 index 기반 key가 아닌, 데이터에 고유 ID가 있다면 그것을 사용하거나, 없다면 items 배열의 각 요소가 고유한 속성을 갖도록 구조화하는 것이 좋습니다. (index 기반 key는 리스트 재정렬 시 버그를 유발할 수 있으므로 권장되지 않습니다)
Likely an incorrect or invalid review comment.
frontend/src/pages/external/Intro.jsx (1)
17-40: 구현이 깔끔하고 올바릅니다!Filter와 Info 컴포넌트가 적절히 통합되어 있으며, 상태 관리도 올바르게 구현되었습니다. 선택된 팀 정보가 Info 컴포넌트에 정확히 전달되고 있습니다.
1) 작업한 이슈번호
SISC1-216
2) 변경 요약 (What & Why)
3) 스크린샷/동영상 (UI 변경 시)
4) 상세 변경사항 (전부 다)
5) 참고사항
API 연동 시에 전체적으로 코드 수정 예정
Summary by CodeRabbit
릴리스 노트
새로운 기능
스타일
✏️ Tip: You can customize this high-level summary in your review settings.