Skip to content

Commit

Permalink
add view and logic to do execericises b00tc4mp#182
Browse files Browse the repository at this point in the history
  • Loading branch information
AgusBirman committed Aug 8, 2024
1 parent b64af8e commit b1cc548
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 28 deletions.
5 changes: 2 additions & 3 deletions staff/agustin-birman/api/handlers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -35,5 +34,5 @@ export {
deleteExerciseHandler,
editExerciseHandler,

submitAnswer
submitAnswerHandler
}
27 changes: 18 additions & 9 deletions staff/agustin-birman/api/handlers/submitAnswerHandler.js
Original file line number Diff line number Diff line change
@@ -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)
}
Expand Down
5 changes: 3 additions & 2 deletions staff/agustin-birman/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {
deleteExerciseHandler,
editActivityHandler,
editExerciseHandler,
submitAnswer

submitAnswerHandler
} from './handlers/index.js'

const { MONGODB_URL, PORT } = process.env
Expand Down Expand Up @@ -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)

Expand Down
4 changes: 2 additions & 2 deletions staff/agustin-birman/app/src/components/core/Button/index.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './index.css'

function Button({ type, className, onClick, children }) {
return <button className={`Button ${className ? className : ''}`} type={type} onClick={onClick}>{children}</button>
function Button({ type, className, onClick, children, disabled }) {
return <button className={`Button ${className ? className : ''}`} type={type} onClick={onClick} disabled={disabled}>{children} </button>
}

export default Button
13 changes: 11 additions & 2 deletions staff/agustin-birman/app/src/components/core/Input/index.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import './index.css'

function Input({ id, type, name, placeholder, value, checked, onChange }) {
return <input className='Input' id={id} type={type} name={name} placeholder={placeholder} value={value} checked={checked} onChange={onChange} />
function Input({ id, type, name, placeholder, value, checked, onChange, className, required }) {
return <input
className={`Input ${className ? className : ''}`}
id={id}
type={type}
name={name}
placeholder={placeholder}
value={value}
checked={checked}
onChange={onChange}
required={required} />
}

export default Input
4 changes: 3 additions & 1 deletion staff/agustin-birman/app/src/logic/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -27,7 +28,8 @@ const logic = {
editActivity,
getExercises,
deleteExercise,
editExercise
editExercise,
submitAnswer
}

export default logic
32 changes: 32 additions & 0 deletions staff/agustin-birman/app/src/logic/submitAnswer.js
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.ExerciseContainer{
display:inline-flex;
align-items: center;
white-space: nowrap;
}

.ExerciseInput{
width: 6rem;
}
65 changes: 56 additions & 9 deletions staff/agustin-birman/app/src/views/components/DoActivity/index.jsx
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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 (<View>
<Heading level='2'></Heading>
{exercises.map(exercise => {
{currentExercises.map(exercise => {
let beforeParentheses = ''
let afterParentheses = ''

Expand All @@ -51,12 +87,23 @@ function DoActivity() {

return (<View key={exercise.index}>
<Text>{exercise.index + 1} Exercise</Text>
<Text>{beforeParentheses}</Text>
<Input />
<Text>{afterParentheses}</Text>
<div className='ExerciseContainer'>
<Text>{beforeParentheses}</Text>
<Input className='ExerciseInput' onChange={(e) => { setAnswer(e.target.value) }} />
<Text>{afterParentheses}</Text>
</div>

{isLastPage === false
? <Button onClick={() => handleSubmittedAnswer(exercise._id)}>Next Exercise</Button>
: <Button onClick={() => handleSubmittedAnswer(exercise._id)}>Finish</Button>}

<Text>Page {currentPage} of {Math.ceil(exercises.length / pageSize)}</Text>
</View>)
}
)}
})}
{/* <div className='PaginationControls'>
<Button onClick={() => handleChangePage(currentPage - 1)} disabled={currentPage === 1}>Previous</Button>
<Button onClick={() => handleChangePage(currentPage + 1)} disabled={currentPage === Math.ceil(exercises.length / pageSize)}>Next</Button>
</div> */}
</View >
)
}
Expand Down

0 comments on commit b1cc548

Please sign in to comment.