diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f6cd364b3ca5bac9b7d973f60b596f5887130845 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# 퀴즈 출제 페이지 + +## 실행 방법 + +1. 두 개의 터미널을 엽니다. +1. 한쪽 터미널(서버)에서는, 프로젝트 디렉토리에서 `yarn install`을 실행합니다.(이것은 패키지가 변경될 때마다 실행합니다.) +1. 다른쪽 터미널(클라이언트)에서는, `cd src\client` 해서 `yarn install` 을 실행합니다.(이것은 패키지가 변경될 때마다 실행합니다.) +1. 서버 터미널에서 `yarn dev`를 실행합니다. +1. 클라이언트 터미널에서 `yarn start` 를 실행합니다. +1. 코드를 수정합니다. diff --git a/src/client/src/quiz/EditableProblem.jsx b/src/client/src/quiz/EditableProblem.jsx index 6b05102fdcbf458ee71502eb42b9d601d3399881..ccbe227cfde2224aec6c3a0522398dcd565ad198 100644 --- a/src/client/src/quiz/EditableProblem.jsx +++ b/src/client/src/quiz/EditableProblem.jsx @@ -1,15 +1,17 @@ import React, { useState } from "react"; -import { Link } from "react-router-dom"; import Card from "react-bootstrap/Card"; import Form from "react-bootstrap/Form"; import Col from "react-bootstrap/Col"; 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 { problem, number, + handleCorrect, removeAnswer, addAnswer, handleQuestion, @@ -28,9 +30,18 @@ const EditableForm = (props) => { /> Answers + {/* */} {problem.answers.map((answer, index) => { return ( + + + { ); })} + {/* */} @@ -65,6 +77,7 @@ const CardForm = (props) => { {problem.answers.map((answer, index) => { return {answer}; })} + 정답: {+problem.correct + 1} @@ -80,6 +93,12 @@ function EditableProblem({ problem, number, onUpdate, onRemove }) { setEditable(!editable); }; + const handleCorrect = (event) => { + const { name, value } = event.target; + console.log("name:", name, "value:", value); + setProblemEdit({...problemEdit, correct: value}) + }; + const handleCancel = (event) => { // const { name, value } = event.target; // console.log(name, value); @@ -111,8 +130,8 @@ function EditableProblem({ problem, number, onUpdate, onRemove }) { }; const handleSave = (event, index) => { - onUpdate(index, problemEdit) - setEditable(!editable) + onUpdate(index, problemEdit); + setEditable(!editable); }; return ( @@ -121,6 +140,7 @@ function EditableProblem({ problem, number, onUpdate, onRemove }) { { + const { name, value } = event.target; + console.log("name:", name, "value:", value); + setCorrect(value) + }; + const handleQuestion = (event) => { setQuestion(event.target.value); }; @@ -42,6 +49,7 @@ function NewProblem({ addProblem }) { question, answers, quiz: quizId, + correct: correct, }; createProblem({ userId: jwt.user._id }, { t: jwt.token }, problem).then( (data) => { @@ -50,7 +58,7 @@ function NewProblem({ addProblem }) { } else { setQuestion(data.question); setAnswers(data.answers); - setShow(true) + setShow(true); } } ); @@ -73,6 +81,14 @@ function NewProblem({ addProblem }) { {answers.map((answer, index) => { return ( + + + New Problem - - Problem successfully created. - + Problem successfully created. diff --git a/src/client/src/quiz/NewQuiz.jsx b/src/client/src/quiz/NewQuiz.jsx index 8131c28c0c7899a951f335804417c506f4106f8e..5df71f43a99d8c567dc89ef568407cbb999558ec 100644 --- a/src/client/src/quiz/NewQuiz.jsx +++ b/src/client/src/quiz/NewQuiz.jsx @@ -15,7 +15,7 @@ import { list } from "../course/api-course"; function NewQuiz() { const [problems, setProblems] = useState([]); const [quiz, setQuiz] = useState({}); - const [courses, setCourses] = useState([]) + const [courses, setCourses] = useState([]); const [values, setValues] = useState({ title: "", problems: [], @@ -28,26 +28,26 @@ function NewQuiz() { const jwt = authHelpers.isAuthenticated(); useEffect(() => { - const abortController = new AbortController() - const signal = abortController.signal - list(signal).then(data => { + const abortController = new AbortController(); + const signal = abortController.signal; + list(signal).then((data) => { if (data.error) { console.log(data.error); } else { console.log(data); - setCourses(data) + setCourses(data); } - }) + }); return () => { - abortController.abort() - } - }, []) + abortController.abort(); + }; + }, []); const handleChange = (event) => { const { name, value } = event.target; console.log("name", name, "value", value); console.log("values:", values); - + if (name === "course") { console.log(`${name}: ${courses[value]._id}`); setValues({ ...values, [name]: courses[value]._id }); @@ -59,16 +59,16 @@ function NewQuiz() { const handleUpdate = (index) => { console.log(`Quiz에서 handleUpdate ${index}번 실행`); // console.log(`Quiz에서 handleUpdate ${JSON.stringify(quiz.problems[index])}`); - } + }; const handleRemove = (index) => { - console.log('handleRemove 실행'); - const problem = problems[index] + console.log("handleRemove 실행"); + const problem = problems[index]; console.log(problem); - const list = [...problems] - list.splice(index, 1) - setProblems(list) - } + const list = [...problems]; + list.splice(index, 1); + setProblems(list); + }; const addProblem = (problem) => { console.log(problem); @@ -88,17 +88,17 @@ function NewQuiz() { console.log(quizData); - // create({ userId: jwt.user._id }, { t: jwt.token }, quizData).then( - // (data) => { - // if (data.error) { - // console.log(data.error); - // } else { - // console.log(data); - // setQuiz(data); - // setShow(true); - // } - // } - // ); + create({ userId: jwt.user._id }, { t: jwt.token }, quizData).then( + (data) => { + if (data.error) { + console.log(data.error); + } else { + console.log(data); + setQuiz(data); + setValues({ ...values, show: true }); + } + } + ); }; return ( @@ -124,7 +124,9 @@ function NewQuiz() { onChange={handleChange} > {courses.map((course, i) => ( - + ))} @@ -149,7 +151,15 @@ function NewQuiz() { {problems.map((problem, index) => { - return ; + return ( + + ); })} @@ -173,9 +183,9 @@ function NewQuiz() { export default NewQuiz; function NewQuizProblem({ addProblem }) { - // const { quizId } = useParams(); const [answers, setAnswers] = useState([""]); const [question, setQuestion] = useState(""); + const [correct, setCorrect] = useState() const addAnswer = () => { setAnswers([...answers, ""]); @@ -194,18 +204,23 @@ function NewQuizProblem({ addProblem }) { setAnswers(list); }; + const handleCorrect = (event) => { + const { name, value } = event.target; + console.log("name:", name, "value:", value); + setCorrect(value) + }; + const handleQuestion = (event) => { setQuestion(event.target.value); }; const clickAdd = (event) => { event.preventDefault(); - addProblem({ question, answers }); + addProblem({ question, answers, correct }); }; return ( <> - {/*
*/} Question { return ( + + + 문제 추가 - {/* */} ); } diff --git a/src/client/src/quiz/Quiz.jsx b/src/client/src/quiz/Quiz.jsx index 2f01874051b900deab5be31c917c47c2ff2160dc..69d312f106d853972220f2f2cca43f4566cdc538 100644 --- a/src/client/src/quiz/Quiz.jsx +++ b/src/client/src/quiz/Quiz.jsx @@ -2,10 +2,11 @@ import React, { useState, useEffect } from "react"; import { Link, useParams } from "react-router-dom"; import { read, removeProblem, updateProblem } from "./api-quiz"; import auth from "../auth/auth-helpers"; -import Problem from "./Problem"; import Button from "react-bootstrap/Button"; import EditableProblem from "./EditableProblem"; import Container from "react-bootstrap/Container"; +import Row from "react-bootstrap/Row"; +import Col from "react-bootstrap/Col"; function Quiz() { const { quizId } = useParams(); @@ -21,6 +22,7 @@ function Quiz() { if (data.error) { console.log(data.error); } else { + console.log(data); setQuiz(data); } }); @@ -43,10 +45,10 @@ function Quiz() { console.log(data.error); } else { console.log(data); - const list = [...quiz.problems] - list[index] = data + const list = [...quiz.problems]; + list[index] = data; console.log(list); - setQuiz({...quiz, problems: list}) + setQuiz({ ...quiz, problems: list }); } } ); @@ -56,21 +58,26 @@ function Quiz() { console.log("Quiz에서 handleRemove 실행"); const problem = quiz.problems[index]; console.log(problem); - removeProblem({problemId: problem._id}, {t: jwt.token}).then(data => { + 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}) + console.log("deleted Problem:", data); + const list = [...quiz.problems]; + list.splice(index, 1); + setQuiz({ ...quiz, problems: list }); } - }) + }); }; return (

제목: {quiz.title}

+ + 과목: {quiz?.course?.name} + 시작: {quiz?.startAt} + 끝: {quiz?.endAt} + {quiz.problems?.map((problem, i) => { // return ; return ( diff --git a/src/server/course/course.controller.js b/src/server/course/course.controller.js index 037d19a5299638aacd1b4c021b25919f87de3024..98dabc1029725a4e48911c1b71f7d153b509d4b1 100644 --- a/src/server/course/course.controller.js +++ b/src/server/course/course.controller.js @@ -22,10 +22,34 @@ const list = async (req, res) => { 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 { create, list, + read, + courseById, } \ No newline at end of file diff --git a/src/server/course/course.routes.js b/src/server/course/course.routes.js index cb6f783dbd86902bdb443bcfadb911b5c16018a9..dc05eccbe77f55620de9586db79638c144f06081 100644 --- a/src/server/course/course.routes.js +++ b/src/server/course/course.routes.js @@ -8,9 +8,13 @@ const router = express.Router() router.route('/api/courses') .get(courseCtrl.list) +router.route('/api/courses/:courseId') + .get(courseCtrl.read) + router.route('/api/courses/by/:userId') .post(authCtrl.requireSignin, authCtrl.hasAuthorization, userCtrl.isAdmin, courseCtrl.create) router.param('userId', userCtrl.userById) +router.param('courseId', courseCtrl.courseById) export default router \ No newline at end of file diff --git a/src/server/quiz/problem.model.js b/src/server/quiz/problem.model.js index 7e0ece7ebdbfc1eec3c672dd9295c17b16230c63..75b923578d7f19ba23b5688b969bac7ff896f1f4 100644 --- a/src/server/quiz/problem.model.js +++ b/src/server/quiz/problem.model.js @@ -20,10 +20,11 @@ const ProblemSchema = new mongoose.Schema({ score: Number, //문제당 할당 점수 question: String, //질문 answers: [String], // 선택형 항목 - correct: { - type: mongoose.Schema.Types.ObjectId, - ref: 'Answer' - }, // 정답; Answer Model 객체 + correct: String, // 정답 + // correct: { + // type: mongoose.Schema.Types.ObjectId, + // ref: 'Answer' + // }, // 정답; Answer Model 객체 }) export default mongoose.model('Problem', ProblemSchema) \ No newline at end of file diff --git a/src/server/quiz/quiz.controller.js b/src/server/quiz/quiz.controller.js index 4b3a2dd4c7103f3d756b5ee080bb152dec9a3931..3d4f39bc384fc17f82c25c52c5ef1603f5efe872 100644 --- a/src/server/quiz/quiz.controller.js +++ b/src/server/quiz/quiz.controller.js @@ -3,10 +3,11 @@ import fs from 'fs' import dbErrorHandler from '../helpers/dbErrorHandler.js' import Problem from './problem.model.js' import Quiz from './quiz.model.js' +import extend from 'lodash/extend.js' const create = async (req, res) => { try { - const { title, problems } = req.body + const { title, problems, startAt, endAt, course } = req.body const quiz = new Quiz() // console.log('quiz in quiz.controller:', quiz); @@ -22,6 +23,9 @@ const create = async (req, res) => { } quiz.title = title + quiz.startAt = startAt + quiz.endAt = endAt + quiz.course = course quiz.author = req.profile // console.log('quiz in quiz.controller:', quiz); @@ -89,10 +93,11 @@ const readProblem = async (req, res) => { const updateProblem = async (req, res) => { try { - const problem = req.problem + let 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 = extend(problem, 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() @@ -137,6 +142,7 @@ const quizById = async (req, res, next, id) => { const quiz = await Quiz.findById(id) .populate('author', '_id name') .populate('problems') + .populate('course', '_id name') .exec() if (!quiz) { return res.status(400).json({