From 4a7e75f92d4e7a273f840c3901bce9d93214b3fa Mon Sep 17 00:00:00 2001 From: AWESOMEDEV Date: Thu, 23 Jul 2026 13:23:13 +0900 Subject: [PATCH] =?UTF-8?q?feat(assignments):=20=EC=A3=BC=EC=B0=A8?= =?UTF-8?q?=EB=B3=84=20=EA=B3=BC=EC=A0=9C=20=E2=86=92=20=ED=95=99=EC=8A=B5?= =?UTF-8?q?=20=EB=AC=B8=EC=84=9C(=EA=B3=BC=EC=A0=9C=EC=A7=91)=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=20=EA=B3=A0=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 과제 페이지에 '이 주차 학습 문서' 링크를 붙였다. 학생이 과제만 보고 '뭘 보고 하나' 헷갈리던 문제 해결. 주차별 과제집(week1~4-assignments)이 있는 주차에만 뜨고, 없는 주차(5~8)엔 안 뜬다. --- frontend/src/pages/AssignmentsPage.jsx | 25 +++++++++++++++++++ frontend/src/styles/global.css | 33 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/frontend/src/pages/AssignmentsPage.jsx b/frontend/src/pages/AssignmentsPage.jsx index c63c561..f5de2b4 100644 --- a/frontend/src/pages/AssignmentsPage.jsx +++ b/frontend/src/pages/AssignmentsPage.jsx @@ -1,6 +1,7 @@ // 이 파일이 하는 일: 주차별 과제 목록을 요일(일차)별로 묶어 보여주고, 각 과제에 대해 // 제출 폼(내용 + 링크)과 내 제출 상태·멘토 피드백을 표시한다. import { useEffect, useState } from 'react'; +import { Link } from 'react-router-dom'; import client from '../api/client'; import Badge from '../components/Badge'; @@ -119,6 +120,7 @@ export default function AssignmentsPage() { const [week, setWeek] = useState(1); const [assignments, setAssignments] = useState([]); const [mySubmissions, setMySubmissions] = useState([]); + const [docs, setDocs] = useState([]); const [loading, setLoading] = useState(true); // 내 제출 목록만 다시 불러오는 함수 — 제출 직후에도 호출한다. @@ -146,6 +148,12 @@ export default function AssignmentsPage() { }; }, [week]); + // 학습 문서 목록(주차별 과제집 등)을 한 번 불러온다 — 과제 화면에서 관련 문서로 바로 잇기 위해. + // API는 학생에게 볼 수 있는 문서만 준다(멘토 전용 강의안은 안 옴). + useEffect(() => { + client.get('/documents').then((res) => setDocs(res.data)).catch(() => {}); + }, []); + // 학습 포인트: 과제 목록과 내 제출 목록은 별도 API다. // assignmentId로 짝을 맞춰(매칭) 과제 카드에 제출 상태를 얹는다. function findSubmission(assignmentId) { @@ -157,6 +165,9 @@ export default function AssignmentsPage() { const percent = assignments.length === 0 ? 0 : Math.round((submittedCount / assignments.length) * 100); + // 이 주차에 해당하는 학습 문서(주차별 과제집). 학생이 과제 전에 배경을 읽도록 연결한다. + const weekDocs = docs.filter((d) => d.week === week); + // 요일(일차)별로 묶는다 — 대시보드와 같은 방식이라 화면 리듬이 익숙해진다. const groups = new Map(); for (const assignment of assignments) { @@ -199,6 +210,20 @@ export default function AssignmentsPage() { ))} + {/* 이 주차 학습 문서로 가는 고리 — "과제만 있고 뭘 보고 하는지 모르겠다"를 없앤다. + 주차별 과제집이 있는 1~4주차엔 링크가, 없는 주차(5~8)엔 안 뜬다. */} + {weekDocs.length > 0 && ( +
+ {weekDocs.map((d) => ( + + 📚 학습 문서 + {d.title} + 과제 전에 먼저 읽어 보세요 → + + ))} +
+ )} + {loading ? (

불러오는 중...

) : assignments.length === 0 ? ( diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 19d0828..8466e39 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -1588,3 +1588,36 @@ inline-code, .icode { align-items: center; } .helper-send:disabled { opacity: 0.5; cursor: default; } + +/* ── 과제 → 학습 문서 연결 고리 ──────────────────────────────────── */ +.assignment-doc-links { margin: 14px 0; } +.assignment-doc-link { + display: flex; + align-items: center; + gap: 12px; + flex-wrap: wrap; + text-decoration: none; + color: var(--ink); + word-break: keep-all; /* 한글 단어 중간 줄바꿈 금지 */ + transition: border-color 0.15s, box-shadow 0.15s; +} +.assignment-doc-link + .assignment-doc-link { margin-top: 10px; } +.assignment-doc-link:hover { + border-color: var(--primary); + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06); +} +.assignment-doc-badge { + flex: none; + font-weight: 700; + color: var(--primary); +} +.assignment-doc-title { font-weight: 600; } +.assignment-doc-cta { + margin-left: auto; + color: var(--muted); + font-size: 13px; + white-space: nowrap; +} +@media (max-width: 520px) { + .assignment-doc-cta { margin-left: 0; } /* 좁은 화면에선 CTA를 다음 줄로 */ +}