Commit 8a0556fb authored by Yoon, Daeki's avatar Yoon, Daeki 😅
Browse files

Problem Edit 수정중

parent f21119fa
......@@ -3,9 +3,11 @@ import { Route, Switch } from "react-router-dom";
import Signin from "./auth/Signin";
import Home from "./core/Home";
import Menu from "./core/Menu";
import NewQuiz from './quiz/NewQuiz'
import Quiz from './quiz/Quiz'
import Signup from "./user/Signup"
import NewQuiz from "./quiz/NewQuiz";
import Quiz from "./quiz/Quiz";
import Signup from "./user/Signup";
import Quizzes from "./quiz/Quizzes";
import EditProblem from "./quiz/EditProblem";
function MainRouter() {
return (
......@@ -13,7 +15,6 @@ function MainRouter() {
<Menu />
<Switch>
<Route exact path="/">
{/* {console.log('Home 안에서 ...')} */}
<Home />
</Route>
<Route path="/signin">
......@@ -22,17 +23,21 @@ function MainRouter() {
<Route path="/signup">
<Signup />
</Route>
<Route path='/quiz/new'>
<Route path="/quiz/new">
<NewQuiz />
</Route>
<Route path="/quiz/:quizId">
<Route path="/quiz/by/:userId">
<Quizzes />
</Route>
<Route path="/quiz/problem/edit/:problemId">
<EditProblem />
</Route>
{/* 아래 "/quiz/:quizId" 는 "/quiz/by/:userId"와 순서 바뀌면 안된다. */}
<Route path="/quiz/:quizId">
<Quiz />
</Route>
</Switch>
</div>
// <BrowserRouter>
// {console.log('BrowserRoter 안에서 ...')}
// </BrowserRouter>
);
}
......
......@@ -20,6 +20,7 @@ function Menu() {
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Nav.Link href="/">Home</Nav.Link>
{authUser && <Nav.Link as={Link} to={`/quiz/by/${authUser.user._id}`}>Quizzes</Nav.Link>}
<Nav.Link href="/quiz/new">New Quiz</Nav.Link>
<NavDropdown title="Dropdown" id="basic-nav-dropdown">
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
......
import React from 'react'
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
function EditProblem() {
return (
<div>
</div>
)
const { problemId } = useParams();
const [problem, setProblem] = useState({});
useEffect(() => {
return () => {};
}, [problemId]);
return <div>문제를 수정합니다. id: {problemId}</div>;
}
export default EditProblem
export default EditProblem;
......@@ -6,11 +6,18 @@ import NewProblem from "./NewProblem";
import Problem from "./Problem";
function NewQuiz() {
const [title, setTitle] = useState('')
const [problems, setProblems] = useState([])
const jwt = authHelpers.isAuthenticated();
const handleChange = (event) => {
const { name, value } = event.target
if (name === 'title') {
setTitle(value)
}
}
const addProblem = (problem) => {
console.log(problem)
setProblems([...problems, problem])
......@@ -20,6 +27,7 @@ function NewQuiz() {
event.preventDefault();
const quizData = {
title,
problems
}
......@@ -37,11 +45,13 @@ function NewQuiz() {
return (
<div>
<h1 className="text-center">
Quiz List
New Quiz
</h1>
<label htmlFor='title'>Title</label>
<input id='title' name='title' onChange={handleChange} placeholder='Title' />
{
problems.map((problem, index) => {
return <Problem key={index} problem={problem} />
return <Problem key={index} problem={problem} number={index+1} />
})
}
<NewProblem addProblem={addProblem} />
......
import React from "react";
import {Link} from 'react-router-dom';
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
function Problem({ problem, number }) {
function Problem({ problem, number, onUpdate, onRemove }) {
return (
<Card>
<Card.Body>
<Card.Title>
{number}번. {problem.question}
{number+1}번. {problem.question}
</Card.Title>
Answers
{problem.answers.map((answer, index) => {
return <Card.Text key={index}>{answer}</Card.Text>;
})}
<Button>수정</Button>
<Button>삭제</Button>
<Link to={`/quiz/problem/edit/${problem._id}`}>
<Button onClick={(event) => onUpdate(number)}>수정</Button>
</Link>
<Button onClick={onRemove}>삭제</Button>
</Card.Body>
</Card>
);
......
......@@ -26,10 +26,20 @@ function Quiz() {
};
}, [quizId]);
const handleUpdate = (index) => {
console.log(`Quiz에서 handleUpdate ${index}번 실행`);
console.log(`Quiz에서 handleUpdate ${JSON.stringify(quiz.problems[index])}`);
}
const handleRemove = () => {
console.log('Quiz에서 handleRemove 실행');
}
return (
<div>
<h2>제목: {quiz.title}</h2>
{quiz.problems?.map((problem, i) => {
return <Problem key={i} problem={problem} number={i+1} />;
return <Problem key={i} problem={problem} number={i} onUpdate={handleUpdate} onRemove={handleRemove} />;
})}
</div>
);
......
import React, { useEffect, useState } from "react";
import Card from "react-bootstrap/Card";
import { Link, useParams } from "react-router-dom";
import authHelpers from "../auth/auth-helpers";
import { listByUserId } from "./api-quiz";
function Quizzes() {
const { userId } = useParams();
const [quizzes, setQuizzes] = useState([]);
const jwt = authHelpers.isAuthenticated();
useEffect(() => {
const abortController = new AbortController();
const signal = abortController.signal;
listByUserId({ userId: userId }, { t: jwt.token }, signal).then((data) => {
if (data.error) {
console.log(data.error);
} else {
// console.log(data);
setQuizzes(data);
}
});
return () => {
abortController.abort();
};
}, [userId]);
return (
<div>
All Quizzes Here
{quizzes.map((quiz, i) => {
return (
<Link key={i} to={`/quiz/${quiz._id}`}>
<Card>
<Card.Body>
<Card.Title>제목: {quiz.title}</Card.Title>
<Card.Text>만든날: {quiz.created}</Card.Text>
</Card.Body>
</Card>
</Link>
);
})}
</div>
);
}
export default Quizzes;
const create = async (params, credentials, quiz) => {
try {
let response = await fetch('/api/quiz/' + params.userId, {
let response = await fetch('/api/quiz/by/' + params.userId, {
method: 'POST',
headers: {
'Accept': 'application/json',
......@@ -33,7 +33,24 @@ const read = async (params, credentials, signal) => {
}
}
const listByUserId = async (params, credentials, signal) => {
try {
let response = await fetch('/api/quiz/by/' + params.userId, {
method: 'GET',
signal: signal,
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + credentials.t,
},
})
return await response.json()
} catch (error) {
console.log(error)
}
}
export {
create,
read,
listByUserId,
}
\ No newline at end of file
import React, { useState } from 'react'
import Button from 'react-bootstrap/Button'
import Form from 'react-bootstrap/Form'
import React, { useState } from "react";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import Modal from 'react-bootstrap/Modal'
import {Link} from 'react-router-dom'
import { create } from "./api-user";
function Signup() {
const [values, setValues] = useState({
name: '',
password: '',
email: '',
name: "",
password: "",
email: "",
open: false,
error: '',
})
error: "",
});
const handleChange = (name) => (event) => {
const { value } = event.target;
setValues({ ...values, [name]: value });
};
const handleSubmit = (event) => {
// console.log(values);
const user = {
name: values.name || undefined,
email: values.email || undefined,
password: values.password || undefined,
};
create(user).then((data) => {
if (data.error) {
console.log(data.error);
setValues({ ...values, error: data.error });
} else {
setValues({ ...values, error: "", open: true });
}
});
};
return (
<div>
<Form>
<Form.Group>
<Form.Label>Name</Form.Label>
<Form.Control type='text' placeholder='Name' />
<Form.Control
type="text"
placeholder="Name"
onChange={handleChange('name')}
/>
</Form.Group>
<Form.Group>
<Form.Label>Password</Form.Label>
<Form.Control type='password' placeholder='Password' />
<Form.Control
type="password"
placeholder="Password"
onChange={handleChange('password')}
/>
</Form.Group>
<Form.Group>
<Form.Label>Email</Form.Label>
<Form.Control type='email' placeholder='Email' />
<Form.Control
type="email"
placeholder="Email"
onChange={handleChange('email')}
/>
</Form.Group>
<Button>확인</Button>
<Button onClick={handleSubmit}>확인</Button>
</Form>
<Modal show={values.open}>
<Modal.Header>
<Modal.Title>New Account</Modal.Title>
</Modal.Header>
<Modal.Body>
New Account successfully created.
</Modal.Body>
<Modal.Footer>
<Link to='/signin'>
<Button>Sign in</Button>
</Link>
</Modal.Footer>
</Modal>
</div>
)
);
}
export default Signup
export default Signup;
const getErrorMessage = (err) => {
let message = ''
// console.log('error in getErrorMessage', err)
if (err.code) {
switch (err.code) {
case 11000:
case 11001:
message = getUniqueErrorMessage(err)
break
default:
message = 'Something went wrong'
}
} else if (err._message) {
message = err._message
}
return message
}
const getUniqueErrorMessage = (err) => {
let output
// console.log('error in getUniqueErrormessage', err)
try {
let fieldName = err.message.substring(err.message.lastIndexOf('.$') + 2,
err.message.lastIndexOf('_1'))
output = fieldName.charAt(0).toUpperCase() + fieldName.slice(1) + ' already exists'
} catch (error) {
output = 'Unique field already exists'
}
return output
}
export default { getErrorMessage }
\ No newline at end of file
import mongoose from 'mongoose'
const ProblemSchema = new mongoose.Schema({
author: {
type: mongoose.SchemaTypes.ObjectId,
ref: 'User'
},
type: String, // 객관식, 주관식 single/multiple choice
created: {
type: Date,
......
import formidable from 'formidable'
import fs from 'fs'
import dbErrorHandler from '../helpers/dbErrorHandler.js'
import Problem from './problem.model.js'
import Quiz from './quiz.model.js'
const create = async (req, res) => {
try {
const { problems } = req.body
const { title, problems } = req.body
const quiz = new Quiz()
// console.log('quiz in quiz.controller:', quiz);
......@@ -14,10 +15,12 @@ const create = async (req, res) => {
// console.log('problem in quiz.controller:', problem);
const p = new Problem(problem)
// console.log('problem in quiz.controller:', p);
p.author = req.profile
await p.save()
quiz.problems.push(p._id)
}
quiz.title = title
quiz.author = req.profile
// console.log('quiz in quiz.controller:', quiz);
......@@ -42,11 +45,39 @@ const isAuthor = (req, res, next) => {
next()
}
const isProblemAuthor = (req, res, next) => {
const isProblemAuthor = req.auth && req.problem && req.auth._id == req.problem.author._id
if (!isProblemAuthor) {
return res.status(403).json({
error: 'User is not an author of the problem'
})
}
next()
}
const read = async (req, res) => {
let quiz = req.quiz
res.json(quiz)
}
const readProblem = async (req, res) => {
let problem = req.problem
res.json(problem)
}
const listByUserId = async (req, res) => {
try {
const authorId = req.profile._id
const quizzes = await Quiz.find({author: authorId}).exec()
// console.log('quizzes in listByUserId:', quizzes);
res.json(quizzes)
} catch (error) {
return res.status(400).json({
error: dbErrorHandler.getErrorMessage(error)
})
}
}
const quizById = async (req, res, next, id) => {
try {
const quiz = await Quiz.findById(id)
......@@ -67,9 +98,32 @@ const quizById = async (req, res, next, id) => {
}
}
const problemById = async (req, res, next, id) => {
try {
const problem = await Problem.findById(id)
.populate('author', '_id name')
.exec()
if (!problem) {
return res.status(400).json({
error: 'Problem not found'
})
}
req.problem = problem
next()
} catch (error) {
return res.status(400).json({
error: dbErrorHandler.getErrorMessage(error)
})
}
}
export default {
create,
read,
readProblem,
isAuthor,
isProblemAuthor,
listByUserId,
quizById,
problemById,
}
\ No newline at end of file
......@@ -5,13 +5,18 @@ import quizCtrl from './quiz.controller.js'
const router = express.Router()
router.route('/api/quiz/:userId')
router.route('/api/quiz/by/:userId')
.post(authCtrl.requireSignin, authCtrl.hasAuthorization, userCtrl.isInstructor, quizCtrl.create)
.get(authCtrl.requireSignin, authCtrl.hasAuthorization, quizCtrl.listByUserId)
router.route('/api/quiz/:quizId')
.get(authCtrl.requireSignin, quizCtrl.isAuthor, quizCtrl.read)
router.route('/api/quiz/problem/:problemId')
.get(authCtrl.requireSignin, quizCtrl.isProblemAuthor, quizCtrl.readProblem)
router.param('userId', userCtrl.userById)
router.param('quizId', quizCtrl.quizById)
router.param('problemId', quizCtrl.problemById)
export default router
\ No newline at end of file
......@@ -2,9 +2,11 @@ import User from './user.model.js'
import formidable from 'formidable'
import extend from 'lodash/extend.js'
import fs from 'fs'
import dbErrorHandler from '../helpers/dbErrorHandler.js'
const create = async (req, res) => {
const user = new User(req.body)
// console.log('user in user.controll:', req.body);
try {
await user.save()
return res.json({
......@@ -12,7 +14,7 @@ const create = async (req, res) => {
})
} catch (error) {
return res.status(400).json({
error: 'User creation error'
error: dbErrorHandler.getErrorMessage(error)
})
}
}
......
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