Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions frontend/src/pages/curriculum/CurriculumPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function MemberSessionCard({ day }) {
</div>
<img src={Toggle1} className={`${styles.toggleIcon} ${isOpen ? styles.toggleOpen : ''}`} alt="toggle" />
</div>
<hr className={styles.divider}/>
<hr className={styles.divider} />

{isOpen && (
<div className={styles.cardBody}>
Expand Down Expand Up @@ -110,7 +110,7 @@ function AdminSessionCard({ day, onEdit, onDelete }) {
</div>
<img src={Toggle1} className={`${styles.toggleIcon} ${isOpen ? styles.toggleOpen : ''}`} alt="toggle" />
</div>
<hr className={styles.divider} />
<hr className={styles.divider} />

{isOpen && (
<div className={styles.cardBody}>
Expand Down Expand Up @@ -168,7 +168,7 @@ function SessionForm({ day, week, onClose, onSave }) {
const date = new Date(year, month - 1, day);
const map = { 0: '일요일', 1: '월요일', 2: '화요일', 3: '수요일', 4: '목요일', 5: '금요일', 6: '토요일' };
return map[date.getDay()] || '';
};
};

const handleSave = async () => {
const newErrors = {};
Expand Down Expand Up @@ -233,6 +233,7 @@ function SessionForm({ day, week, onClose, onSave }) {
return (
<div className={styles.formOverlay}>
<div className={styles.formCard}>

<div className={styles.formSection}>
<label className={styles.formLabel}>주차</label>
<select className={styles.formInput} value={form.week}
Expand All @@ -256,6 +257,7 @@ function SessionForm({ day, week, onClose, onSave }) {
</div>
</div>


{/* 오전 세션 */}
<div className={styles.formSectionTitle}>
<img src={AmImg} className={styles.sessionIcon} alt="AM" />
Expand Down Expand Up @@ -305,8 +307,8 @@ function SessionForm({ day, week, onClose, onSave }) {
{/* 과제 */}
<div className={styles.assignmentSection}>
<span className={styles.assignmentLabel}>과제</span>
<div><label className={styles.formLabel}>과제 제목</label><input className={styles.formInput} style={{width:'100%'}} value={form.assignmentName} onChange={e => setForm({ ...form, assignmentName: e.target.value })} /></div>
<div><label className={styles.formLabel}>과제 링크</label><input className={styles.formInput} style={{width:'100%'}} value={form.assignmentUrl} onChange={e => setForm({ ...form, assignmentUrl: e.target.value })} /></div>
<div><label className={styles.formLabel}>과제 제목</label><input className={styles.formInput} style={{ width: '100%' }} value={form.assignmentName} onChange={e => setForm({ ...form, assignmentName: e.target.value })} /></div>
<div><label className={styles.formLabel}>과제 링크</label><input className={styles.formInput} style={{ width: '100%' }} value={form.assignmentUrl} onChange={e => setForm({ ...form, assignmentUrl: e.target.value })} /></div>
</div>

<button className={styles.saveFormBtn} onClick={handleSave}>저장하기</button>
Expand All @@ -330,7 +332,7 @@ function CurriculumPage() {
const res = await authFetch('/api/curriculums');
const data = await res.json();
setDays(Array.isArray(data) ? data : []);
} catch (e) {}
} catch (e) { }
};

useEffect(() => { fetchDays(); }, []);
Expand Down Expand Up @@ -364,7 +366,7 @@ function CurriculumPage() {
세션 생성
</button>
</div>
)}
)}
{Object.entries(grouped).map(([week, weekDays]) => (
<div key={week} className={styles.weekSection}>
<div className={styles.weekHeader}>
Expand All @@ -387,8 +389,8 @@ function CurriculumPage() {
))}

{showForm && (
<SessionForm

<SessionForm
day={editDay}
week={createWeek}
onClose={() => { setShowForm(false); setEditDay(null); setCreateWeek(null); }}
Expand Down
17 changes: 16 additions & 1 deletion frontend/src/pages/qna/QnADetailPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import '../../assets/styles/global.css';
import { useState, useEffect, useRef, useCallback } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import styles from './QnADetailPage.module.css';
import { FiMoreVertical, FiCornerDownRight } from 'react-icons/fi';
import { FiMoreVertical, FiCornerDownRight, FiChevronLeft } from 'react-icons/fi';
import {
CommentImoji,
MeCuriousToo,
Expand Down Expand Up @@ -97,6 +97,7 @@ function QnADetailPage() {
const [editingCommentId, setEditingCommentId] = useState(null);
const [editCommentText, setEditCommentText] = useState('');


const fetchQuestion = useCallback(async ({ showLoading = false } = {}) => {
try {
if (showLoading) {
Expand Down Expand Up @@ -194,6 +195,11 @@ function QnADetailPage() {
return () => document.removeEventListener('click', handleClickOutside);
}, [showMenu, commentMenuId]);

// ── 목록으로 가기 ────────────────────────────────
const handleBackToList = () => {
navigate(`/sessions/${sessionId}/questions/`);
};

// ── 좋아요 토글 ──────────────────────────────────
const toggleLike = async () => {
try {
Expand Down Expand Up @@ -458,6 +464,15 @@ function QnADetailPage() {
return (
<div className={styles.page}>

{/* ── 목록으로 가기 ── */}
<button
className={styles.backToListBtn}
onClick={handleBackToList}
>
<FiChevronLeft size={18} />
목록으로
</button>

{/* ── 작성자 행 ── */}
<div className={styles.authorRow}>
<div className={styles.avatar}>
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/pages/qna/QnADetailPage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,32 @@
box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 0.25);
}

/* ── 목록으로 가기 ── */
.backToListBtn {
display: flex;
align-items: center;
gap: 4px;
background: none;
border: none;
cursor: pointer;
font-family: var(--font-main);
font-size: 14px;
font-weight: 500;
color: var(--gray600);
padding: 0;
margin: 0 0 18px;
align-self: flex-start;
transition: color 0.15s;
}

.backToListBtn:hover {
color: var(--black);
}

.backToListBtn svg {
flex-shrink: 0;
}

/* ── 작성자 행 ── */
.authorRow {
display: flex;
Expand Down Expand Up @@ -587,6 +613,12 @@
border-radius: 16px 16px 0 0;
}

/* ── 목록으로 가기 ── */
.backToListBtn {
font-size: 13px;
margin-bottom: 14px;
}

/* ── 질문 본문 ── */
.qIcon {
font-size: 28px;
Expand Down
68 changes: 35 additions & 33 deletions frontend/src/pages/qna/QnAListPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -733,40 +733,42 @@ function QnAListPage() {
</div>
<hr className={styles.divider} />

{/* ── 이해도 바 ── */}
<div className={styles.understandBar}>
<button className={styles.arrowBtn} onClick={goPrevUnderstand}
disabled={!understanding?.hasOlder}>
<FiChevronLeft size={30} />
</button>
<span className={styles.understandName}>
{understanding?.current?.content ?? '이해도 없음'}
<span className={styles.understandCount}>
({understanding?.current?.respondedCount ?? 0}/
{understanding?.current?.attendanceCount ?? 0})
{/* ── 이해도 바 (이해도 체크가 없으면 숨김) ── */}
{understanding?.current?.checkId != null && (
<div className={styles.understandBar}>
<button className={styles.arrowBtn} onClick={goPrevUnderstand}
disabled={!understanding?.hasOlder}>
<FiChevronLeft size={30} />
</button>
<span className={styles.understandName}>
{understanding.current.content}
<span className={styles.understandCount}>
({understanding.current.respondedCount ?? 0}/
{understanding.current.attendanceCount ?? 0})
</span>
</span>
</span>
<button
className={`${styles.oxBtn} ${styles.oxO} ${currentChoice === 'UNDERSTOOD' ? styles.oxActive : ''}`}
onClick={() => handleUnderstandChoice('UNDERSTOOD')}
disabled={isStaff || isPast}
>
<OBtn />
{isStaff && <span className={styles.oxCount}>{understanding?.current?.understoodCount ?? 0}</span>}
</button>
<button
className={`${styles.oxBtn} ${styles.oxX} ${currentChoice === 'NOT_UNDERSTOOD' ? styles.oxActive : ''}`}
onClick={() => handleUnderstandChoice('NOT_UNDERSTOOD')}
disabled={isStaff || isPast}
>
<XBtn />
{isStaff && <span className={styles.oxCount}>{understanding?.current?.notUnderstoodCount ?? 0}</span>}
</button>
<button className={styles.arrowBtn} onClick={goNextUnderstand}
disabled={!understanding?.hasNewer}>
<FiChevronRight size={30} />
</button>
</div>
<button
className={`${styles.oxBtn} ${styles.oxO} ${currentChoice === 'UNDERSTOOD' ? styles.oxActive : ''}`}
onClick={() => handleUnderstandChoice('UNDERSTOOD')}
disabled={isStaff || isPast}
>
<OBtn />
{isStaff && <span className={styles.oxCount}>{understanding.current.understoodCount ?? 0}</span>}
</button>
<button
className={`${styles.oxBtn} ${styles.oxX} ${currentChoice === 'NOT_UNDERSTOOD' ? styles.oxActive : ''}`}
onClick={() => handleUnderstandChoice('NOT_UNDERSTOOD')}
disabled={isStaff || isPast}
>
<XBtn />
{isStaff && <span className={styles.oxCount}>{understanding.current.notUnderstoodCount ?? 0}</span>}
</button>
<button className={styles.arrowBtn} onClick={goNextUnderstand}
disabled={!understanding?.hasNewer}>
<FiChevronRight size={30} />
</button>
</div>
)}

{/* ── 질문 목록 ── */}
<div className={styles.questionList}>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/qna/QnAMainPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function QNAMainPage() {
// ── 세션 목록 불러오기 ──────────────────────────
useEffect(() => {
document.title = "Q&A | PIROIN";

const fetchSessions = async () => {
try {
setLoading(true);
Expand Down Expand Up @@ -50,7 +50,7 @@ function QNAMainPage() {
{activeSessions.length > 0 && (
<>
<section className={styles.section}>
<h2 className={styles.sectionTitle}>Q&A</h2>
<h2 className={styles.sectionTitle}>현재 세션</h2>
{activeSessions.map(session => (
<div
key={session.sessionId}
Expand Down
Loading