Widen peer review question range

This commit is contained in:
outisa
2026-10-06 00:58:47 +03:00
parent 1d2fe5bdd6
commit c6f7c8edeb
4 changed files with 164 additions and 6 deletions
+16 -2
View File
@@ -36,6 +36,11 @@ const validateAnswerSheet = (peerReview) => {
if (error) {
return error
}
} else if (question.type === 'radioOneliner') {
error = validateRadioOneliner(question)
if (error) {
return error
}
} else if (question.type === 'number') {
error = validateNumberAnswer(question)
if (error) {
@@ -66,11 +71,14 @@ const validatePeerReviewAnswer = (question) => {
}
const validateTextAnswer = (question) => {
if (question.optional) {
return null
}
if (question.answer.length === 0) {
return 'You must answer all questions'
}
if (question.answer.length < 30) {
return 'Text answers must be over 30 characters long.'
if (question.answer.length < 10) {
return 'Text answers must be over 10 characters long.'
}
if (question.answer.length > 50000) {
return 'Text answer must be less than 50000 characters.'
@@ -88,6 +96,12 @@ const validateRadioAnswer = (question) => {
return error
}
const validateRadioOneliner = (question) => {
if (isNil(question.answer)) {
return 'You must answer this question'
}
}
const validateNumberAnswer = (question) => {
if (isNil(question.answer)) {
return 'You must answer all questions'
@@ -128,6 +128,7 @@ const getQuestions = (answers) => {
return {
type: question.type,
questionHeader: question.questionHeader,
options: question.options ?? null,
}
})
}
@@ -163,6 +164,12 @@ const GroupAnswers = ({ answers, students }) => {
<RadioAnswer answers={answers} questionNumber={index} students={students} />
</Question>
)
} else if (question.type === 'radioOneliner') {
return (
<Question key={index} title={question.questionHeader}>
<RadioOneliner answers={answers} questionNumber={index} question={question} />
</Question>
)
} else {
return null
}
@@ -205,7 +212,7 @@ const TextNumberAnswer = ({ answers, questionNumber }) => {
<div className="padding-left-18">
{answers.map((member, index) => {
return (
<div className="text-number-answer-container" key={index}>
<div style={{ width: '75%' }} key={index}>
<p>
{`${member.student.first_names} ${member.student.last_name}`}
:&nbsp;
@@ -218,6 +225,40 @@ const TextNumberAnswer = ({ answers, questionNumber }) => {
)
}
const RadioOneliner = ({ answers, questionNumber, question }) => {
const options = question.options
return (
<div className="padding-left-18">
<Table size="small" className="radio-button-table">
<TableHead>
<TableRow>
<TableCell></TableCell>
{options.map((option) => (
<TableCell key={option}>{option}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{answers.map((answer, answerIndex) => {
return (
<TableRow key={answerIndex}>
<TableCell>{answer.student.last_name}</TableCell>
{options.map((_option, index) => {
return (
<TableCell key={`${answer.student.last_name}-${index}`}>
{answer.answer_sheet[questionNumber].answer === index ? 'x' : ''}
</TableCell>
)
})}
</TableRow>
)
})}
</TableBody>
</Table>
</div>
)
}
const RadioAnswer = ({ answers, questionNumber, students }) => {
const peers = answers.map((member) => {
return member.student.first_names + ' ' + member.student.last_name
@@ -106,6 +106,36 @@ const calculateAverageRating = (member, answers) => {
return ratings.length > 0 ? (sum / ratings.length).toFixed(2) : 'N/A'
}
const RadioOneLinerSimple = ({ answer, questionNumber, question }) => {
const options = question.options
return (
<div className="padding-left-18">
<Table size="small" className="radio-button-table">
<TableHead>
<TableRow>
<TableCell></TableCell>
{options.map((option) => (
<TableCell key={option}>{option}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>{answer.student.last_name}</TableCell>
{options.map((_option, index) => {
return (
<TableCell key={`${answer.student.last_name}-${index}`}>
{answer.answer_sheet[questionNumber].answer === index ? 'x' : ''}
</TableCell>
)
})}
</TableRow>
</TableBody>
</Table>
</div>
)
}
const StudentViewGroupAnswers = ({ answers }) => {
return (
<div className="padding-left-18 flex-column-72">
@@ -127,6 +157,15 @@ const StudentViewGroupAnswers = ({ answers }) => {
student={studentAnswer.student}
/>
)
} else if (question.type === 'radioOneliner') {
return (
<RadioOneLinerSimple
key={questionIndex}
answer={studentAnswer}
questionNumber={questionIndex}
question={question}
/>
)
} else if (question.type === 'peerReview') {
return (
<PeerReviewAnswer
@@ -141,9 +180,9 @@ const StudentViewGroupAnswers = ({ answers }) => {
)
} else {
return (
<div className="padding-left-18" key={questionIndex}>
<div style={{ width: '70%' }} key={questionIndex}>
<h3>{question.questionHeader}</h3>
<p className="padding-left-18">{question.answer}</p>
<p>{question.answer}</p>
</div>
)
}
+65 -1
View File
@@ -83,6 +83,17 @@ class PeerReview extends React.Component {
return peerAnswers
}
const initializeRadioOneliner = (question, questionId) => {
return {
type: 'radioOneliner',
id: questionId,
questionHeader: question.header,
options: question.options,
optional: question.optional ?? false,
answer: null,
}
}
const initializeNumberAnswer = (question, questionId) => {
return {
type: 'number',
@@ -97,6 +108,7 @@ class PeerReview extends React.Component {
type: 'text',
questionHeader: question.header,
id: questionId,
optional: question.optional ?? false,
answer: '',
}
}
@@ -121,6 +133,8 @@ class PeerReview extends React.Component {
return initializeProjectHours(question, questionID)
} else if (question.type === 'radio') {
return initializeRadioAnswer(question, questionID)
} else if (question.type === 'radioOneliner') {
return initializeRadioOneliner(question, questionID)
} else if (question.type === 'peerReview') {
return initializePeerReview(question, questionID)
} else if (question.type === 'text') {
@@ -273,6 +287,31 @@ const Question = ({ peers, question, questionId, answerSheet, updateAnswer, upda
</Table>
</div>
)
} else if (question.type === 'radioOneliner') {
let temp = question.options
if (question.options === undefined) {
temp = ['Kyllä', 'Ei']
}
return (
<div className="peer-review-box">
<h3 className="peer-review-box__h3">{question.header}</h3>
<Table size="small" className="peer-review-box__radio-button-table">
<TableHead>
<TableRow hover>
<OptionHeaders options={temp} />
</TableRow>
</TableHead>
<TableBody>
<QuestionRowOneLine
options={temp}
questionId={question.header}
answerSheet={answerSheet[questionId]}
/>
</TableBody>
</Table>
</div>
)
} else if (question.type === 'peerReview') {
return (
<div className="peer-review-box">
@@ -298,7 +337,7 @@ const Question = ({ peers, question, questionId, answerSheet, updateAnswer, upda
<TextField
value={answerSheet[questionId].answer}
rows="4"
style={{ width: 400 }}
style={{ width: '75%' }}
multiline
variant="outlined"
onChange={(e) => textFieldHandler(e.target.value, questionId, updateAnswer)}
@@ -410,6 +449,24 @@ const QuestionRow = ({ peerName, options, peerId, questionId, answerSheet }) =>
)
}
const QuestionRowOneLine = ({ options, questionId, answerSheet }) => {
return (
<TableRow hover className="peer-review-box__peer-row">
{options.map((buttonId, buttonNumber) => {
return (
<TableCell className="peer-review-box__radio-button" key={buttonId}>
<input
type="radio"
name={questionId.toString()}
onClick={() => radioSelectHandlerOneLine(buttonNumber, answerSheet)}
/>
</TableCell>
)
})}
</TableRow>
)
}
const peerReviewHandler = (peerId, value, questionId, updatePeerReview) => {
updatePeerReview(peerId, value, questionId)
}
@@ -422,6 +479,13 @@ const radioSelectHandler = (peerId, buttonId, answerSheet) => {
updateAnswers(peerId, buttonId, answerSheet)
}
const radioSelectHandlerOneLine = (buttonId, questionId) => {
updateOneliner(buttonId, questionId)
}
const updateOneliner = (buttonId, answerSheet) => {
answerSheet.answer = buttonId
}
const updateAnswers = (peerId, buttonId, answerSheet) => {
answerSheet.peers[peerId] = buttonId
}