diff --git a/frontend/src/App.js b/frontend/src/App.js
index a6b7474..7c37e68 100644
--- a/frontend/src/App.js
+++ b/frontend/src/App.js
@@ -4,7 +4,7 @@ import LoginPage from './pages/login/LoginPage';
import OnboardingPage from './pages/OnboardingPage';
import QnAMainPage from './pages/qna/QnAMainPage';
import QnAListPage from './pages/qna/QnAListPage';
-import QnADetailePage from './pages/qna/QnADetailePage';
+import QnADetailPage from './pages/qna/QnADetailPage';
import CurriculumPage from './pages/curriculum/CurriculumPage';
import PiroCheckMain from './pages/pirocheck/PIroCheckMain';
import Attendance from './pages/pirocheck/attendance/Attendance'
@@ -23,14 +23,14 @@ function App() {
}>
} />
} />
- } />
+ } />
} />
-
+
{/* 다크 헤더 페이지 */}
}>
- }/>
- }/>
+ } />
+ } />
diff --git a/frontend/src/assets/images/profile.png b/frontend/src/assets/images/profile.png
new file mode 100644
index 0000000..0ac7d4c
Binary files /dev/null and b/frontend/src/assets/images/profile.png differ
diff --git a/frontend/src/assets/styles/global.css b/frontend/src/assets/styles/global.css
index 24d9dbe..667173f 100644
--- a/frontend/src/assets/styles/global.css
+++ b/frontend/src/assets/styles/global.css
@@ -24,9 +24,4 @@
--black: #111111;
--font-title: 'GemunuLibre', sans-serif;
--font-main: 'Pretendard', sans-serif;
-}
-
-/* body 기본 설정 */
-body {
- background-color: var(--gray20);
}
\ No newline at end of file
diff --git a/frontend/src/components/Layout.js b/frontend/src/components/Layout.js
index e0a4bee..7961f7a 100644
--- a/frontend/src/components/Layout.js
+++ b/frontend/src/components/Layout.js
@@ -3,7 +3,7 @@ import { Outlet } from 'react-router-dom';
function Layout({ headerType }) {
return (
-
+
diff --git a/frontend/src/pages/qna/QnADetailPage.js b/frontend/src/pages/qna/QnADetailPage.js
new file mode 100644
index 0000000..f617a2b
--- /dev/null
+++ b/frontend/src/pages/qna/QnADetailPage.js
@@ -0,0 +1,245 @@
+import '../../assets/styles/global.css';
+import { useState } from 'react';
+import styles from './QnADetailPage.module.css';
+import { FiChevronLeft, FiMoreVertical, FiCornerDownRight } from 'react-icons/fi';
+import {
+ CommentImoji,
+ MeCuriousToo,
+ StaffCheck,
+ SumitBtn,
+} from '../../components/qna_svg';
+import profileImg from '../../assets/images/profile.png';
+
+
+
+// ── 목업 데이터 ──────────────────────────────────────────
+const MOCK_QUESTION = {
+ id: 2,
+ author: '익명',
+ isStaff: false,
+ avatarUrl: null,
+ date: '2025/04/25 13:20',
+ text: '오류 났어요',
+ image: 'https://dora-guide.com/wp-content/uploads/2019/11/Visual-studio-code-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95.png',
+ likes: 7,
+ iLiked: false,
+ isSolved: true,
+ comments: [
+ {
+ id: 1,
+ author: '운영진1',
+ isStaff: true,
+ avatarUrl: null,
+ date: '2025/04/25 13:28',
+ content: '사진 참고하세요',
+ image: 'https://dora-guide.com/wp-content/uploads/2019/11/Visual-studio-code-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95.png',
+ },
+ {
+ id: 2,
+ author: '작성자',
+ isStaff: false,
+ avatarUrl: null,
+ date: '2025/04/25 13:28',
+ content: '감사합니다',
+ image: null,
+ },
+ {
+ id: 3,
+ author: '익명1',
+ isStaff: false,
+ avatarUrl: null,
+ date: '2025/04/25 13:28',
+ content: '감사합니다',
+ image: null,
+ },
+ ],
+};
+
+
+// ── 메인 컴포넌트 ────────────────────────────────────────
+function QnADetailPage({
+ question: initialQuestion = MOCK_QUESTION,
+ isStaff = false,
+ onBack,
+}) {
+ const [question, setQuestion] = useState(initialQuestion);
+ const [commentText, setCommentText] = useState('');
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ // 좋아요 토글
+ const toggleLike = () => {
+ setQuestion(prev => ({
+ ...prev,
+ iLiked: !prev.iLiked,
+ likes: prev.iLiked ? prev.likes - 1 : prev.likes + 1,
+ }));
+ };
+
+ // 댓글 제출
+ const handleCommentSubmit = async () => {
+ const text = commentText.trim();
+ if (!text) return;
+
+ setIsSubmitting(true);
+ try {
+ const newComment = {
+ id: Date.now(),
+ author: isStaff ? '운영진' : '나',
+ isStaff,
+ avatarUrl: null,
+ date: new Date().toLocaleDateString('ko-KR', {
+ year: 'numeric',
+ month: '2-digit',
+ day: '2-digit',
+ hour: '2-digit',
+ minute: '2-digit',
+ }).replace(/\. /g, '/').replace('.', ''),
+ content: text,
+ image: null,
+ };
+ setQuestion(prev => ({
+ ...prev,
+ comments: [...prev.comments, newComment],
+ }));
+ setCommentText('');
+ } catch (err) {
+ console.error('댓글 등록 실패:', err);
+ } finally {
+ setIsSubmitting(false);
+ }
+ };
+
+ return (
+
+
+ {/* ── 상단 바:해결 여부 ── */}
+
+ {question.isSolved ? (
+ 해결 질문
+ ) : (
+ 미해결 질문
+ )}
+
+
+ {/* ── 작성자 행 ── */}
+
+
+

+
+
+
+ {question.author}
+ {question.isStaff && (
+
+ )}
+
+ {question.date}
+
+
+
+
+ {/* ── 질문 제목 ── */}
+
+ Q.
+ {question.text}
+
+
+ {/* ── 첨부 이미지 ── */}
+ {question.image && (
+

+ )}
+
+ {/* ── 액션 버튼 (저도 궁금해요 / 댓글달기) ── */}
+
+
+
+
+
+
+
+ {/* ── 댓글 목록 ── */}
+
+ {question.comments.map(comment => (
+
+
+ {/* 댓글 작성자 */}
+
+
+

+
+
+ {comment.author}
+ {comment.isStaff && (
+
+ )}
+
+
+
+ {/* 댓글 말풍선 */}
+
+
+
+ {comment.content}
+
+ {comment.image && (
+

+ )}
+
+
+ {/* 타임스탬프 */}
+
{comment.date}
+
+ ))}
+
+
+ {/* ── 하단 그라디언트 커버 ── */}
+
+
+ {/* ── 댓글 입력 바 (하단 고정) ── */}
+
+ setCommentText(e.target.value)}
+ onKeyDown={e => {
+ if (e.key === 'Enter') handleCommentSubmit();
+ }}
+ disabled={isSubmitting}
+ />
+
+
+
+
+ );
+}
+
+export default QnADetailPage;
\ No newline at end of file
diff --git a/frontend/src/pages/qna/QnADetailPage.module.css b/frontend/src/pages/qna/QnADetailPage.module.css
new file mode 100644
index 0000000..1f24ed2
--- /dev/null
+++ b/frontend/src/pages/qna/QnADetailPage.module.css
@@ -0,0 +1,356 @@
+/* ── 전체 페이지 ── */
+.page {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ max-width: 900px;
+ margin: 70px auto 0;
+ padding: 52px 90px 120px;
+ box-sizing: border-box;
+ background: var(--white);
+ border-radius: 40px 40px 0 0;
+ box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 0.25);
+}
+
+/* ── 상단 헤더 (해결 여부 뱃지) ── */
+.topBar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px 0 10px;
+}
+
+.solvedBadge {
+ font-family: var(--font-main);
+ font-size: 0.78rem;
+ font-weight: 600;
+ color: var(--black);
+ background: var(--gray20);
+ border-radius: 20px;
+ padding: 3px 10px;
+ letter-spacing: 0.01em;
+}
+
+.unsolvedBadge {
+ font-family: var(--font-main);
+ font-size: 0.78rem;
+ font-weight: 600;
+ color: var(--black);
+ background: var(--light);
+ border-radius: 20px;
+ padding: 3px 10px;
+}
+
+/* ── 작성자 행 ── */
+.authorRow {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 16px;
+}
+
+.avatar {
+ width: 35px;
+ height: 35px;
+ background: none;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ overflow: hidden;
+}
+
+.avatarImg {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.authorInfo {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ flex: 1;
+}
+
+.authorName {
+ font-family: var(--font-main);
+ font-size: 0.95rem;
+ font-weight: 600;
+ color: var(--black);
+ display: flex;
+ align-items: center;
+ gap: 4px;
+}
+
+.authorDate {
+ font-family: var(--font-main);
+ font-size: 0.75rem;
+ color: var(--gray200);
+}
+
+.menuBtn {
+ background: none;
+ border: none;
+ cursor: pointer;
+ color: var(--gray600);
+ padding: 4px;
+ display: flex;
+ align-items: center;
+}
+
+/* ── 질문 본문 ── */
+.questionTitle {
+ display: flex;
+ align-items: flex-start;
+ gap: 6px;
+ margin-bottom: 18px;
+}
+
+.qIcon {
+ font-family: var(--font-main);
+ font-size: 2rem;
+ font-weight: 900;
+ color: var(--main);
+ line-height: 1.1;
+ flex-shrink: 0;
+}
+
+.questionText {
+ font-family: var(--font-main);
+ font-size: 24px;
+ font-weight: 600;
+ color: var(--black);
+ line-height: 1.3;
+ word-break: keep-all;
+ padding-top: 4px;
+}
+
+/* ── 첨부 이미지 ── */
+.questionImage {
+ width: 100%;
+ border-radius: 12px;
+ object-fit: cover;
+ display: block;
+ margin-bottom: 18px;
+}
+
+/* ── 액션 버튼 행 ── */
+.actionRow {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 10px;
+ margin-bottom: 10px;
+}
+
+.likeBtn {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ border: none;
+ cursor: pointer;
+ font-family: var(--font-main);
+ font-size: 0.85rem;
+ color: var(--gray600);
+ padding: 4px 10px 4px 8px;
+ background: var(--gray50);
+ border-radius: 10px;
+ transition: color 0.15s, background 0.15s;
+ height: 28px;
+}
+
+.likeBtn.liked {
+ color: var(--dark);
+ background: var(--light);
+}
+
+.commentBtn {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ border: none;
+ cursor: pointer;
+ font-family: var(--font-main);
+ font-size: 0.85rem;
+ color: var(--gray600);
+ padding: 4px 10px;
+ background: var(--gray50);
+ border-radius: 10px;
+ height: 28px;
+ white-space: nowrap;
+}
+
+/* ── 구분선 ── */
+.divider {
+ background: var(--gray200);
+ width: 100%;
+ height: 1px;
+ border: none;
+ margin: 4px 0 0;
+}
+
+/* ── 댓글 목록 ── */
+.commentList {
+ display: flex;
+ flex-direction: column;
+ gap: 0;
+ padding-top: 4px;
+}
+
+.commentBlock {
+ padding: 16px 0;
+}
+
+/* 댓글 작성자 행 */
+.commentAuthorRow {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 10px;
+}
+
+.commentAvatar {
+ width: 35px;
+ height: 35px;
+ background: none;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ overflow: hidden;
+}
+
+.commentAvatarImg {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.commentAuthorName {
+ font-family: var(--font-main);
+ font-size: 0.9rem;
+ font-weight: 600;
+ color: var(--black);
+ display: flex;
+ align-items: center;
+ gap: 4px;
+}
+
+/* ── 댓글 말풍선 ── */
+.commentBubble {
+ margin-left: 42px;
+ background: var(--gray50);
+ border-radius: 5px 20px 20px 20px;
+ padding: 10px 14px;
+ display: inline-flex;
+ flex-direction: column;
+ gap: 10px;
+ max-width: calc(100% - 42px);
+ box-sizing: border-box;
+}
+
+.commentContent {
+ font-family: var(--font-main);
+ font-size: 0.9rem;
+ color: var(--black);
+ font-weight: 400;
+ line-height: 1.5;
+ display: flex;
+ align-items: flex-start;
+ gap: 6px;
+}
+
+.commentArrow {
+ flex-shrink: 0;
+ color: var(--gray600);
+ margin-top: 2px;
+}
+
+.commentImage {
+ width: 100%;
+ max-width: 380px;
+ border-radius: 8px;
+ object-fit: cover;
+ display: block;
+}
+
+/* 댓글 타임스탬프 */
+.commentDate {
+ margin-left: 42px;
+ font-family: var(--font-main);
+ font-size: 0.72rem;
+ color: var(--gray200);
+ margin-top: 6px;
+}
+
+/* ── 댓글 입력 바 (하단 고정) ── */
+.bottomCover {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 80px;
+ background: linear-gradient(to bottom, transparent, var(--white) 60%);
+ z-index: 99;
+ pointer-events: none;
+}
+
+.commentInputBar {
+ position: fixed;
+ bottom: 20px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: min(740px, 100vw - 32px);
+ height: 56px;
+ border-radius: 30px;
+ background: var(--white);
+ box-shadow: 1px 2px 10px 0 rgba(0, 0, 0, 0.25);
+ display: flex;
+ align-items: center;
+ padding: 0 12px;
+ box-sizing: border-box;
+ z-index: 100;
+ gap: 8px;
+}
+
+.commentInput {
+ flex: 1;
+ border: none;
+ background: none;
+ font-family: var(--font-main);
+ font-size: 1rem;
+ color: var(--black);
+ outline: none;
+ height: 100%;
+}
+
+.commentInput::placeholder {
+ color: var(--gray200);
+}
+
+.submitBtn {
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ background: #09C410;
+ border: none;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ padding: 0;
+ transition: opacity 0.15s;
+}
+
+.submitBtn:disabled {
+ background: var(--gray200);
+ cursor: default;
+}
+
+/* ── 스태프 뱃지 ── */
+.staffBadge {
+ display: inline-flex;
+ align-items: center;
+}
\ No newline at end of file
diff --git a/frontend/src/pages/qna/QnADetailePage.js b/frontend/src/pages/qna/QnADetailePage.js
deleted file mode 100644
index e69de29..0000000
diff --git a/frontend/src/pages/qna/QnADetailePage.module.css b/frontend/src/pages/qna/QnADetailePage.module.css
deleted file mode 100644
index e69de29..0000000
diff --git a/frontend/src/pages/qna/QnAMainPage.js b/frontend/src/pages/qna/QnAMainPage.js
index f875ffc..d01df87 100644
--- a/frontend/src/pages/qna/QnAMainPage.js
+++ b/frontend/src/pages/qna/QnAMainPage.js
@@ -15,6 +15,7 @@ const pastSessions = [ // css 보려고 걍 적어둠
];
function QNAMainPage() {
+
return (