Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Front-End] feat:lectureCreatePage 추가 #146

Closed
wants to merge 5 commits into from
Closed
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
5 changes: 5 additions & 0 deletions frontend/src/Router.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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([
{
Expand All @@ -45,6 +46,10 @@ const router = createBrowserRouter([
index: true,
element: <HomePage />,
},
{
path: 'lecture/create',
element: <LectureCreatePage />,
},
{
path: 'lecture/:lectureId/info',
element: <LectureInfoPage />,
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/Layout/LectureLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ 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 (
<>
<LectureHeader
title={lecture.title}
tutor={lecture.teacherName}
img={lecture.image}
// TODO: isLive를 받아올 수단 추가
isLive={true}
/>
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/hooks/api/useLectureCreate.js
Original file line number Diff line number Diff line change
@@ -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 };
}
16 changes: 16 additions & 0 deletions frontend/src/hooks/api/usePasswordChange.js
Original file line number Diff line number Diff line change
@@ -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 };
}
4 changes: 2 additions & 2 deletions frontend/src/pages/CreateQuestionPage/CreateQuestionPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
111 changes: 111 additions & 0 deletions frontend/src/pages/LectureCreatePage/LectureCreatePage.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<form
className={styles.createClass}
onSubmit={handleSubmit}
>
<div className={styles.inputField}>
<label className={styles.label}>강의명</label>
<input
className={styles.input}
ref={titleRef}
type="text"
placeholder="강의명을 입력하세요"
/>
</div>
<div className={styles.inputField}>
<label className={styles.label}>설명</label>
<textarea
ref={descriptionRef}
className={styles.textarea}
placeholder="강의에 대한 설명을 입력하세요"
></textarea>
</div>
<div className={styles.inputField}>
<label className={styles.label}>강의 계획</label>
<textarea
ref={planRef}
className={styles.textarea}
placeholder="강의 계획을 입력하세요"
></textarea>
</div>
<div className={styles.inputField}>
<label className={styles.label}>강의 기간</label>
<input
className={styles.input}
ref={startDateRef}
type="date"
/>
<input
className={styles.input}
ref={endDateRef}
type="date"
/>
</div>
<div className={styles.inputField}>
<label className={styles.label}>수업 시간</label>
<input
type="text"
ref={timeRef}
className={styles.input}
placeholder="실제 강의 진행 시간을 입력하세요"
></input>
</div>
<div className={styles.inputField}>
<label className={styles.label}>수업 이미지</label>
<input
type="file"
ref={imageFileRef}
accept=""
/>
</div>
<button
type="submit"
className={styles.button}
>
<div>ㅁ</div>
<div className={styles.buttonText}>강의 생성</div>
</button>
</form>
);
}
69 changes: 69 additions & 0 deletions frontend/src/pages/LectureCreatePage/LectureCreatePage.module.css
Original file line number Diff line number Diff line change
@@ -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;
}
1 change: 1 addition & 0 deletions frontend/src/pages/LectureCreatePage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './LectureCreatePage';
4 changes: 2 additions & 2 deletions frontend/src/pages/LectureInfoPage/LectureInfoPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -37,7 +37,7 @@ export default function LectureInfoPage() {
<LectureHeader
title={lectureData.title}
img={lectureData.image}
tutor={lectureData.teachername}
tutor={lectureData.teacherName}
tutorImg={lectureData.tutorImg}
/>
<MaxWidthLayout hasSideBar>
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/pages/NoticeListPage/NoticeListPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<ArticleBoard
title="공지사항"
canCreate={false}
canCreate={userType === 'teacher'}
>
{notices.map?.((notice) => (
<ArticleLink
Expand Down
4 changes: 1 addition & 3 deletions frontend/src/pages/QuestionDetailPage/QuestionDetailPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,14 @@ export default function QuestionDetailPage() {
const qnaId = params.questionId;
const { data } = useQnaDetail(qnaId);
const qna = data?.data;
const answer = qna?.answer;
console.log(qna.author);

return (
<ArticleDetail
topic="Q&A"
title={qna.title}
author={qna.username}
content={qna.content}
answer={answer}
answer={qna?.answer}
/>
);
}
4 changes: 3 additions & 1 deletion frontend/src/pages/QuestionListPage/QuestionListPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<ArticleBoard
title="Q&A"
canCreate={true}
canCreate={userType === 'student'}
>
{questions.map?.((question) => (
<ArticleLink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
font-size: 16px;
line-height: 1.4;
font-weight: 700;
transition:
background-color 0.25s,
border-color 0.25s,
stroke 0.25s,
color 0.25s;
}

.active {
Expand Down