UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

134 lines (116 loc) 3.73 kB
import React, {Component} from 'react' import PropTypes from 'prop-types' import {Decimal} from '@instructure/quiz-i18n/util/Decimal' 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 {parseSeparators} from '@instructure/quiz-common/util/parseSeparators' import {ApplyLocaleContext} from '@instructure/ui-i18n' /** --- category: Numeric --- Numeric Result component ```jsx_example function Example (props) { const exampleProps = { itemBody: 'x is an integer and 9 < x^2 < 99. What\'s the max value of x, minus the minimum value of x', scoredData: { value: { userResponse: '3.14159265', correctAnswer: '9999.9999', resultScore: 0 } } } return <NumericResult {...exampleProps} {...props} /> } <SettingsSwitcher locales={LOCALES}> <Example /> </SettingsSwitcher> ``` **/ export default class NumericResult extends Component { static propTypes = { itemBody: PropTypes.string.isRequired, scoredData: PropTypes.shape({ value: PropTypes.shape({ userResponse: PropTypes.string, correctAnswer: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), resultScore: PropTypes.number, }), }).isRequired, locale: PropTypes.string, separatorConfig: PropTypes.shape({ decimalSeparator: PropTypes.string, thousandSeparator: PropTypes.string, }), } static contextType = ApplyLocaleContext static defaultProps = { locale: void 0, } componentDidMount() { Decimal.accountSettingDelimiters = this.props.separatorConfig ? parseSeparators(this.props.separatorConfig) : null } get locale() { return this.props.locale || this.context.locale || 'en-US' } correctAnswerString() { const {correctAnswer} = this.props.scoredData.value || {} if (Array.isArray(correctAnswer)) { const [minimum, maximum] = correctAnswer return t('{minimum} to {maximum} inclusive', { minimum: this.formatNumber(minimum), maximum: this.formatNumber(maximum), }) } else if (correctAnswer) { return this.formatNumber(correctAnswer) } return '' } isDecimal(value) { return /^-?\d+(\.\d+)?$/.test(String(value).trim()) } formatNumber(value) { // Only format decimal numbers, if a user used scientific notation or something else, // we want to display it as they entered it return this.isDecimal(value) ? Decimal.toLocaleString(value.toString().trim(), this.locale) : value } render() { const {itemBody} = this.props const {resultScore, userResponse} = this.props.scoredData.value || {} const responseHidden = typeof userResponse === 'undefined' let status if (resultScore > 0) { status = 'correct' } else if (resultScore <= 0) { status = 'incorrect' } else { status = 'unknown' } return ( <ItemBodyWrapper itemBody={itemBody}> {userResponse == null ? ( <NoResponse correctAnswerLabel={this.correctAnswerString()} responseHidden={responseHidden} status={status} /> ) : ( <FeedbackWrapper status={status} userResponse={this.formatNumber(userResponse)} correctAnswer={this.correctAnswerString()} hiddenCorrectAnswerText={t('Correct answer: ')} hiddenIncorrectAnswerText={t('Incorrect answer: ')} /> )} </ItemBodyWrapper> ) } }