Commit 75cdec2c authored by Yoon, Daeki's avatar Yoon, Daeki 😅
Browse files

quiz 문제 수정, 삭제까지

parent 8a0556fb
...@@ -8,6 +8,7 @@ import Quiz from "./quiz/Quiz"; ...@@ -8,6 +8,7 @@ import Quiz from "./quiz/Quiz";
import Signup from "./user/Signup"; import Signup from "./user/Signup";
import Quizzes from "./quiz/Quizzes"; import Quizzes from "./quiz/Quizzes";
import EditProblem from "./quiz/EditProblem"; import EditProblem from "./quiz/EditProblem";
import NewProblem from "./quiz/NewProblem";
function MainRouter() { function MainRouter() {
return ( return (
...@@ -29,6 +30,9 @@ function MainRouter() { ...@@ -29,6 +30,9 @@ function MainRouter() {
<Route path="/quiz/by/:userId"> <Route path="/quiz/by/:userId">
<Quizzes /> <Quizzes />
</Route> </Route>
{/* <Route path="/quiz/problem/new/:quizId">
<NewProblem />
</Route> */}
<Route path="/quiz/problem/edit/:problemId"> <Route path="/quiz/problem/edit/:problemId">
<EditProblem /> <EditProblem />
</Route> </Route>
......
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom"; import { Link, useParams } from "react-router-dom";
import Form from "react-bootstrap/Form";
import Col from "react-bootstrap/Col";
import Button from "react-bootstrap/Button";
import Modal from 'react-bootstrap/Modal'
import authHelpers from "../auth/auth-helpers";
import { readProblem, updateProblem } from "./api-quiz";
function EditProblem() { function EditProblem() {
const { problemId } = useParams(); const { problemId } = useParams();
const [problem, setProblem] = useState({}); const [problem, setProblem] = useState({show: false});
const jwt = authHelpers.isAuthenticated();
useEffect(() => { useEffect(() => {
return () => {}; const abortController = new AbortController();
const signal = abortController.signal;
readProblem({ problemId }, { t: jwt.token }, signal).then((data) => {
if (data.error) {
console.log(data.error);
} else {
console.log(data);
setProblem(data);
}
});
return () => {
abortController.abort();
};
}, [problemId]); }, [problemId]);
return <div>문제를 수정합니다. id: {problemId}</div>; const addAnswer = () => {
setProblem({...problem, answers: [...problem.answers, '']})
};
const removeAnswer = (index) => {
const list = [...problem.answers];
list.splice(index, 1);
setProblem({...problem, answers: list})
};
const handleAnswer = (event, index) => {
const { value } = event.target;
const list = [...problem.answers];
list[index] = value;
setProblem({...problem, answers: list})
};
const handleQuestion = (event) => {
const {value} = event.target
setProblem({...problem, question: value})
};
const handleSave = (event) => {
event.preventDefault();
console.log(problem);
updateProblem({problemId}, {t: jwt.token}, problem).then(data => {
if (data.error) {
console.log(data.error);
} else {
console.log(data);
setProblem({...data, show: true})
}
})
};
return (
<div>
문제를 수정합니다. id: {problemId}
<Form>
<Form.Group controlId="question">
<Form.Label>Question</Form.Label>
<Form.Control
name="question"
as="textarea"
value={problem.question}
rows={5}
onChange={handleQuestion}
/>
</Form.Group>
<Form.Label>Answers</Form.Label>
{problem.answers?.map((answer, index) => {
return (
<Form.Row key={index}>
<Col>
<Form.Control
type="text"
value={answer}
onChange={(event) => handleAnswer(event, index)}
/>
</Col>
<Col>
{problem.answers.length !== 1 && (
<Button onClick={() => removeAnswer(index)}>Remove</Button>
)}
{problem.answers.length - 1 === index && (
<Button onClick={addAnswer}>Add</Button>
)}
</Col>
</Form.Row>
);
})}
<Button onClick={handleSave}>저장</Button>
</Form>
<Modal show={problem.show}>
<Modal.Header>
<Modal.Title>Edit Problem</Modal.Title>
</Modal.Header>
<Modal.Body>
Problem successfully modified.
</Modal.Body>
<Modal.Footer>
<Link to={`/quiz/${problem.quiz}`}>
<Button>Go to quiz</Button>
</Link>
</Modal.Footer>
</Modal>
</div>
);
} }
export default EditProblem; export default EditProblem;
...@@ -2,8 +2,10 @@ import React, { useState } from "react"; ...@@ -2,8 +2,10 @@ import React, { useState } from "react";
import Button from "react-bootstrap/Button"; import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form"; import Form from "react-bootstrap/Form";
import Col from "react-bootstrap/Col"; import Col from "react-bootstrap/Col";
import { useParams } from "react-router-dom";
function NewProblem({ addProblem }) { function NewProblem({ addProblem }) {
const { quizId } = useParams();
const [answers, setAnswers] = useState([""]); const [answers, setAnswers] = useState([""]);
const [question, setQuestion] = useState(""); const [question, setQuestion] = useState("");
...@@ -58,7 +60,7 @@ function NewProblem({ addProblem }) { ...@@ -58,7 +60,7 @@ function NewProblem({ addProblem }) {
</Col> </Col>
<Col> <Col>
{answers.length !== 1 && ( {answers.length !== 1 && (
<Button onClick={removeAnswer}>Remove</Button> <Button onClick={() => removeAnswer(index)}>Remove</Button>
)} )}
{answers.length - 1 === index && ( {answers.length - 1 === index && (
<Button onClick={addAnswer}>Add</Button> <Button onClick={addAnswer}>Add</Button>
...@@ -67,7 +69,7 @@ function NewProblem({ addProblem }) { ...@@ -67,7 +69,7 @@ function NewProblem({ addProblem }) {
</Form.Row> </Form.Row>
); );
})} })}
<Button onClick={clickAdd}>Add</Button> <Button onClick={clickAdd}>문제 추가</Button>
</Form> </Form>
</div> </div>
); );
......
import React, { useState } from "react"; import React, { useState } from "react";
import Button from "react-bootstrap/Button"; import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import Col from "react-bootstrap/Col";
import authHelpers from "../auth/auth-helpers"; import authHelpers from "../auth/auth-helpers";
import { create } from "./api-quiz"; import { create } from "./api-quiz";
import NewProblem from "./NewProblem"; // import NewProblem from "./NewProblem";
import Problem from "./Problem"; import Problem from "./Problem";
function NewQuiz() { function NewQuiz() {
...@@ -51,13 +53,84 @@ function NewQuiz() { ...@@ -51,13 +53,84 @@ function NewQuiz() {
<input id='title' name='title' onChange={handleChange} placeholder='Title' /> <input id='title' name='title' onChange={handleChange} placeholder='Title' />
{ {
problems.map((problem, index) => { problems.map((problem, index) => {
return <Problem key={index} problem={problem} number={index+1} /> return <Problem key={index} problem={problem} number={index} />
}) })
} }
<NewProblem addProblem={addProblem} /> <NewQuizProblem addProblem={addProblem} />
<Button onClick={clickSubmit}>퀴즈 저장</Button> <Button onClick={clickSubmit}>퀴즈 저장</Button>
</div> </div>
); );
} }
export default NewQuiz; export default NewQuiz;
function NewQuizProblem({ addProblem }) {
// const { quizId } = useParams();
const [answers, setAnswers] = useState([""]);
const [question, setQuestion] = useState("");
const addAnswer = () => {
setAnswers([...answers, ""]);
};
const removeAnswer = (index) => {
const list = [...answers];
list.splice(index, 1);
setAnswers(list);
};
const handleAnswer = (event, index) => {
const { value } = event.target;
const list = [...answers];
list[index] = value;
setAnswers(list);
};
const handleQuestion = (event) => {
setQuestion(event.target.value);
};
const clickAdd = (event) => {
event.preventDefault();
addProblem({ question, answers });
};
return (
<div>
<Form>
<Form.Group controlId="question">
<Form.Label>Question</Form.Label>
<Form.Control
name="question"
as="textarea"
rows={5}
onChange={handleQuestion}
/>
</Form.Group>
<Form.Label>Answers</Form.Label>
{answers.map((answer, index) => {
return (
<Form.Row key={index}>
<Col>
<Form.Control
type="text"
value={answer}
onChange={(event) => handleAnswer(event, index)}
/>
</Col>
<Col>
{answers.length !== 1 && (
<Button onClick={() => removeAnswer(index)}>Remove</Button>
)}
{answers.length - 1 === index && (
<Button onClick={addAnswer}>Add</Button>
)}
</Col>
</Form.Row>
);
})}
<Button onClick={clickAdd}>문제 추가</Button>
</Form>
</div>
);
}
...@@ -17,7 +17,7 @@ function Problem({ problem, number, onUpdate, onRemove }) { ...@@ -17,7 +17,7 @@ function Problem({ problem, number, onUpdate, onRemove }) {
<Link to={`/quiz/problem/edit/${problem._id}`}> <Link to={`/quiz/problem/edit/${problem._id}`}>
<Button onClick={(event) => onUpdate(number)}>수정</Button> <Button onClick={(event) => onUpdate(number)}>수정</Button>
</Link> </Link>
<Button onClick={onRemove}>삭제</Button> <Button onClick={() => onRemove(number)}>삭제</Button>
</Card.Body> </Card.Body>
</Card> </Card>
); );
......
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom"; import { Link, useParams } from "react-router-dom";
import { read } from "./api-quiz"; import { read, removeProblem } from "./api-quiz";
import auth from "../auth/auth-helpers"; import auth from "../auth/auth-helpers";
import Problem from './Problem' import Problem from './Problem'
import Button from "react-bootstrap/Button";
function Quiz() { function Quiz() {
const { quizId } = useParams(); const { quizId } = useParams();
...@@ -31,8 +32,20 @@ function Quiz() { ...@@ -31,8 +32,20 @@ function Quiz() {
console.log(`Quiz에서 handleUpdate ${JSON.stringify(quiz.problems[index])}`); console.log(`Quiz에서 handleUpdate ${JSON.stringify(quiz.problems[index])}`);
} }
const handleRemove = () => { const handleRemove = (index) => {
console.log('Quiz에서 handleRemove 실행'); console.log('Quiz에서 handleRemove 실행');
const problem = quiz.problems[index]
console.log(problem);
removeProblem({problemId: problem._id}, {t: jwt.token}).then(data => {
if (data.error) {
console.log(data.error);
} else {
console.log('deleted Problem:', data);
const list = [...quiz.problems]
list.splice(index, 1)
setQuiz({...quiz, problems: list})
}
})
} }
return ( return (
...@@ -41,6 +54,9 @@ function Quiz() { ...@@ -41,6 +54,9 @@ function Quiz() {
{quiz.problems?.map((problem, i) => { {quiz.problems?.map((problem, i) => {
return <Problem key={i} problem={problem} number={i} onUpdate={handleUpdate} onRemove={handleRemove} />; return <Problem key={i} problem={problem} number={i} onUpdate={handleUpdate} onRemove={handleRemove} />;
})} })}
<Link to={`/quiz/problem/new/${quizId}`}>
<Button>문제 추가</Button>
</Link>
</div> </div>
); );
} }
......
...@@ -33,6 +33,56 @@ const read = async (params, credentials, signal) => { ...@@ -33,6 +33,56 @@ const read = async (params, credentials, signal) => {
} }
} }
const readProblem = async (params, credentials, signal) => {
try {
let response = await fetch('/api/quiz/problem/' + params.problemId, {
method: 'GET',
signal: signal,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + credentials.t,
},
})
return await response.json()
} catch (error) {
console.log(error)
}
}
const updateProblem = async (params, credentials, problem) => {
try {
let response = await fetch('/api/quiz/problem/' + params.problemId, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + credentials.t,
},
body: JSON.stringify(problem)
})
return await response.json()
} catch (error) {
console.log(error)
}
}
const removeProblem = async (params, credentials) => {
try {
let response = await fetch('/api/quiz/problem/' + params.problemId, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + credentials.t,
}
})
return await response.json()
} catch (error) {
console.log(error)
}
}
const listByUserId = async (params, credentials, signal) => { const listByUserId = async (params, credentials, signal) => {
try { try {
let response = await fetch('/api/quiz/by/' + params.userId, { let response = await fetch('/api/quiz/by/' + params.userId, {
...@@ -52,5 +102,8 @@ const listByUserId = async (params, credentials, signal) => { ...@@ -52,5 +102,8 @@ const listByUserId = async (params, credentials, signal) => {
export { export {
create, create,
read, read,
readProblem,
updateProblem,
removeProblem,
listByUserId, listByUserId,
} }
\ No newline at end of file
...@@ -5,6 +5,10 @@ const ProblemSchema = new mongoose.Schema({ ...@@ -5,6 +5,10 @@ const ProblemSchema = new mongoose.Schema({
type: mongoose.SchemaTypes.ObjectId, type: mongoose.SchemaTypes.ObjectId,
ref: 'User' ref: 'User'
}, },
quiz: {
type: mongoose.SchemaTypes.ObjectId,
ref: 'Quiz'
},
type: String, // 객관식, 주관식 single/multiple choice type: String, // 객관식, 주관식 single/multiple choice
created: { created: {
type: Date, type: Date,
......
...@@ -16,6 +16,7 @@ const create = async (req, res) => { ...@@ -16,6 +16,7 @@ const create = async (req, res) => {
const p = new Problem(problem) const p = new Problem(problem)
// console.log('problem in quiz.controller:', p); // console.log('problem in quiz.controller:', p);
p.author = req.profile p.author = req.profile
p.quiz = quiz._id
await p.save() await p.save()
quiz.problems.push(p._id) quiz.problems.push(p._id)
} }
...@@ -65,6 +66,38 @@ const readProblem = async (req, res) => { ...@@ -65,6 +66,38 @@ const readProblem = async (req, res) => {
res.json(problem) res.json(problem)
} }
const updateProblem = async (req, res) => {
try {
const problem = req.problem
console.log('req.body in updateProblem in quiz.controller', req.body);
problem.question = req.body.question
problem.answers = req.body.answers
problem.updated = new Date()
console.log('updated problem in updateProblem in quiz.controller', problem);
await problem.save()
res.json(problem)
} catch (error) {
return res.status(400).json({
error: dbErrorHandler.getErrorMessage(error)
})
}
}
const removeProblem = async (req, res) => {
try {
const problem = req.problem
await Quiz.findByIdAndUpdate(problem.quiz, {
$pull: {problems: problem._id}
})
const deletedProblem = await problem.remove()
res.json(deletedProblem)
} catch (error) {
return res.status(400).json({
error: dbErrorHandler.getErrorMessage(error)
})
}
}
const listByUserId = async (req, res) => { const listByUserId = async (req, res) => {
try { try {
const authorId = req.profile._id const authorId = req.profile._id
...@@ -121,6 +154,8 @@ export default { ...@@ -121,6 +154,8 @@ export default {
create, create,
read, read,
readProblem, readProblem,
updateProblem,
removeProblem,
isAuthor, isAuthor,
isProblemAuthor, isProblemAuthor,
listByUserId, listByUserId,
......
...@@ -14,6 +14,8 @@ router.route('/api/quiz/:quizId') ...@@ -14,6 +14,8 @@ router.route('/api/quiz/:quizId')
router.route('/api/quiz/problem/:problemId') router.route('/api/quiz/problem/:problemId')
.get(authCtrl.requireSignin, quizCtrl.isProblemAuthor, quizCtrl.readProblem) .get(authCtrl.requireSignin, quizCtrl.isProblemAuthor, quizCtrl.readProblem)
.put(authCtrl.requireSignin, quizCtrl.isProblemAuthor, quizCtrl.updateProblem)
.delete(authCtrl.requireSignin, quizCtrl.isProblemAuthor, quizCtrl.removeProblem)
router.param('userId', userCtrl.userById) router.param('userId', userCtrl.userById)
router.param('quizId', quizCtrl.quizById) router.param('quizId', quizCtrl.quizById)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment