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

quiz 문제 수정, 삭제까지

parent 8a0556fb
......@@ -8,6 +8,7 @@ import Quiz from "./quiz/Quiz";
import Signup from "./user/Signup";
import Quizzes from "./quiz/Quizzes";
import EditProblem from "./quiz/EditProblem";
import NewProblem from "./quiz/NewProblem";
function MainRouter() {
return (
......@@ -29,6 +30,9 @@ function MainRouter() {
<Route path="/quiz/by/:userId">
<Quizzes />
</Route>
{/* <Route path="/quiz/problem/new/:quizId">
<NewProblem />
</Route> */}
<Route path="/quiz/problem/edit/:problemId">
<EditProblem />
</Route>
......
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() {
const { problemId } = useParams();
const [problem, setProblem] = useState({});
const [problem, setProblem] = useState({show: false});
const jwt = authHelpers.isAuthenticated();
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]);
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;
......@@ -2,8 +2,10 @@ import React, { useState } from "react";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import Col from "react-bootstrap/Col";
import { useParams } from "react-router-dom";
function NewProblem({ addProblem }) {
const { quizId } = useParams();
const [answers, setAnswers] = useState([""]);
const [question, setQuestion] = useState("");
......@@ -58,7 +60,7 @@ function NewProblem({ addProblem }) {
</Col>
<Col>
{answers.length !== 1 && (
<Button onClick={removeAnswer}>Remove</Button>
<Button onClick={() => removeAnswer(index)}>Remove</Button>
)}
{answers.length - 1 === index && (
<Button onClick={addAnswer}>Add</Button>
......@@ -67,7 +69,7 @@ function NewProblem({ addProblem }) {
</Form.Row>
);
})}
<Button onClick={clickAdd}>Add</Button>
<Button onClick={clickAdd}>문제 추가</Button>
</Form>
</div>
);
......
import React, { useState } from "react";
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 { create } from "./api-quiz";
import NewProblem from "./NewProblem";
// import NewProblem from "./NewProblem";
import Problem from "./Problem";
function NewQuiz() {
......@@ -51,13 +53,84 @@ function NewQuiz() {
<input id='title' name='title' onChange={handleChange} placeholder='Title' />
{
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>
</div>
);
}
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 }) {
<Link to={`/quiz/problem/edit/${problem._id}`}>
<Button onClick={(event) => onUpdate(number)}>수정</Button>
</Link>
<Button onClick={onRemove}>삭제</Button>
<Button onClick={() => onRemove(number)}>삭제</Button>
</Card.Body>
</Card>
);
......
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import { read } from "./api-quiz";
import { Link, useParams } from "react-router-dom";
import { read, removeProblem } from "./api-quiz";
import auth from "../auth/auth-helpers";
import Problem from './Problem'
import Button from "react-bootstrap/Button";
function Quiz() {
const { quizId } = useParams();
......@@ -31,8 +32,20 @@ function Quiz() {
console.log(`Quiz에서 handleUpdate ${JSON.stringify(quiz.problems[index])}`);
}
const handleRemove = () => {
const handleRemove = (index) => {
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 (
......@@ -41,6 +54,9 @@ function Quiz() {
{quiz.problems?.map((problem, i) => {
return <Problem key={i} problem={problem} number={i} onUpdate={handleUpdate} onRemove={handleRemove} />;
})}
<Link to={`/quiz/problem/new/${quizId}`}>
<Button>문제 추가</Button>
</Link>
</div>
);
}
......
......@@ -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) => {
try {
let response = await fetch('/api/quiz/by/' + params.userId, {
......@@ -52,5 +102,8 @@ const listByUserId = async (params, credentials, signal) => {
export {
create,
read,
readProblem,
updateProblem,
removeProblem,
listByUserId,
}
\ No newline at end of file
......@@ -5,6 +5,10 @@ const ProblemSchema = new mongoose.Schema({
type: mongoose.SchemaTypes.ObjectId,
ref: 'User'
},
quiz: {
type: mongoose.SchemaTypes.ObjectId,
ref: 'Quiz'
},
type: String, // 객관식, 주관식 single/multiple choice
created: {
type: Date,
......
......@@ -16,6 +16,7 @@ const create = async (req, res) => {
const p = new Problem(problem)
// console.log('problem in quiz.controller:', p);
p.author = req.profile
p.quiz = quiz._id
await p.save()
quiz.problems.push(p._id)
}
......@@ -65,6 +66,38 @@ const readProblem = async (req, res) => {
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) => {
try {
const authorId = req.profile._id
......@@ -121,6 +154,8 @@ export default {
create,
read,
readProblem,
updateProblem,
removeProblem,
isAuthor,
isProblemAuthor,
listByUserId,
......
......@@ -14,6 +14,8 @@ router.route('/api/quiz/:quizId')
router.route('/api/quiz/problem/:problemId')
.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('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