diff --git a/frontend/src/Router.jsx b/frontend/src/Router.jsx index 39e36df9..8868ec10 100644 --- a/frontend/src/Router.jsx +++ b/frontend/src/Router.jsx @@ -24,6 +24,7 @@ const PasswordResetPage = lazy(async () => await import('./pages/PasswordResetPa const MyInfoChangePage = lazy(async () => await import('./pages/MyInfoChangePage')); const PasswordChangePage = lazy(async () => await import('./pages/PasswordChangePage')); const LearningLecturesPage = lazy(async () => await import('./pages/LearningLecturesPage')); +const LectureCreatePage = lazy(async () => await import('./pages/LectureCreatePage')); const router = createBrowserRouter([ { @@ -45,6 +46,10 @@ const router = createBrowserRouter([ index: true, element: , }, + { + path: 'lecture/create', + element: , + }, { path: 'lecture/:lectureId/info', element: , diff --git a/frontend/src/components/Layout/LectureLayout.jsx b/frontend/src/components/Layout/LectureLayout.jsx index b95a5d02..fd1515b7 100644 --- a/frontend/src/components/Layout/LectureLayout.jsx +++ b/frontend/src/components/Layout/LectureLayout.jsx @@ -10,7 +10,7 @@ export default function LectureLayout() { const { lectureId } = useParams(); const { data } = useLectureInfo(lectureId); const lecture = data?.data; - + console.log(lecture); const userType = useBoundStore((state) => state.userType); return ( @@ -18,6 +18,7 @@ export default function LectureLayout() { diff --git a/frontend/src/hooks/api/useLectureCreate.js b/frontend/src/hooks/api/useLectureCreate.js new file mode 100644 index 00000000..d7d7359f --- /dev/null +++ b/frontend/src/hooks/api/useLectureCreate.js @@ -0,0 +1,15 @@ +import instance from '../../utils/axios/instance'; +import { API_URL } from '../../constants'; + +export function useLectureCreate() { + const lectureCreate = (formData) => { + // return instance.post(`${API_URL}/lecture`, lectureObject, image); + return instance.post(`${API_URL}/lecture`, formData, { + headers: { + 'Content-type': 'multipart/form-data', + }, + }); + }; + + return { lectureCreate }; +} diff --git a/frontend/src/hooks/api/usePasswordChange.js b/frontend/src/hooks/api/usePasswordChange.js new file mode 100644 index 00000000..7c1772bb --- /dev/null +++ b/frontend/src/hooks/api/usePasswordChange.js @@ -0,0 +1,16 @@ +import instance from '../../utils/axios/instance'; +import { API_URL } from '../../constants'; + +export function usePasswordChange() { + // TODO: API 수정 후 실제 기능하는지 확인 + const passwordChange = (currentPw, newPw, newPwCheck) => { + const newPasswordBody = { + currentPassword: currentPw, + newPassword: newPw, + newPasswordCheck: newPwCheck, + }; + return instance.put(`${API_URL}/user/updatepassword/`, newPasswordBody); + }; + + return { passwordChange }; +} diff --git a/frontend/src/pages/CreateQuestionPage/CreateQuestionPage.jsx b/frontend/src/pages/CreateQuestionPage/CreateQuestionPage.jsx index 380e92ae..afcf686d 100644 --- a/frontend/src/pages/CreateQuestionPage/CreateQuestionPage.jsx +++ b/frontend/src/pages/CreateQuestionPage/CreateQuestionPage.jsx @@ -5,12 +5,12 @@ import { useParams, useNavigate } from 'react-router-dom'; export default function CreateQuestionPage() { const navigate = useNavigate(); const { lectureId } = useParams(); - const { questionWrite } = useQnaWrite(); + const { qnaWrite } = useQnaWrite(); const handleSubmit = async (e, title, content) => { e.preventDefault(); - await questionWrite(lectureId, title, content); + await qnaWrite(lectureId, title, content); navigate('..'); }; return ( diff --git a/frontend/src/pages/LectureCreatePage/LectureCreatePage.jsx b/frontend/src/pages/LectureCreatePage/LectureCreatePage.jsx new file mode 100644 index 00000000..40b9e766 --- /dev/null +++ b/frontend/src/pages/LectureCreatePage/LectureCreatePage.jsx @@ -0,0 +1,111 @@ +import styles from './LectureCreatePage.module.css'; +import { useRef } from 'react'; +import { useLectureCreate } from '../../hooks/api/useLectureCreate'; + +export default function LectureCreatePage() { + // TODO: 디자인 필요 + const titleRef = useRef(''); + const descriptionRef = useRef(''); + const planRef = useRef(''); + const startDateRef = useRef(''); + const endDateRef = useRef(''); + const timeRef = useRef(null); + const imageFileRef = useRef(''); + + const { lectureCreate } = useLectureCreate(); + + const handleSubmit = async (e) => { + e.preventDefault(); + + const lectureObject = { + title: titleRef.current.value, + description: descriptionRef.current.value, + plan: planRef.current.value, + startDate: new Date(startDateRef.current.value).toISOString(), + endDate: new Date(endDateRef.current.value).toISOString(), + time: timeRef.current.value, + }; + + const formData = new FormData(); + + formData.append('lectureCreateRequest', new Blob([JSON.stringify(lectureObject)], { type: 'application/json' })); + + const imageFile = imageFileRef.current.files[0] ?? null; + if (imageFile) { + formData.append('image', imageFile); + } + + const response = await lectureCreate(formData); + console.log(response?.data); + }; + + return ( +
+
+ + +
+
+ + +
+
+ + +
+
+ + + +
+
+ + +
+
+ + +
+ +
+ ); +} diff --git a/frontend/src/pages/LectureCreatePage/LectureCreatePage.module.css b/frontend/src/pages/LectureCreatePage/LectureCreatePage.module.css new file mode 100644 index 00000000..06e7ce0f --- /dev/null +++ b/frontend/src/pages/LectureCreatePage/LectureCreatePage.module.css @@ -0,0 +1,69 @@ +.createClass { + background: var(--background-color); + width: 100%; + max-width: 900px; + margin: 0 auto; + display: flex; + flex-direction: column; + gap: 40px; +} + +.inputField { + display: flex; + flex-direction: column; + gap: 8px; +} + +.label { + color: var(--text-color); + font-size: 16px; + font-weight: 400; + line-height: 1.4; +} + +.input { + background: var(--background-color); + padding: 20px; + border: 1px solid var(--border-color); + border-radius: 8px; + font-size: 20px; + line-height: 1.2; + font-weight: 400; +} + +.input::placeholder { + color: var(--text-color-tertiary); +} + +.textarea { + padding: 20px; + height: 80px; + background: var(--background-color); + border: 1px solid var(--border-color); + border-radius: 8px; + font-size: 16px; + line-height: 1.4; + font-weight: 400; +} + +.textarea::placeholder { + color: var(--text-color-tertiary); +} + +.button { + display: flex; + flex-direction: row; + padding: 16px 24px; + border-radius: 8px; + border: 1px solid var(--primary-color); + background-color: var(--primary-color); + color: var(--on-primary); + gap: 8px; + align-self: end; +} + +.buttonText { + font-size: 16px; + line-height: 1.4; + font-weight: 700; +} diff --git a/frontend/src/pages/LectureCreatePage/index.js b/frontend/src/pages/LectureCreatePage/index.js new file mode 100644 index 00000000..70d624d4 --- /dev/null +++ b/frontend/src/pages/LectureCreatePage/index.js @@ -0,0 +1 @@ +export { default } from './LectureCreatePage'; diff --git a/frontend/src/pages/LectureInfoPage/LectureInfoPage.jsx b/frontend/src/pages/LectureInfoPage/LectureInfoPage.jsx index 45590303..fd2dbcca 100644 --- a/frontend/src/pages/LectureInfoPage/LectureInfoPage.jsx +++ b/frontend/src/pages/LectureInfoPage/LectureInfoPage.jsx @@ -15,7 +15,7 @@ export default function LectureInfoPage() { const startDate = new Date(lectureData.startDate).toLocaleDateString(); const endDate = new Date(lectureData.endDate).toLocaleDateString(); const userType = useBoundStore((state) => state.userType); - + console.log(lectureData); const { lectureRegister } = useLectureRegister(); const handleSubmit = () => { if (userType === null) { @@ -37,7 +37,7 @@ export default function LectureInfoPage() { diff --git a/frontend/src/pages/NoticeListPage/NoticeListPage.jsx b/frontend/src/pages/NoticeListPage/NoticeListPage.jsx index 99b4e571..d70161da 100644 --- a/frontend/src/pages/NoticeListPage/NoticeListPage.jsx +++ b/frontend/src/pages/NoticeListPage/NoticeListPage.jsx @@ -2,16 +2,18 @@ import { ArticleLink } from '../../components/ArticleLink'; import ArticleBoard from '../../components/ArticleBoard/ArticleBoard'; import { useNotices } from '../../hooks/api/useNotices'; import { useParams } from 'react-router-dom'; +import useBoundStore from '../../store'; export default function NoticeListPage() { const { lectureId } = useParams(); const { data } = useNotices(lectureId); const notices = data?.data; + const userType = useBoundStore((state) => state.userType); return ( {notices.map?.((notice) => ( ); } diff --git a/frontend/src/pages/QuestionListPage/QuestionListPage.jsx b/frontend/src/pages/QuestionListPage/QuestionListPage.jsx index d9407154..27ba6d8a 100644 --- a/frontend/src/pages/QuestionListPage/QuestionListPage.jsx +++ b/frontend/src/pages/QuestionListPage/QuestionListPage.jsx @@ -2,16 +2,18 @@ import { ArticleLink } from '../../components/ArticleLink'; import ArticleBoard from '../../components/ArticleBoard/ArticleBoard'; import { useParams } from 'react-router-dom'; import { useQnas } from '../../hooks/api/useQnas'; +import useBoundStore from '../../store'; export default function QuestionListPage() { const { lectureId } = useParams(); const { data } = useQnas(lectureId); const questions = data?.data; + const userType = useBoundStore((state) => state.userType); return ( {questions.map?.((question) => (