Commit 1c18d0e1 authored by Yoon, Daeki's avatar Yoon, Daeki 😅
Browse files

정답 추가

parent 9d96ee41
# 퀴즈 출제 페이지
## 실행 방법
1. 두 개의 터미널을 엽니다.
1. 한쪽 터미널(서버)에서는, 프로젝트 디렉토리에서 `yarn install`을 실행합니다.(이것은 패키지가 변경될 때마다 실행합니다.)
1. 다른쪽 터미널(클라이언트)에서는, `cd src\client` 해서 `yarn install` 을 실행합니다.(이것은 패키지가 변경될 때마다 실행합니다.)
1. 서버 터미널에서 `yarn dev`를 실행합니다.
1. 클라이언트 터미널에서 `yarn start` 를 실행합니다.
1. 코드를 수정합니다.
import React, { useState } from "react"; import React, { useState } from "react";
import { Link } from "react-router-dom";
import Card from "react-bootstrap/Card"; import Card from "react-bootstrap/Card";
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 Button from "react-bootstrap/Button"; import Button from "react-bootstrap/Button";
import { remove } from "lodash"; import ButtonGroup from "react-bootstrap/ButtonGroup";
import ToggleButton from "react-bootstrap/ToggleButton";
import ToggleButtonGroup from "react-bootstrap/ToggleButtonGroup";
const EditableForm = (props) => { const EditableForm = (props) => {
const { const {
problem, problem,
number, number,
handleCorrect,
removeAnswer, removeAnswer,
addAnswer, addAnswer,
handleQuestion, handleQuestion,
...@@ -28,9 +30,18 @@ const EditableForm = (props) => { ...@@ -28,9 +30,18 @@ const EditableForm = (props) => {
/> />
</Form.Group> </Form.Group>
<Form.Label>Answers</Form.Label> <Form.Label>Answers</Form.Label>
{/* <ToggleButtonGroup type="radio" name="radio" > */}
{problem.answers.map((answer, index) => { {problem.answers.map((answer, index) => {
return ( return (
<Form.Row key={index}> <Form.Row key={index}>
<Col>
<Form.Check
type="radio"
value={index}
name="correct"
onChange={handleCorrect}
/>
</Col>
<Col> <Col>
<Form.Control <Form.Control
value={answer} value={answer}
...@@ -49,6 +60,7 @@ const EditableForm = (props) => { ...@@ -49,6 +60,7 @@ const EditableForm = (props) => {
</Form.Row> </Form.Row>
); );
})} })}
{/* </ToggleButtonGroup> */}
<Button onClick={(event) => handleSave(event, number)}>저장</Button> <Button onClick={(event) => handleSave(event, number)}>저장</Button>
<Button onClick={handleCancel}>취소</Button> <Button onClick={handleCancel}>취소</Button>
</Form> </Form>
...@@ -65,6 +77,7 @@ const CardForm = (props) => { ...@@ -65,6 +77,7 @@ const CardForm = (props) => {
{problem.answers.map((answer, index) => { {problem.answers.map((answer, index) => {
return <Card.Text key={index}>{answer}</Card.Text>; return <Card.Text key={index}>{answer}</Card.Text>;
})} })}
<Card.Text>정답: {+problem.correct + 1}</Card.Text>
<Button onClick={handleEditable}>수정</Button> <Button onClick={handleEditable}>수정</Button>
<Button onClick={() => onRemove(number)}>삭제</Button> <Button onClick={() => onRemove(number)}>삭제</Button>
</Card.Body> </Card.Body>
...@@ -80,6 +93,12 @@ function EditableProblem({ problem, number, onUpdate, onRemove }) { ...@@ -80,6 +93,12 @@ function EditableProblem({ problem, number, onUpdate, onRemove }) {
setEditable(!editable); setEditable(!editable);
}; };
const handleCorrect = (event) => {
const { name, value } = event.target;
console.log("name:", name, "value:", value);
setProblemEdit({...problemEdit, correct: value})
};
const handleCancel = (event) => { const handleCancel = (event) => {
// const { name, value } = event.target; // const { name, value } = event.target;
// console.log(name, value); // console.log(name, value);
...@@ -111,8 +130,8 @@ function EditableProblem({ problem, number, onUpdate, onRemove }) { ...@@ -111,8 +130,8 @@ function EditableProblem({ problem, number, onUpdate, onRemove }) {
}; };
const handleSave = (event, index) => { const handleSave = (event, index) => {
onUpdate(index, problemEdit) onUpdate(index, problemEdit);
setEditable(!editable) setEditable(!editable);
}; };
return ( return (
...@@ -121,6 +140,7 @@ function EditableProblem({ problem, number, onUpdate, onRemove }) { ...@@ -121,6 +140,7 @@ function EditableProblem({ problem, number, onUpdate, onRemove }) {
<EditableForm <EditableForm
number={number} number={number}
problem={problemEdit} problem={problemEdit}
handleCorrect={handleCorrect}
handleSave={handleSave} handleSave={handleSave}
handleCancel={handleCancel} handleCancel={handleCancel}
removeAnswer={removeAnswer} removeAnswer={removeAnswer}
......
...@@ -11,7 +11,8 @@ function NewProblem({ addProblem }) { ...@@ -11,7 +11,8 @@ function NewProblem({ addProblem }) {
const { quizId } = useParams(); const { quizId } = useParams();
const [answers, setAnswers] = useState([""]); const [answers, setAnswers] = useState([""]);
const [question, setQuestion] = useState(""); const [question, setQuestion] = useState("");
const [show, setShow] = useState(false) const [correct, setCorrect] = useState()
const [show, setShow] = useState(false);
const jwt = authHelpers.isAuthenticated(); const jwt = authHelpers.isAuthenticated();
...@@ -32,6 +33,12 @@ function NewProblem({ addProblem }) { ...@@ -32,6 +33,12 @@ function NewProblem({ addProblem }) {
setAnswers(list); setAnswers(list);
}; };
const handleCorrect = (event) => {
const { name, value } = event.target;
console.log("name:", name, "value:", value);
setCorrect(value)
};
const handleQuestion = (event) => { const handleQuestion = (event) => {
setQuestion(event.target.value); setQuestion(event.target.value);
}; };
...@@ -42,6 +49,7 @@ function NewProblem({ addProblem }) { ...@@ -42,6 +49,7 @@ function NewProblem({ addProblem }) {
question, question,
answers, answers,
quiz: quizId, quiz: quizId,
correct: correct,
}; };
createProblem({ userId: jwt.user._id }, { t: jwt.token }, problem).then( createProblem({ userId: jwt.user._id }, { t: jwt.token }, problem).then(
(data) => { (data) => {
...@@ -50,7 +58,7 @@ function NewProblem({ addProblem }) { ...@@ -50,7 +58,7 @@ function NewProblem({ addProblem }) {
} else { } else {
setQuestion(data.question); setQuestion(data.question);
setAnswers(data.answers); setAnswers(data.answers);
setShow(true) setShow(true);
} }
} }
); );
...@@ -73,6 +81,14 @@ function NewProblem({ addProblem }) { ...@@ -73,6 +81,14 @@ function NewProblem({ addProblem }) {
{answers.map((answer, index) => { {answers.map((answer, index) => {
return ( return (
<Form.Row key={index}> <Form.Row key={index}>
<Col>
<Form.Check
type="radio"
value={index}
name="correct"
onChange={handleCorrect}
/>
</Col>
<Col> <Col>
<Form.Control <Form.Control
type="text" type="text"
...@@ -95,9 +111,7 @@ function NewProblem({ addProblem }) { ...@@ -95,9 +111,7 @@ function NewProblem({ addProblem }) {
</Form> </Form>
<Modal show={show}> <Modal show={show}>
<Modal.Header>New Problem</Modal.Header> <Modal.Header>New Problem</Modal.Header>
<Modal.Body> <Modal.Body>Problem successfully created.</Modal.Body>
Problem successfully created.
</Modal.Body>
<Modal.Footer> <Modal.Footer>
<Link to={`/quiz/${quizId}`}> <Link to={`/quiz/${quizId}`}>
<Button>Go to quiz</Button> <Button>Go to quiz</Button>
......
...@@ -15,7 +15,7 @@ import { list } from "../course/api-course"; ...@@ -15,7 +15,7 @@ import { list } from "../course/api-course";
function NewQuiz() { function NewQuiz() {
const [problems, setProblems] = useState([]); const [problems, setProblems] = useState([]);
const [quiz, setQuiz] = useState({}); const [quiz, setQuiz] = useState({});
const [courses, setCourses] = useState([]) const [courses, setCourses] = useState([]);
const [values, setValues] = useState({ const [values, setValues] = useState({
title: "", title: "",
problems: [], problems: [],
...@@ -28,26 +28,26 @@ function NewQuiz() { ...@@ -28,26 +28,26 @@ function NewQuiz() {
const jwt = authHelpers.isAuthenticated(); const jwt = authHelpers.isAuthenticated();
useEffect(() => { useEffect(() => {
const abortController = new AbortController() const abortController = new AbortController();
const signal = abortController.signal const signal = abortController.signal;
list(signal).then(data => { list(signal).then((data) => {
if (data.error) { if (data.error) {
console.log(data.error); console.log(data.error);
} else { } else {
console.log(data); console.log(data);
setCourses(data) setCourses(data);
} }
}) });
return () => { return () => {
abortController.abort() abortController.abort();
} };
}, []) }, []);
const handleChange = (event) => { const handleChange = (event) => {
const { name, value } = event.target; const { name, value } = event.target;
console.log("name", name, "value", value); console.log("name", name, "value", value);
console.log("values:", values); console.log("values:", values);
if (name === "course") { if (name === "course") {
console.log(`${name}: ${courses[value]._id}`); console.log(`${name}: ${courses[value]._id}`);
setValues({ ...values, [name]: courses[value]._id }); setValues({ ...values, [name]: courses[value]._id });
...@@ -59,16 +59,16 @@ function NewQuiz() { ...@@ -59,16 +59,16 @@ function NewQuiz() {
const handleUpdate = (index) => { const handleUpdate = (index) => {
console.log(`Quiz에서 handleUpdate ${index}번 실행`); console.log(`Quiz에서 handleUpdate ${index}번 실행`);
// console.log(`Quiz에서 handleUpdate ${JSON.stringify(quiz.problems[index])}`); // console.log(`Quiz에서 handleUpdate ${JSON.stringify(quiz.problems[index])}`);
} };
const handleRemove = (index) => { const handleRemove = (index) => {
console.log('handleRemove 실행'); console.log("handleRemove 실행");
const problem = problems[index] const problem = problems[index];
console.log(problem); console.log(problem);
const list = [...problems] const list = [...problems];
list.splice(index, 1) list.splice(index, 1);
setProblems(list) setProblems(list);
} };
const addProblem = (problem) => { const addProblem = (problem) => {
console.log(problem); console.log(problem);
...@@ -88,17 +88,17 @@ function NewQuiz() { ...@@ -88,17 +88,17 @@ function NewQuiz() {
console.log(quizData); console.log(quizData);
// create({ userId: jwt.user._id }, { t: jwt.token }, quizData).then( create({ userId: jwt.user._id }, { t: jwt.token }, quizData).then(
// (data) => { (data) => {
// if (data.error) { if (data.error) {
// console.log(data.error); console.log(data.error);
// } else { } else {
// console.log(data); console.log(data);
// setQuiz(data); setQuiz(data);
// setShow(true); setValues({ ...values, show: true });
// } }
// } }
// ); );
}; };
return ( return (
...@@ -124,7 +124,9 @@ function NewQuiz() { ...@@ -124,7 +124,9 @@ function NewQuiz() {
onChange={handleChange} onChange={handleChange}
> >
{courses.map((course, i) => ( {courses.map((course, i) => (
<option key={i} value={i}>{course.name}</option> <option key={i} value={i}>
{course.name}
</option>
))} ))}
</Form.Control> </Form.Control>
</Form.Group> </Form.Group>
...@@ -149,7 +151,15 @@ function NewQuiz() { ...@@ -149,7 +151,15 @@ function NewQuiz() {
</Form.Row> </Form.Row>
{problems.map((problem, index) => { {problems.map((problem, index) => {
return <Problem key={index} problem={problem} number={index} onUpdate={handleUpdate} onRemove={handleRemove}/>; return (
<Problem
key={index}
problem={problem}
number={index}
onUpdate={handleUpdate}
onRemove={handleRemove}
/>
);
})} })}
<NewQuizProblem addProblem={addProblem} /> <NewQuizProblem addProblem={addProblem} />
<Button onClick={clickSubmit}>퀴즈 저장</Button> <Button onClick={clickSubmit}>퀴즈 저장</Button>
...@@ -173,9 +183,9 @@ function NewQuiz() { ...@@ -173,9 +183,9 @@ function NewQuiz() {
export default NewQuiz; export default NewQuiz;
function NewQuizProblem({ addProblem }) { function NewQuizProblem({ addProblem }) {
// const { quizId } = useParams();
const [answers, setAnswers] = useState([""]); const [answers, setAnswers] = useState([""]);
const [question, setQuestion] = useState(""); const [question, setQuestion] = useState("");
const [correct, setCorrect] = useState()
const addAnswer = () => { const addAnswer = () => {
setAnswers([...answers, ""]); setAnswers([...answers, ""]);
...@@ -194,18 +204,23 @@ function NewQuizProblem({ addProblem }) { ...@@ -194,18 +204,23 @@ function NewQuizProblem({ addProblem }) {
setAnswers(list); setAnswers(list);
}; };
const handleCorrect = (event) => {
const { name, value } = event.target;
console.log("name:", name, "value:", value);
setCorrect(value)
};
const handleQuestion = (event) => { const handleQuestion = (event) => {
setQuestion(event.target.value); setQuestion(event.target.value);
}; };
const clickAdd = (event) => { const clickAdd = (event) => {
event.preventDefault(); event.preventDefault();
addProblem({ question, answers }); addProblem({ question, answers, correct });
}; };
return ( return (
<> <>
{/* <Form> */}
<Form.Group controlId="question"> <Form.Group controlId="question">
<Form.Label>Question</Form.Label> <Form.Label>Question</Form.Label>
<Form.Control <Form.Control
...@@ -219,6 +234,14 @@ function NewQuizProblem({ addProblem }) { ...@@ -219,6 +234,14 @@ function NewQuizProblem({ addProblem }) {
{answers.map((answer, index) => { {answers.map((answer, index) => {
return ( return (
<Form.Row key={index}> <Form.Row key={index}>
<Col>
<Form.Check
type="radio"
value={index}
name="correct"
onChange={handleCorrect}
/>
</Col>
<Col> <Col>
<Form.Control <Form.Control
type="text" type="text"
...@@ -238,7 +261,6 @@ function NewQuizProblem({ addProblem }) { ...@@ -238,7 +261,6 @@ function NewQuizProblem({ addProblem }) {
); );
})} })}
<Button onClick={clickAdd}>문제 추가</Button> <Button onClick={clickAdd}>문제 추가</Button>
{/* </Form> */}
</> </>
); );
} }
...@@ -2,10 +2,11 @@ import React, { useState, useEffect } from "react"; ...@@ -2,10 +2,11 @@ import React, { useState, useEffect } from "react";
import { Link, useParams } from "react-router-dom"; import { Link, useParams } from "react-router-dom";
import { read, removeProblem, updateProblem } from "./api-quiz"; import { read, removeProblem, updateProblem } from "./api-quiz";
import auth from "../auth/auth-helpers"; import auth from "../auth/auth-helpers";
import Problem from "./Problem";
import Button from "react-bootstrap/Button"; import Button from "react-bootstrap/Button";
import EditableProblem from "./EditableProblem"; import EditableProblem from "./EditableProblem";
import Container from "react-bootstrap/Container"; import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
function Quiz() { function Quiz() {
const { quizId } = useParams(); const { quizId } = useParams();
...@@ -21,6 +22,7 @@ function Quiz() { ...@@ -21,6 +22,7 @@ function Quiz() {
if (data.error) { if (data.error) {
console.log(data.error); console.log(data.error);
} else { } else {
console.log(data);
setQuiz(data); setQuiz(data);
} }
}); });
...@@ -43,10 +45,10 @@ function Quiz() { ...@@ -43,10 +45,10 @@ function Quiz() {
console.log(data.error); console.log(data.error);
} else { } else {
console.log(data); console.log(data);
const list = [...quiz.problems] const list = [...quiz.problems];
list[index] = data list[index] = data;
console.log(list); console.log(list);
setQuiz({...quiz, problems: list}) setQuiz({ ...quiz, problems: list });
} }
} }
); );
...@@ -56,21 +58,26 @@ function Quiz() { ...@@ -56,21 +58,26 @@ function Quiz() {
console.log("Quiz에서 handleRemove 실행"); console.log("Quiz에서 handleRemove 실행");
const problem = quiz.problems[index]; const problem = quiz.problems[index];
console.log(problem); console.log(problem);
removeProblem({problemId: problem._id}, {t: jwt.token}).then(data => { removeProblem({ problemId: problem._id }, { t: jwt.token }).then((data) => {
if (data.error) { if (data.error) {
console.log(data.error); console.log(data.error);
} else { } else {
console.log('deleted Problem:', data); console.log("deleted Problem:", data);
const list = [...quiz.problems] const list = [...quiz.problems];
list.splice(index, 1) list.splice(index, 1);
setQuiz({...quiz, problems: list}) setQuiz({ ...quiz, problems: list });
} }
}) });
}; };
return ( return (
<Container> <Container>
<h2 className="text-center">제목: {quiz.title}</h2> <h2 className="text-center">제목: {quiz.title}</h2>
<Row>
<Col md={4}>과목: {quiz?.course?.name}</Col>
<Col md={4}>시작: {quiz?.startAt}</Col>
<Col md={4}>끝: {quiz?.endAt}</Col>
</Row>
{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} />;
return ( return (
......
...@@ -22,10 +22,34 @@ const list = async (req, res) => { ...@@ -22,10 +22,34 @@ const list = async (req, res) => {
error: dbErrorHandler.getErrorMessage(error) error: dbErrorHandler.getErrorMessage(error)
}) })
} }
}
const read = (req, res) => {
return res.json(req.course)
}
const courseById = async (req, res, next, id) => {
// console.log('req.body in userById', req.body);
try {
let course = await Course.findById(id)
.exec()
if (!course) {
return res.status(400).json({
error: 'Course not found'
})
}
req.course = course
next()
} catch (error) {
return res.status(400).json({
error: 'Could not retrieve course'
})
}
} }
export default { export default {
create, create,
list, list,
read,
courseById,
} }
\ No newline at end of file
...@@ -8,9 +8,13 @@ const router = express.Router() ...@@ -8,9 +8,13 @@ const router = express.Router()
router.route('/api/courses') router.route('/api/courses')
.get(courseCtrl.list) .get(courseCtrl.list)
router.route('/api/courses/:courseId')
.get(courseCtrl.read)
router.route('/api/courses/by/:userId') router.route('/api/courses/by/:userId')
.post(authCtrl.requireSignin, authCtrl.hasAuthorization, userCtrl.isAdmin, courseCtrl.create) .post(authCtrl.requireSignin, authCtrl.hasAuthorization, userCtrl.isAdmin, courseCtrl.create)
router.param('userId', userCtrl.userById) router.param('userId', userCtrl.userById)
router.param('courseId', courseCtrl.courseById)
export default router export default router
\ No newline at end of file
...@@ -20,10 +20,11 @@ const ProblemSchema = new mongoose.Schema({ ...@@ -20,10 +20,11 @@ const ProblemSchema = new mongoose.Schema({
score: Number, //문제당 할당 점수 score: Number, //문제당 할당 점수
question: String, //질문 question: String, //질문
answers: [String], // 선택형 항목 answers: [String], // 선택형 항목
correct: { correct: String, // 정답
type: mongoose.Schema.Types.ObjectId, // correct: {
ref: 'Answer' // type: mongoose.Schema.Types.ObjectId,
}, // 정답; Answer Model 객체 // ref: 'Answer'
// }, // 정답; Answer Model 객체
}) })
export default mongoose.model('Problem', ProblemSchema) export default mongoose.model('Problem', ProblemSchema)
\ No newline at end of file
...@@ -3,10 +3,11 @@ import fs from 'fs' ...@@ -3,10 +3,11 @@ import fs from 'fs'
import dbErrorHandler from '../helpers/dbErrorHandler.js' import dbErrorHandler from '../helpers/dbErrorHandler.js'
import Problem from './problem.model.js' import Problem from './problem.model.js'
import Quiz from './quiz.model.js' import Quiz from './quiz.model.js'
import extend from 'lodash/extend.js'
const create = async (req, res) => { const create = async (req, res) => {
try { try {
const { title, problems } = req.body const { title, problems, startAt, endAt, course } = req.body
const quiz = new Quiz() const quiz = new Quiz()
// console.log('quiz in quiz.controller:', quiz); // console.log('quiz in quiz.controller:', quiz);
...@@ -22,6 +23,9 @@ const create = async (req, res) => { ...@@ -22,6 +23,9 @@ const create = async (req, res) => {
} }
quiz.title = title quiz.title = title
quiz.startAt = startAt
quiz.endAt = endAt
quiz.course = course
quiz.author = req.profile quiz.author = req.profile
// console.log('quiz in quiz.controller:', quiz); // console.log('quiz in quiz.controller:', quiz);
...@@ -89,10 +93,11 @@ const readProblem = async (req, res) => { ...@@ -89,10 +93,11 @@ const readProblem = async (req, res) => {
const updateProblem = async (req, res) => { const updateProblem = async (req, res) => {
try { try {
const problem = req.problem let problem = req.problem
console.log('req.body in updateProblem in quiz.controller', req.body); console.log('req.body in updateProblem in quiz.controller', req.body);
problem.question = req.body.question problem = extend(problem, req.body)
problem.answers = req.body.answers // problem.question = req.body.question
// problem.answers = req.body.answers
problem.updated = new Date() problem.updated = new Date()
console.log('updated problem in updateProblem in quiz.controller', problem); console.log('updated problem in updateProblem in quiz.controller', problem);
await problem.save() await problem.save()
...@@ -137,6 +142,7 @@ const quizById = async (req, res, next, id) => { ...@@ -137,6 +142,7 @@ const quizById = async (req, res, next, id) => {
const quiz = await Quiz.findById(id) const quiz = await Quiz.findById(id)
.populate('author', '_id name') .populate('author', '_id name')
.populate('problems') .populate('problems')
.populate('course', '_id name')
.exec() .exec()
if (!quiz) { if (!quiz) {
return res.status(400).json({ return res.status(400).json({
......
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