fix: 커밋 누락사항(quizset, updateinfo) 재반영

This commit is contained in:
정기영 2024-08-05 13:23:39 +09:00
parent a8069bb562
commit 4d4a2b579f
14 changed files with 176 additions and 76 deletions

View File

@ -1,11 +1,15 @@
import styles from './InfoEditForm.module.css';
import { useState } from 'react';
export default function InfoEditForm() {
export default function InfoEditForm({ onSubmit }) {
const [username, setUsername] = useState('');
const [useremail, setUseremail] = useState('');
return (
<form className={styles.infoEditForm}>
<form
onSubmit={(e) => onSubmit(e, username, useremail)}
className={styles.infoEditForm}
>
<p className={styles.textHeading}>이름 변경</p>
<div className={styles.inputBox}>
<label

View File

@ -4,7 +4,7 @@ import styles from './LectureForm.module.css';
import EditIcon from '/src/assets/icons/edit.svg?react';
import BackIcon from '/src/assets/icons/back.svg?react';
export default function LectureForm({ title, topic, to, initialValues = {}, onSubmit, onCreate = false }) {
export default function LectureForm({ title, topic, to = '..', initialValues = {}, onSubmit, onCreate = false }) {
// TODO: , useState
const titleRef = useRef('');
const descriptionRef = useRef('');

View File

@ -1,13 +1,13 @@
import { useState, useRef } from 'react';
import styles from './PasswordChangeForm.module.css';
export default function PasswordChangeForm() {
export default function PasswordChangeForm({ onSubmit, onPwError = false }) {
// TODO: onPwError( )
const [errorConfirmMessage, setErrorConfirmMessage] = useState(false);
const [errorSameMessage, setErrorSameMessage] = useState(false);
const currentPasswordRef = useRef('');
const newPasswordRef = useRef('');
const confirmPasswordRef = useRef('');
const userPassword = '1234';
const handleSubmit = (e) => {
e.preventDefault();
@ -15,13 +15,15 @@ export default function PasswordChangeForm() {
const newPassword = newPasswordRef.current.value;
const confirmPassword = confirmPasswordRef.current.value;
if (currentPassword === userPassword) {
setErrorSameMessage(false);
} else {
setErrorSameMessage(true);
}
if (newPassword === confirmPassword) {
setErrorConfirmMessage(false);
onSubmit(currentPassword, newPassword, confirmPassword);
if (onPwError) {
setErrorSameMessage(true);
} else {
setErrorSameMessage(false);
}
} else {
setErrorConfirmMessage(true);
}

View File

@ -1,15 +1,18 @@
import { useState } from 'react';
import styles from './QuizCard.module.css';
export default function QuizCard({ quiz, index, updateQuiz }) {
export default function QuizCard({ quiz, updateQuiz, deleteQuiz }) {
const [question, setQuestion] = useState(quiz.question || '');
const [answer, setAnswer] = useState(quiz.answer || '');
const [choices, setChoices] = useState(quiz.choices || []);
const [imageFile, setImageFile] = useState(quiz.imageFile || null);
const handleChoiceChange = (num, content) => {
const updatedChoices = choices.map((choice) => (choice.num === num ? { ...choice, content } : choice));
const updatedChoices = choices.map((choice) =>
choice.num === num ? { ...choice, content } : choice
);
setChoices(updatedChoices);
updateQuiz(index, { question, answer, choices: updatedChoices });
updateQuiz(quiz.id, { ...quiz, question, answer, choices: updatedChoices, imageFile });
};
const handleAddChoice = () => {
@ -17,7 +20,7 @@ export default function QuizCard({ quiz, index, updateQuiz }) {
const newChoice = { num: choices.length + 1, content: '' };
const updatedChoices = [...choices, newChoice];
setChoices(updatedChoices);
updateQuiz(index, { question, answer, choices: updatedChoices });
updateQuiz(quiz.id, { ...quiz, question, answer, choices: updatedChoices, imageFile });
}
};
@ -25,19 +28,29 @@ export default function QuizCard({ quiz, index, updateQuiz }) {
if (choices.length > 0) {
const updatedChoices = choices.slice(0, -1);
setChoices(updatedChoices);
updateQuiz(index, { question, answer, choices: updatedChoices });
updateQuiz(quiz.id, { ...quiz, question, answer, choices: updatedChoices, imageFile });
}
};
const handleFileChange = (e) => {
const file = e.target.files[0] ?? null;
setImageFile(file);
updateQuiz(quiz.id, { ...quiz, question, answer, choices, imageFile: file });
};
return (
<div className={styles.card}>
<div className={styles.header}>
<span>퀴즈 생성 카드</span>
<span onClick={() => deleteQuiz(quiz.id)}>X</span> {/* id를 기반으로 삭제 */}
</div>
<label>질문</label>
<input
type="text"
value={question}
onChange={(e) => {
setQuestion(e.target.value);
updateQuiz(index, { question: e.target.value, answer, choices });
updateQuiz(quiz.id, { ...quiz, question: e.target.value, answer, choices, imageFile });
}}
placeholder="질문 내용을 입력하세요"
/>
@ -47,7 +60,7 @@ export default function QuizCard({ quiz, index, updateQuiz }) {
value={answer}
onChange={(e) => {
setAnswer(e.target.value);
updateQuiz(index, { question, answer: e.target.value, choices });
updateQuiz(quiz.id, { ...quiz, question, answer: e.target.value, choices, imageFile });
}}
placeholder="정답을 입력하세요"
/>
@ -55,18 +68,10 @@ export default function QuizCard({ quiz, index, updateQuiz }) {
<span>Tip: 선택지를 넣지 않는다면 단답형 문제가 됩니다</span>
</div>
<div className={styles.buttonsWrapper}>
<button
type="button"
onClick={handleAddChoice}
className={styles.button}
>
<button type="button" onClick={handleAddChoice} className={styles.button}>
선택지 추가하기
</button>
<button
type="button"
onClick={handlePopChoice}
className={styles.removeButton}
>
<button type="button" onClick={handlePopChoice} className={styles.removeButton}>
선택지 줄이기
</button>
</div>
@ -81,6 +86,8 @@ export default function QuizCard({ quiz, index, updateQuiz }) {
/>
</div>
))}
<label>퀴즈 이미지</label>
<input type="file" accept=".png, .jpg, .jpeg" onChange={handleFileChange} />
</div>
);
}
}

View File

@ -8,6 +8,12 @@
gap: 8px;
}
.header {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.buttonsWrapper {
display: flex;
flex-direction: row;

View File

@ -6,32 +6,33 @@ import BackIcon from '/src/assets/icons/back.svg?react';
import { Link } from 'react-router-dom';
export default function QuizsetForm({ headerTitle, topic, to, onSubmit }) {
// TODO:
const [title, setTitle] = useState('');
const [quizzes, setQuizzes] = useState([]);
const [imageFile, setImageFile] = useState(null);
const [quizId, setQuizId] = useState(0);
const handleAddQuiz = () => {
setQuizzes([...quizzes, { question: '', answer: '', choices: [] }]);
setQuizzes([
...quizzes,
{ id: quizId, question: '', answer: '', choices: [], imageFile: null },
]);
setQuizId(quizId + 1);
};
const updateQuiz = (index, updatedQuiz) => {
const updatedQuizzes = quizzes.map((quiz, i) => (i === index ? updatedQuiz : quiz));
const updateQuiz = (id, updatedQuiz) => {
const updatedQuizzes = quizzes.map((quiz) =>
quiz.id === id ? updatedQuiz : quiz
);
setQuizzes(updatedQuizzes);
};
const handleFileChange = (e) => {
const file = e.target.files?.[0];
setImageFile(file);
const deleteQuiz = (id) => {
setQuizzes(quizzes.filter((quiz) => quiz.id !== id));
};
return (
<div className={styles.quizsetForm}>
<header className={styles.header}>
<Link
to={to}
className={styles.goBack}
>
<Link to={to} className={styles.goBack}>
<BackIcon />
<span>{headerTitle}</span>
</Link>
@ -39,7 +40,7 @@ export default function QuizsetForm({ headerTitle, topic, to, onSubmit }) {
</header>
<form
className={styles.form}
onSubmit={(e) => onSubmit(e, title, quizzes, imageFile)}
onSubmit={(e) => onSubmit(e, title, quizzes)}
>
<input
type="text"
@ -47,12 +48,12 @@ export default function QuizsetForm({ headerTitle, topic, to, onSubmit }) {
onChange={(e) => setTitle(e.target.value)}
placeholder="퀴즈셋 제목을 입력해주세요"
/>
{quizzes.map((quiz, index) => (
{quizzes.map((quiz) => (
<QuizCard
key={index}
key={quiz.id}
quiz={quiz}
index={index}
updateQuiz={updateQuiz}
deleteQuiz={deleteQuiz}
/>
))}
<button
@ -62,20 +63,11 @@ export default function QuizsetForm({ headerTitle, topic, to, onSubmit }) {
>
퀴즈 추가하기
</button>
<label>퀴즈 이미지</label>
<input
type="file"
accept=".png, .jpg, .jpeg"
onChange={handleFileChange}
/>
<button
type="submit"
className={styles.button}
>
<button type="submit" className={styles.button}>
<EditIcon />
<div>제출</div>
</button>
</form>
</div>
);
}
}

View File

@ -2,7 +2,7 @@ import BackIcon from '/src/assets/icons/back.svg?react';
import { Link } from 'react-router-dom';
import styles from './QuizsetDetail.module.css';
export default function QuizsetDetail({ topic, title }) {
export default function QuizsetDetail({ topic, title, quizzes = [], onDelete }) {
return (
<div className={styles.quizsetDetail}>
<header className={styles.header}>
@ -17,6 +17,24 @@ export default function QuizsetDetail({ topic, title }) {
<h1 className={styles.title}>{title}</h1>
</div>
</header>
<div>
{quizzes.map((quiz, index) => (
<div key={index}>
<div>질문 : {quiz.question}</div>
<img
src={quiz.image}
alt="강의 이미지"
/>
<div>정답 : {quiz.answer}</div>
</div>
))}
</div>
<button
type="button"
onClick={onDelete}
>
퀴즈셋 삭제
</button>
</div>
);
}

View File

@ -59,5 +59,23 @@ export function useAuth() {
});
};
return { login, logout, userRegister };
const updateInfo = (name, email) => {
const infoBody = {
name,
email,
};
return instance.put(`${API_URL}/user/updateinfo`, infoBody);
};
const updatePassword = (currentPw, newPw, newPwCheck) => {
const passwordBody = {
currentPassword: currentPw,
newPassword: newPw,
newPasswordCheck: newPwCheck,
};
console.log(passwordBody);
return instance.put(`${API_URL}/user/updatepassword`, passwordBody);
};
return { login, logout, userRegister, updateInfo, updatePassword };
}

View File

@ -0,0 +1,10 @@
import instance from '../../utils/axios/instance';
import { API_URL } from '../../constants';
export function useQuizsetDelete() {
const quizsetDelete = (quizsetId) => {
return instance.delete(`${API_URL}/quiz/teacher/${quizsetId}`);
};
return { quizsetDelete };
}

View File

@ -5,6 +5,6 @@ import { API_URL } from '../../constants';
export function useQuizsetDetail(id) {
return useSuspenseQuery({
queryKey: ['quizset', id],
queryFn: () => instance.get(`${API_URL}/quiz/${id}`),
queryFn: () => instance.get(`${API_URL}/quiz/teacher/${id}`),
});
}

View File

@ -0,0 +1,10 @@
import instance from '../../utils/axios/instance';
import { API_URL } from '../../constants';
export function useQuizsetEdit() {
const quizsetEdit = (quizsetId, quizsetObject) => {
return instance.put(`${API_URL}/lecture/${quizsetId}`, quizsetObject);
};
return { quizsetEdit };
}

View File

@ -21,9 +21,10 @@ export default function LectureCreatePage() {
return (
<div>
<h1>강의 생성</h1>
<LectureForm
title={'강의 생성'}
title={'강의 홈'}
topic={'강의 생성'}
to={'..'}
onSubmit={handleSubmit}
onCreate={true}
/>

View File

@ -1,11 +1,25 @@
import { useQuizsetDetail } from '../../hooks/api/useQuizsetDetail';
import { useParams } from 'react-router-dom';
import { useParams, useNavigate } from 'react-router-dom';
import { QuizsetDetail } from '../../components/QuizsetDetail';
import { useQuizsetDelete } from '../../hooks/api/useQuizsetDelete';
export default function QuizsetListPage() {
const { lectureId } = useParams();
const { data } = useQuizsetDetail(lectureId);
const quizset = data?.data ?? [];
export default function QuizsetDetailPage() {
const navigate = useNavigate();
const { quizsetId } = useParams();
const { quizsetDelete } = useQuizsetDelete();
const { data } = useQuizsetDetail(quizsetId);
const quizset = data.data;
console.log(quizset);
return <QuizsetDetail title={quizset.title} />;
const handleDelete = async () => {
await quizsetDelete(quizsetId);
navigate('..');
};
return (
<QuizsetDetail
topic={'퀴즈 목록'}
title={quizset.title}
quizzes={quizset.quizzes}
onDelete={handleDelete}
/>
);
}

View File

@ -1,26 +1,44 @@
import { QuizsetForm } from '../../components/QuizForm';
import { useQuizsetWrite } from '../../hooks/api/useQuizsetWrite';
import { useNavigate } from 'react-router-dom';
export default function QuizsetWritePage() {
// TODO: lecture
const navigate = useNavigate();
const { quizsetWrite } = useQuizsetWrite();
const handleSubmit = async (e, title, quizzes, imageFile = null) => {
const handleSubmit = async (e, title, quizzes) => {
e.preventDefault();
console.log(quizzes);
const images = [];
const quizContents = [];
quizzes.forEach((quiz) => {
const { imageFile, ...quizData } = quiz;
images.push(imageFile);
quizContents.push(quizData);
});
const quizsetObject = {
title,
quizzes,
quizzes: quizContents,
};
console.log(quizsetObject);
console.log(imageFile);
const formData = new FormData();
formData.append('quizSetCreateRequest', new Blob([JSON.stringify(quizsetObject)], { type: 'application/json' }));
if (imageFile) {
formData.append('image', imageFile);
}
const response = await quizsetWrite(formData);
console.log(response);
images.forEach((imageFile) => {
if (imageFile) {
formData.append('images', imageFile);
} else {
formData.append('images', new Blob([''], { type: 'image/jpg' }));
}
});
await quizsetWrite(formData);
navigate('..');
};
return (
<QuizsetForm
onSubmit={handleSubmit}