fix: QnaWrite 훅/함수 이름 수정, NoticeWrite 사용 오류 수정
This commit is contained in:
parent
86c0adc2cd
commit
5b2a8fdfef
@ -47,4 +47,5 @@
|
|||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
|
79
frontend/src/components/Article/EditArticle/EditArticle.jsx
Normal file
79
frontend/src/components/Article/EditArticle/EditArticle.jsx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import { useState, useEffect, useRef } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import styles from './EditArticle.module.css';
|
||||||
|
import EditIcon from '/src/assets/icons/edit.svg?react';
|
||||||
|
import BackIcon from '/src/assets/icons/back.svg?react';
|
||||||
|
|
||||||
|
export default function EditArticle({ topic, title, prevTitle, prevContent, onSubmit }) {
|
||||||
|
const [articleTitle, setArticleTitle] = useState(prevTitle);
|
||||||
|
const [articleContent, setArticleContent] = useState(prevContent);
|
||||||
|
const textAreaRef = useRef(null);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// adjustTextAreaHeight();
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
adjustTextAreaHeight();
|
||||||
|
}, [articleContent]);
|
||||||
|
|
||||||
|
const adjustTextAreaHeight = () => {
|
||||||
|
if (textAreaRef.current) {
|
||||||
|
textAreaRef.current.style.height = 'auto';
|
||||||
|
textAreaRef.current.style.height = `${textAreaRef.current.scrollHeight}px`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInput = (e) => {
|
||||||
|
setArticleContent(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.createArticle}>
|
||||||
|
<header className={styles.header}>
|
||||||
|
<Link
|
||||||
|
to={'..'}
|
||||||
|
className={styles.goBack}
|
||||||
|
>
|
||||||
|
<BackIcon />
|
||||||
|
<span>{title}</span>
|
||||||
|
</Link>
|
||||||
|
<div className={styles.title}>{topic}</div>
|
||||||
|
</header>
|
||||||
|
<form
|
||||||
|
className={styles.formWrapper}
|
||||||
|
onSubmit={(e) => onSubmit(e, articleTitle, articleContent)}
|
||||||
|
>
|
||||||
|
<div className={styles.fieldWrapper}>
|
||||||
|
<label className={styles.label}>제목</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className={styles.titleInput}
|
||||||
|
placeholder="제목을 입력하세요"
|
||||||
|
value={articleTitle}
|
||||||
|
onChange={(e) => setArticleTitle(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.fieldWrapper}>
|
||||||
|
<label className={styles.label}>내용</label>
|
||||||
|
<textarea
|
||||||
|
ref={textAreaRef}
|
||||||
|
className={styles.contentInput}
|
||||||
|
placeholder="내용을 입력하세요"
|
||||||
|
value={articleContent}
|
||||||
|
onChange={handleInput}
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.button}
|
||||||
|
onClick={(e) => onSubmit(e, articleTitle, articleContent)}
|
||||||
|
disabled={!articleTitle || !articleContent || (articleTitle === prevTitle && articleContent === prevContent)}
|
||||||
|
>
|
||||||
|
<EditIcon />
|
||||||
|
<div>수정하기</div>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
.createArticle {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: start;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goBack {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-weight: 400;
|
||||||
|
color: var(--text-color-secondary);
|
||||||
|
stroke: var(--text-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formWrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fieldWrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titleInput {
|
||||||
|
padding: 20px;
|
||||||
|
background: var(--background);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titleInput::placeholder {
|
||||||
|
color: var(--text-color-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentInput {
|
||||||
|
padding: 20px;
|
||||||
|
height: 80px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
background: var(--background-color);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentInput::placeholder {
|
||||||
|
color: var(--text-color-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border: 1px solid var(--primary-color);
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
color: var(--on-primary);
|
||||||
|
stroke: var(--on-primary);
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-weight: 700;
|
||||||
|
align-self: end;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition:
|
||||||
|
background-color 0.25s,
|
||||||
|
border-color 0.25s,
|
||||||
|
stroke 0.25s,
|
||||||
|
color 0.25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:disabled,
|
||||||
|
.button[disabled] {
|
||||||
|
border-color: var(--border-color);
|
||||||
|
background-color: var(--background-tertiary);
|
||||||
|
color: var(--text-color-tertiary);
|
||||||
|
cursor: not-allowed;
|
||||||
|
stroke: var(--text-color-tertiary);
|
||||||
|
}
|
@ -2,3 +2,4 @@ export { default as ArticleDetail } from './ArticleDetail/ArticleDetail.jsx';
|
|||||||
export { default as ArticleDetailAnswer } from './ArticleDetail/ArticleDetailAnswer/ArticleDetailAnswer.jsx';
|
export { default as ArticleDetailAnswer } from './ArticleDetail/ArticleDetailAnswer/ArticleDetailAnswer.jsx';
|
||||||
export { default as CreateArticle } from './CreateArticle/CreateArticle.jsx';
|
export { default as CreateArticle } from './CreateArticle/CreateArticle.jsx';
|
||||||
export { default as ArticlePreview } from './ArticlePreview/ArticlePreview.jsx';
|
export { default as ArticlePreview } from './ArticlePreview/ArticlePreview.jsx';
|
||||||
|
export { default as EditArticle } from './EditArticle/EditArticle.jsx';
|
||||||
|
16
frontend/src/hooks/api/useQnAWrite.js
Normal file
16
frontend/src/hooks/api/useQnAWrite.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import instance from '../../utils/axios/instance';
|
||||||
|
import { API_URL } from '../../constants';
|
||||||
|
|
||||||
|
export function useQnaWrite() {
|
||||||
|
const qnaWrite = (lectureId, title, content) => {
|
||||||
|
const newQna = {
|
||||||
|
title,
|
||||||
|
content,
|
||||||
|
answer: null,
|
||||||
|
};
|
||||||
|
console.log(newQna);
|
||||||
|
return instance.post(`${API_URL}/qna/${lectureId}`, newQna);
|
||||||
|
};
|
||||||
|
|
||||||
|
return { qnaWrite };
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
import instance from '../../utils/axios/instance';
|
|
||||||
import { API_URL } from '../../constants';
|
|
||||||
|
|
||||||
export function useQnaWrite() {
|
|
||||||
const questionWrite = (lectureId, title, content) => {
|
|
||||||
const newNotice = {
|
|
||||||
title,
|
|
||||||
content,
|
|
||||||
answer: null,
|
|
||||||
};
|
|
||||||
console.log(newNotice);
|
|
||||||
return instance.post(`${API_URL}/qna/${lectureId}`, newNotice);
|
|
||||||
};
|
|
||||||
|
|
||||||
return { questionWrite };
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
import { CreateArticle } from '../../components/Article';
|
import { CreateArticle } from '../../components/Article';
|
||||||
import { useQnaWrite } from '../../hooks/api/useQuestionWrite';
|
import { useQnaWrite } from '../../hooks/api/useQnAWrite';
|
||||||
import { useParams, useNavigate } from 'react-router-dom';
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
export default function CreateQuestionPage() {
|
export default function CreateQuestionPage() {
|
||||||
|
@ -7,6 +7,7 @@ export default function NoticeDetailPage() {
|
|||||||
const noticeId = params.noticeId;
|
const noticeId = params.noticeId;
|
||||||
const { data } = useNoticeDetail(noticeId);
|
const { data } = useNoticeDetail(noticeId);
|
||||||
const notice = data?.data;
|
const notice = data?.data;
|
||||||
|
// TODO: 수정 버튼 추가(여기에 또는 ArticleDetail에)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ArticleDetail
|
<ArticleDetail
|
||||||
|
@ -13,7 +13,7 @@ export default function NoticeListPage() {
|
|||||||
title="공지사항"
|
title="공지사항"
|
||||||
canCreate={false}
|
canCreate={false}
|
||||||
>
|
>
|
||||||
{notices?.map?.((notice) => (
|
{notices?.map((notice) => (
|
||||||
<ArticleLink
|
<ArticleLink
|
||||||
key={`${notice.id}`}
|
key={`${notice.id}`}
|
||||||
title={notice.title}
|
title={notice.title}
|
||||||
|
@ -10,13 +10,8 @@ export default function NoticeWritePage() {
|
|||||||
|
|
||||||
const handleSubmit = async (e, title, content) => {
|
const handleSubmit = async (e, title, content) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
console.log(lectureId, content, title);
|
||||||
await noticeWrite({
|
await noticeWrite(lectureId, title, content);
|
||||||
lectureId: Number(lectureId),
|
|
||||||
title,
|
|
||||||
category: 'announcement',
|
|
||||||
content,
|
|
||||||
});
|
|
||||||
|
|
||||||
navigate('..');
|
navigate('..');
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user