Skip to content

[FE] SISC1-227 [FEAT] : 세투연 월간 리포트 구현#163

Merged
DongEun02 merged 10 commits intomainfrom
SISC1-227-FE-monthly-sisc-ui
Dec 6, 2025
Merged

[FE] SISC1-227 [FEAT] : 세투연 월간 리포트 구현#163
DongEun02 merged 10 commits intomainfrom
SISC1-227-FE-monthly-sisc-ui

Conversation

@DongEun02
Copy link
Contributor

@DongEun02 DongEun02 commented Dec 4, 2025

1) 작업한 이슈번호

SISC1-227

2) 변경 요약 (What & Why)

  • 무엇을 변경했는지: 외부페이지 - 월간 리포트 페이지 구현
  • 변경했는지(문제/목표):

3) 스크린샷/동영상 (UI 변경 시)

전/후 비교, 반응형(모바일/데스크톱) 캡쳐

  • Before:
  • After:
image image

4) 상세 변경사항 (전부 다)

  • 라우팅/페이지: MonthlyReport.jsx, MonthlyReportDetail.jsx
  • 컴포넌트: Content.jsx, Report.jsx
  • 상태관리:
  • API 호출:
  • 스타일: MonthlyReport.module.css, MonthlyReportDetail.module.css, Content.module.css, Report.module.css
  • 기타: reportContent.js

5) 참고사항

현재 임시로 이미지를 전부 저장하여 구현하였지만 추후 API 연동 후 로직 변경 예정입니다.

Summary by CodeRabbit

  • 새로운 기능

    • 월간 세투연 페이지와 메뉴 항목 추가
    • 월간 보고서 카드 및 상세 뷰 페이지 추가(상세 페이지에서 이미지 뷰어 제공)
    • 다중 페이지 콘텐츠를 두 장씩 보여주고 진행도를 표시하는 이미지 뷰어 추가
  • 스타일

    • 관련 페이지 및 컴포넌트 전용 스타일 모듈 추가/조정 (헤더 이미지 경로 포함)

✏️ Tip: You can customize this high-level summary in your review settings.

@DongEun02 DongEun02 requested a review from gxuoo as a code owner December 4, 2025 16:17
@coderabbitai
Copy link

coderabbitai bot commented Dec 4, 2025

Walkthrough

월간 보고서 기능(목록 및 상세 페이지)과 두-페이지 이미지 갤러리 뷰어, 관련 라우트·컴포넌트·스타일·이미지 자산(22개)이 추가되고 일부 외부 이미지 경로와 네비게이션 항목이 갱신되었습니다.

Changes

코호트 / 파일(s) 변경 내용
라우팅 / 앱 엔트리
frontend/src/App.jsx
MonthlyReport, MonthlyReportDetail 컴포넌트 임포트 및 /main/monthly-report, /main/monthly-report-detail 라우트 추가
월간 보고서 목록 페이지
frontend/src/pages/external/MonthlyReport.jsx, frontend/src/pages/external/MonthlyReport.module.css
MonthlyReport 페이지 컴포넌트 추가 — 로고·제목·4개 Report 카드 렌더링 및 관련 스타일 추가
월간 보고서 상세 페이지
frontend/src/pages/external/MonthlyReportDetail.jsx, frontend/src/pages/external/MonthlyReportDetail.module.css
MonthlyReportDetail 페이지 추가 — 헤더(목록으로 복귀) 및 Content 갤러리 포함, 스타일 추가
리포트 카드 컴포넌트
frontend/src/components/external/Report.jsx, frontend/src/components/external/Report.module.css
클릭 가능한 보고서 카드 컴포넌트 추가(배경 이미지, 네비게이션), 스타일 추가
이미지 갤러리 뷰어
frontend/src/components/external/Content.jsx, frontend/src/components/external/Content.module.css
두-페이지 페어 뷰어 컴포넌트 추가 — current 인덱스, goPrev/goNext(±2), 진행률 바, 반응형 스타일
리포트 이미지 유틸리티
frontend/src/utils/reportContent.js
22개 이미지(cover + content1..content21) 임포트 및 pages 배열로 내보내기
네비게이션 / 자산 경로 업데이트
frontend/src/pages/external/Main.jsx, frontend/src/pages/external/External.module.css
외부 이미지 임포트 경로 수정(.../external/external-image.png), 메인 메뉴에 /main/monthly-report 항목 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Router
    participant MonthlyReport as MonthlyReport (목록)
    participant Report as Report (카드)
    participant MonthlyReportDetail as MonthlyReportDetail (상세)
    participant Content as Content (갤러리)

    User->>Router: GET /main/monthly-report
    Router->>MonthlyReport: render list
    MonthlyReport->>Report: render N cards

    User->>Report: click card
    Report->>Router: navigate /main/monthly-report-detail

    Router->>MonthlyReportDetail: render detail
    MonthlyReportDetail->>Content: mount Content (pages[])
    Content->>Content: set index = 0, show pages[0]/pages[1]

    User->>Content: click Next
    Content->>Content: index += 2, update progress
    User->>Content: click Prev
    Content->>Content: index -= 2, update progress

    User->>MonthlyReportDetail: click header
    MonthlyReportDetail->>Router: navigate /main/monthly-report
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 분

  • 주목 파일: frontend/src/components/external/Content.jsx (페이지 인덱스·경계 로직), frontend/src/utils/reportContent.js (이미지 경로/순서), 라우팅 추가점(frontend/src/App.jsx) 검토 권장
  • 스타일 모듈 여러 파일(레이아웃/반응형) 적용 확인 필요

