diff --git a/staff/agustin-birman/api/handlers/index.js b/staff/agustin-birman/api/handlers/index.js index 053a8b561..7288082a0 100644 --- a/staff/agustin-birman/api/handlers/index.js +++ b/staff/agustin-birman/api/handlers/index.js @@ -15,8 +15,7 @@ import getExercisesHandler from './getExercisesHandler.js' import deleteExerciseHandler from './deleteExerciseHandler.js' import editExerciseHandler from './editExerciseHandler.js' -import submitAnswer from '../logic/submitAnswer.js' - +import submitAnswerHandler from './submitAnswerHandler.js' export { registerUserHandler, authenticateUserHandler, @@ -35,5 +34,5 @@ export { deleteExerciseHandler, editExerciseHandler, - submitAnswer + submitAnswerHandler } \ No newline at end of file diff --git a/staff/agustin-birman/api/handlers/submitAnswerHandler.js b/staff/agustin-birman/api/handlers/submitAnswerHandler.js index 0b27e63b5..5963191ac 100644 --- a/staff/agustin-birman/api/handlers/submitAnswerHandler.js +++ b/staff/agustin-birman/api/handlers/submitAnswerHandler.js @@ -1,21 +1,30 @@ -import logic from '../logic/index.js' import jwt from '../util/jsonwebtoken-promised.js' +import logic from '../logic/index.js' + +import { CredentialsError } from 'com/errors.js' + const { JWT_SECRET } = process.env export default (req, res, next) => { try { const token = req.headers.authorization.slice(7) - const { exerciseId, answer } = req.body jwt.verify(token, JWT_SECRET) - try { - logic.submitAnswer(userId, exerciseId, answer) - .then(() => res.status(201).json()) - .catch(error => next(error)) - } catch (error) { - next(error) - } + .then(payload => { + const { sub: userId } = payload + + const { exerciseId, answer } = req.body + + try { + logic.submitAnswer(userId, exerciseId, answer) + .then(() => res.status(201).json()) + .catch(error => next(error)) + } catch (error) { + next(error) + } + }) + .catch(error => next(new CredentialsError(error.message))) } catch (error) { next(error) } diff --git a/staff/agustin-birman/api/index.js b/staff/agustin-birman/api/index.js index ac032636f..c10f36ffe 100644 --- a/staff/agustin-birman/api/index.js +++ b/staff/agustin-birman/api/index.js @@ -17,7 +17,8 @@ import { deleteExerciseHandler, editActivityHandler, editExerciseHandler, - submitAnswer + + submitAnswerHandler } from './handlers/index.js' const { MONGODB_URL, PORT } = process.env @@ -61,7 +62,7 @@ mongoose.connect(MONGODB_URL) api.patch('/exercise/:exerciseId', jsonBodyParser, editExerciseHandler) - api.post('/answer', jsonBodyParser, submitAnswer) + api.post('/answer', jsonBodyParser, submitAnswerHandler) api.use(errorHandler) diff --git a/staff/agustin-birman/app/src/components/core/Button/index.jsx b/staff/agustin-birman/app/src/components/core/Button/index.jsx index ccc55d06c..e4afd7988 100644 --- a/staff/agustin-birman/app/src/components/core/Button/index.jsx +++ b/staff/agustin-birman/app/src/components/core/Button/index.jsx @@ -1,7 +1,7 @@ import './index.css' -function Button({ type, className, onClick, children }) { - return +function Button({ type, className, onClick, children, disabled }) { + return } export default Button \ No newline at end of file diff --git a/staff/agustin-birman/app/src/components/core/Input/index.jsx b/staff/agustin-birman/app/src/components/core/Input/index.jsx index 6230ad46a..a02663402 100644 --- a/staff/agustin-birman/app/src/components/core/Input/index.jsx +++ b/staff/agustin-birman/app/src/components/core/Input/index.jsx @@ -1,7 +1,16 @@ import './index.css' -function Input({ id, type, name, placeholder, value, checked, onChange }) { - return +function Input({ id, type, name, placeholder, value, checked, onChange, className, required }) { + return } export default Input \ No newline at end of file diff --git a/staff/agustin-birman/app/src/logic/index.js b/staff/agustin-birman/app/src/logic/index.js index 48c8ab68d..b7bdd2339 100644 --- a/staff/agustin-birman/app/src/logic/index.js +++ b/staff/agustin-birman/app/src/logic/index.js @@ -12,6 +12,7 @@ import editActivity from './editActivity' import getExercises from './getExercises' import deleteExercise from './deleteExercise' import editExercise from './editExercise' +import submitAnswer from './submitAnswer' const logic = { registerUser, @@ -27,7 +28,8 @@ const logic = { editActivity, getExercises, deleteExercise, - editExercise + editExercise, + submitAnswer } export default logic \ No newline at end of file diff --git a/staff/agustin-birman/app/src/logic/submitAnswer.js b/staff/agustin-birman/app/src/logic/submitAnswer.js new file mode 100644 index 000000000..1c761c9ce --- /dev/null +++ b/staff/agustin-birman/app/src/logic/submitAnswer.js @@ -0,0 +1,32 @@ +import errors, { SystemError } from "com/errors" +import validate from "com/validate" + +const submitAnswer = (exerciseId, answer) => { + validate.id(exerciseId, 'exerciseId') + validate.text(answer, 'answer') + + return fetch(`${import.meta.env.VITE_API_URL}/answer`, { + method: 'POST', + headers: { + Authorization: `Bearer ${sessionStorage.token}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ exerciseId, answer }) + }) + .catch(() => { throw new SystemError('server error') }) + .then(response => { + if (response.status === 201) + return + + return response.json() + .catch(() => { throw new SystemError('server error') }) + .then(body => { + const { error, message } = body + + const constructor = errors[error] + + throw new constructor(message) + }) + }) +} +export default submitAnswer diff --git a/staff/agustin-birman/app/src/views/components/DoActivity/index.css b/staff/agustin-birman/app/src/views/components/DoActivity/index.css new file mode 100644 index 000000000..213c8ff40 --- /dev/null +++ b/staff/agustin-birman/app/src/views/components/DoActivity/index.css @@ -0,0 +1,9 @@ +.ExerciseContainer{ + display:inline-flex; + align-items: center; + white-space: nowrap; +} + +.ExerciseInput{ + width: 6rem; +} \ No newline at end of file diff --git a/staff/agustin-birman/app/src/views/components/DoActivity/index.jsx b/staff/agustin-birman/app/src/views/components/DoActivity/index.jsx index a2d9aaddb..f605c7e46 100644 --- a/staff/agustin-birman/app/src/views/components/DoActivity/index.jsx +++ b/staff/agustin-birman/app/src/views/components/DoActivity/index.jsx @@ -1,21 +1,33 @@ -import { useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import View from '../../../components/library/View'; import { useEffect, useState } from 'react'; import Heading from '../../../components/core/Heading'; import Text from '../../../components/core/Text'; import logic from '../../../logic'; import Input from '../../../components/core/Input'; +import Button from '../../../components/core/Button'; +import './index.css' let SENTENCE_REGEX = /^(.*?)\s*\(.*?\)\s*(.*?)$/ function DoActivity() { const [exercises, setExercises] = useState([]) + const [answer, setAnswer] = useState('') + const [currentPage, setCurrentPage] = useState(1) + const pageSize = 1 const { activityId } = useParams() + const navigate = useNavigate() + + const isLastPage = currentPage === Math.ceil(exercises.length / pageSize) useEffect(() => { loadExercises() }, []) + useEffect(() => { + setAnswer('') + }, [currentPage]) + const loadExercises = () => { try { logic.getExercises(activityId) @@ -32,13 +44,37 @@ function DoActivity() { } } - const handleSubmittedAnswer = () => { - //TODO + const handleSubmittedAnswer = (exerciseId) => { + try { + logic.submitAnswer(exerciseId, answer) + .then(() => { + handleChangePage(currentPage + 1) + + if (isLastPage) + navigate('/') + }) + .catch(error => { + console.error(error) + + alert(error.message) //TODO hacer un alert mejor + }) + } catch (error) { + console.error(error) + + alert(error.message) + } + } + + const handleChangePage = newPage => { + setCurrentPage(newPage) } + const currentExercises = exercises.slice((currentPage - 1) * pageSize, currentPage * pageSize); + + return ( - {exercises.map(exercise => { + {currentExercises.map(exercise => { let beforeParentheses = '' let afterParentheses = '' @@ -51,12 +87,23 @@ function DoActivity() { return ( {exercise.index + 1} Exercise - {beforeParentheses} - - {afterParentheses} +
+ {beforeParentheses} + { setAnswer(e.target.value) }} /> + {afterParentheses} +
+ + {isLastPage === false + ? + : } + + Page {currentPage} of {Math.ceil(exercises.length / pageSize)}
) - } - )} + })} + {/*
+ + +
*/}
) }