UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

180 lines (156 loc) 5.31 kB
/** @jsx jsx */ import {Component} from 'react' import PropTypes from 'prop-types' import {RadioInput} from '@instructure/ui-radio-input' import {jsx} from '@instructure/emotion' import t from '@instructure/quiz-i18n/format-message' import {ItemBodyWrapper} from '@instructure/quiz-rce/components/ItemBodyWrapper/index' import {FeedbackWrapper, NoResponse} from '@instructure/quiz-results-feedback' import generateStyle from './styles' import generateComponentTheme from './theme' import {withStyleOverrides} from '@instructure/quiz-common/util/withStyleOverrides' const TRUE_CHOICE = 'trueChoice' const FALSE_CHOICE = 'falseChoice' /** --- category: TrueFalse --- True False Result component ```jsx_example <SettingsSwitcher locales={LOCALES}> <TrueFalseResult itemBody="The sun is a star" itemId="12" interactionData={{ trueChoice: 'True', falseChoice: 'False' }} scoredData={{ value: { true: { resultScore: 1, userResponded: true }, false: { resultScore: 0, userResponded: false } }} } /> </SettingsSwitcher> ``` **/ @withStyleOverrides(generateStyle, generateComponentTheme) export default class TrueFalseResult extends Component { static displayName = 'TrueFalseResult' static componentId = `Quizzes${this.displayName}` static propTypes = { interactionData: PropTypes.shape({ trueChoice: PropTypes.string, falseChoice: PropTypes.string, }).isRequired, itemBody: PropTypes.string.isRequired, itemId: PropTypes.string, scoredData: PropTypes.shape({ correct: PropTypes.bool, value: PropTypes.shape({ true: PropTypes.shape({ resultScore: PropTypes.number, userResponded: PropTypes.bool, }), false: PropTypes.shape({ resultScore: PropTypes.number, userResponded: PropTypes.bool, }), }), }).isRequired, styles: PropTypes.object, } static defaultProps = { itemId: void 0, } getUserResponse() { const {value} = this.props.scoredData if (!value) return void 0 if (value.true && value.true.userResponded) return true if (value.false && value.false.userResponded) return false return null } getCorrectAnswer() { const {value} = this.props.scoredData if (!value) return void 0 const trueScore = value.true && value.true.resultScore const falseScore = value.false && value.false.resultScore if (typeof trueScore !== 'undefined') { return trueScore > 0 } else if (typeof falseScore !== 'undefined') { return falseScore <= 0 // if we're > 0 we want this to return false } // unknown answer! return void 0 } getCorrectAnswerLabel() { const {interactionData, scoredData} = this.props const {value} = scoredData if (!value) return null if (value.true && value.true.resultScore > 0) { return interactionData[TRUE_CHOICE] } else if (value.false && value.false.resultScore > 0) { return interactionData[FALSE_CHOICE] } return null } renderUngradedChoice(name, label, checked) { return ( <RadioInput checked={checked} value={checked.toString()} readOnly name={name} label={label} /> ) } renderChoice(choiceType, correctAnswer, userResponse) { const {interactionData} = this.props const isChecked = choiceType === userResponse const label = interactionData[choiceType ? TRUE_CHOICE : FALSE_CHOICE] if (typeof correctAnswer === 'undefined' || !isChecked) { return this.renderUngradedChoice(name, label, !!isChecked) } let status if (choiceType === correctAnswer) { status = 'correct' } else { status = 'incorrect' } const correctAnswerLabel = this.getCorrectAnswerLabel() const name = `interaction_${this.props.itemId}_${choiceType}` return ( <FeedbackWrapper correctAnswer={correctAnswerLabel} hiddenCorrectAnswerText={t('Correct answer: ')} hiddenIncorrectAnswerText={t('Incorrect answer: ')} status={status} userResponse={label} > <RadioInput checked value="true" readOnly name={name} label={label} /> </FeedbackWrapper> ) } render() { const userResponse = this.getUserResponse() const correctAnswer = this.getCorrectAnswer() const correctnessKnown = typeof this.props.scoredData.correct !== 'undefined' const responseHidden = typeof userResponse === 'undefined' return ( <ItemBodyWrapper itemBody={this.props.itemBody}> <div className="fs-mask"> <div css={this.props.styles.choiceWrapper}> {this.renderChoice(true, correctAnswer, userResponse)} </div> <div css={this.props.styles.choiceWrapper}> {this.renderChoice(false, correctAnswer, userResponse)} </div> {userResponse == null && ( <NoResponse css={this.props.styles.noResponseWrapper} correctAnswerLabel={this.getCorrectAnswerLabel(correctAnswer)} responseHidden={responseHidden} status={userResponse === null && correctnessKnown ? 'incorrect' : 'unknown'} /> )} </div> </ItemBodyWrapper> ) } }