Possibly related PRs

Suggested reviewers

  • gxuoo

Poem

🐰 스물두 장을 품은 달의 보고서,
좌우로 훌쩍 넘어가는 페이지 소리,
진행률이 반짝이면 마음도 찰칵,†
목록에서 상세로 깡충 뛰어들고,
작은 당근처럼 기쁜 배포날! 📄✨

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 변경 내용의 주요 목표를 명확하게 반영합니다. 세투연 월간 리포트 구현이라는 핵심 기능 추가 내용을 요약하고 있습니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch SISC1-227-FE-monthly-sisc-ui

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84a2309 and 95b8f32.

📒 Files selected for processing (5)
  • frontend/src/components/external/Content.jsx (1 hunks)
  • frontend/src/components/external/Content.module.css (1 hunks)
  • frontend/src/components/external/Report.module.css (1 hunks)
  • frontend/src/pages/external/MonthlyReport.module.css (1 hunks)
  • frontend/src/pages/external/MonthlyReportDetail.module.css (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • frontend/src/components/external/Report.module.css
  • frontend/src/pages/external/MonthlyReportDetail.module.css
  • frontend/src/components/external/Content.module.css
  • frontend/src/pages/external/MonthlyReport.module.css
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/components/external/Content.jsx (1)
frontend/src/utils/reportContent.js (2)
  • pages (24-47)
  • pages (24-47)

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

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

🧹 Nitpick comments (3)
frontend/src/components/external/Report.jsx (1)

5-21: 클릭 카드에 버튼/Link 패턴을 쓰면 접근성이 좋아집니다.

현재는 div + onClick 으로만 이동을 처리해서 키보드 사용자(탭/Enter) 입장에서는 이 요소를 활성화하기 어렵습니다.
가능하다면 다음과 같이 개선하는 것을 권장드립니다.

  • 네비게이션 목적이라면 <Link to="/main/monthly-report-detail"> 로 래핑하고, CSS 로 카드 스타일을 적용.
  • 또는 <button type="button"> 로 바꾸고 onClick={() => nav('/main/monthly-report-detail')} 를 부여.
  • 기존처럼 div 를 유지해야 한다면 role="button"tabIndex={0} 를 주고, onKeyDown 에 Enter/Space 대응을 추가.

이렇게 하면 화면 리더 및 키보드 사용자까지 포함한 접근성이 크게 좋아집니다.

frontend/src/pages/external/MonthlyReport.jsx (1)

22-31: 게시물 개수/카드 개수 하드코딩 구조 개선 제안

4개 텍스트와 <Report /> 4개가 모두 하드코딩되어 있어서, 실제 데이터 연동 시 개수 불일치가 발생하기 쉽습니다.
차후 API 연동을 염두에 두고, 예를 들어 배열 길이를 기준으로 개수와 카드 렌더링을 같이 계산하는 형태로 바꾸는 것을 추천합니다.

-      <div className={styles.countSection}>
-        <span className={styles.count}>
-          <strong style={{ color: '#339FFF' }}>4개</strong>의 게시물
-        </span>
-      </div>
-      <div className={styles.reportSection}>
-        <Report />
-        <Report />
-        <Report />
-        <Report />
-      </div>
+      {/*
+        TODO: API 연동 후 reports 데이터를 받아오도록 변경
+      */}
+      {(() => {
+        const reports = [1, 2, 3, 4]; // 임시 목업 데이터
+        return (
+          <>
+            <div className={styles.countSection}>
+              <span className={styles.count}>
+                <strong style={{ color: '#339FFF' }}>
+                  {reports.length}개
+                </strong>
+                의 게시물
+              </span>
+            </div>
+            <div className={styles.reportSection}>
+              {reports.map((id) => (
+                <Report key={id} />
+              ))}
+            </div>
+          </>
+        );
+      })()}
frontend/src/App.jsx (1)

36-40: 외부 월간 리포트 라우트 추가 구성 적절

/main/monthly-report/main/monthly-report-detail 라우트 구성이 Main 이하 외부 페이지 군과 잘 맞고, Report.jsxMonthlyReportDetail.jsxuseNavigate 경로('/main/monthly-report', '/main/monthly-report-detail')와도 정합성이 있습니다. 현재 요구사항 범위에서는 별도 중첩 라우트/레이아웃 분리는 없어도 충분해 보입니다.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 29ab579 and 84a2309.

⛔ Files ignored due to path filters (25)
  • frontend/src/assets/external/external-detail-image.png is excluded by !**/*.png
  • frontend/src/assets/external/external-image.png is excluded by !**/*.png
  • frontend/src/assets/external/monthly-report.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content1.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content10.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content11.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content12.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content13.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content14.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content15.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content16.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content17.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content18.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content19.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content2.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content20.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content21.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content3.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content4.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content5.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content6.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content7.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content8.png is excluded by !**/*.png
  • frontend/src/assets/external/report/content9.png is excluded by !**/*.png
  • frontend/src/assets/external/report/report-cover.png is excluded by !**/*.png
📒 Files selected for processing (12)
  • frontend/src/App.jsx (2 hunks)
  • frontend/src/components/external/Content.jsx (1 hunks)
  • frontend/src/components/external/Content.module.css (1 hunks)
  • frontend/src/components/external/Report.jsx (1 hunks)
  • frontend/src/components/external/Report.module.css (1 hunks)
  • frontend/src/pages/external/External.module.css (1 hunks)
  • frontend/src/pages/external/Main.jsx (2 hunks)
  • frontend/src/pages/external/MonthlyReport.jsx (1 hunks)
  • frontend/src/pages/external/MonthlyReport.module.css (1 hunks)
  • frontend/src/pages/external/MonthlyReportDetail.jsx (1 hunks)
  • frontend/src/pages/external/MonthlyReportDetail.module.css (1 hunks)
  • frontend/src/utils/reportContent.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
frontend/src/pages/external/MonthlyReport.jsx (1)
frontend/src/components/external/Report.jsx (1)
  • Report (5-23)
frontend/src/components/external/Report.jsx (1)
frontend/src/pages/external/MonthlyReportDetail.jsx (1)
  • nav (7-7)
frontend/src/pages/external/MonthlyReportDetail.jsx (2)
frontend/src/components/external/Report.jsx (1)
  • nav (6-6)
frontend/src/components/external/Content.jsx (1)
  • Content (5-52)
frontend/src/components/external/Content.jsx (1)
frontend/src/utils/reportContent.js (2)
  • pages (24-47)
  • pages (24-47)
frontend/src/App.jsx (2)
frontend/src/pages/external/MonthlyReport.jsx (1)
  • MonthlyReport (5-35)
frontend/src/pages/external/MonthlyReportDetail.jsx (1)
  • MonthlyReportDetail (6-22)
🔇 Additional comments (4)
frontend/src/pages/external/External.module.css (1)

9-10: 헤더 배경 이미지 경로 변경 문제 없어 보입니다.

폴더 구조(assets/external/...)와 일관되고, 기존과 동일한 배경 표시(center no-repeat)이어서 스타일/동작 상 이슈는 없어 보입니다.

frontend/src/pages/external/Main.jsx (1)

2-2: 월간 리포트 메뉴 추가 방향 적절합니다.

이미지 경로 변경 및 /main/monthly-report 링크 추가 모두 의도에 맞게 보입니다.
App.jsx 쪽 라우트 path(/main/monthly-report)와 문자열이 정확히 일치하는지만 한 번 더 확인해 주시면 좋겠습니다.

Also applies to: 21-23

frontend/src/utils/reportContent.js (1)

1-47: 현재 요구사항에는 충분히 단순하고 명시적인 구성입니다.

로컬 자산을 명시적으로 import 해서 pages 배열로 넘기는 구조라 Content 컴포넌트에서 사용하기 직관적입니다.
향후 페이지 수가 늘거나 줄 때에는, Content.jsx 의 2페이지 단위 넘김 로직(인덱스 +2씩 증가, progress 계산 등)과 항상 맞춰 주기만 하면 될 것 같습니다.

frontend/src/App.jsx (1)

22-23: 새 월간 리포트 페이지 import 정합성 확인

MonthlyReport, MonthlyReportDetail import 경로와 파일 구조가 외부 페이지들과 일관되고, 라우터 설정에서도 그대로 사용되고 있어 문제 없어 보입니다.

Comment on lines +6 to +13
const [current, setCurrent] = useState(0);
const goPrev = () => {
if (current > 1) setCurrent(current - 2);
};

const goNext = () => {
if (current < pages.length - 2) setCurrent(current + 2);
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

페이지 이동 로직과 우측 화살표 비활성 조건 불일치

현재 구현에서는:

  • goNextcurrent < pages.length - 2일 때만 current를 +2 하여 마지막 spread(예: 길이 22일 때 current = 20)까지만 이동하고,
  • 우측 화살표 disabled 조건은 current === pages.length - 1로 되어 있어, 실제로는 마지막 spread에서도 버튼이 비활성화되지 않습니다(클릭해도 state는 안 바뀌지만, UI 상으로는 계속 활성처럼 보임).

또한 setCurrent(current ± 2)는 콜백이 아니라 클로저 값을 쓰고 있어, 향후 로직 변경 시 예기치 못한 동작 여지가 있습니다.

아래처럼 boundary를 일관되게 맞추고, 콜백 형태로 상태를 갱신하는 편이 더 안전하고 직관적입니다.

-  const [current, setCurrent] = useState(0);
-  const goPrev = () => {
-    if (current > 1) setCurrent(current - 2);
-  };
-
-  const goNext = () => {
-    if (current < pages.length - 2) setCurrent(current + 2);
-  };
+  const [current, setCurrent] = useState(0);
+
+  const goPrev = () => {
+    setCurrent((prev) => Math.max(prev - 2, 0));
+  };
+
+  const goNext = () => {
+    setCurrent((prev) =>
+      Math.min(prev + 2, pages.length - 2),
+    );
+  };
@@
-        <button
-          className={styles.arrowBtn}
-          onClick={goNext}
-          disabled={current === pages.length - 1}
-        >
+        <button
+          className={styles.arrowBtn}
+          onClick={goNext}
+          disabled={current >= pages.length - 2}
+        >

추가로:

  • 현재 구현은 pages.length가 짝수(항상 2장 단위로 끝나는 경우)라는 전제를 깔고 있으므로, 추후 API에서 페이지 수가 홀수일 가능성이 있다면 마지막 한 장에 대한 처리(예: 오른쪽 이미지는 조건부 렌더링)를 고려해 두면 좋겠습니다.
  • 접근성을 위해 좌우 화살표 버튼에 aria-label="이전 페이지", aria-label="다음 페이지"를 부여하는 것도 추천드립니다.

Also applies to: 20-21, 25-48

🤖 Prompt for AI Agents
In frontend/src/components/external/Content.jsx around lines 6–13 (and also
apply same fix to 20–21, 25–48), the page navigation boundary logic and
disabled-state checks are inconsistent and setState uses closure values; compute
a single maxIndex = pages.length - (pages.length % 2 === 0 ? 2 : 1) and use that
for both navigation guards and button disabled checks, update goPrev/goNext to
use functional state updates (setCurrent(prev => Math.max(0, Math.min(maxIndex,
prev ± 2)))), ensure the right-hand page/image is conditionally rendered when
pages.length is odd, and add aria-label="이전 페이지" / aria-label="다음 페이지" to the
arrow buttons for accessibility.

@DongEun02 DongEun02 merged commit 12ed0ac into main Dec 6, 2025
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.

1 participant