Skip to content
Snippets Groups Projects
PreciseAnswerComponent.js 4.38 KiB
Newer Older
chris's avatar
chris committed
/* eslint-disable react/prop-types */
chris's avatar
chris committed
import React, { useRef, useState, useContext } from 'react';
chris's avatar
chris committed
import styled from 'styled-components';
chris's avatar
chris committed
import { DocumentHelpers, WaxContext } from 'wax-prosemirror-core';
chris's avatar
chris committed

chris's avatar
chris committed
const AnswerContainer = styled.div`
  display: flex;
  flex-direction: row;
  width: 100%;
`;

const ValueContainer = styled.div`
  display: flex;
  flex-direction: column;
  margin-right: 25px;
  label {
    font-size: 12px;
  }

  input:focus {
    outline: none;
  }
`;

const ValueInnerContainer = styled.div`
  display: flex;
  flex-direction: column;
`;

chris's avatar
chris committed
const ResultContainer = styled.div`
  display: flex;
  flex-direction: column;
`;

const FinalResult = styled.span`
  color: ${props => (props.isCorrect ? ' #008000' : 'red')};
  font-weight: 999;
`;

chris's avatar
chris committed
const PreciseAnswerComponent = ({ node, readOnly, testMode, showFeedBack }) => {
chris's avatar
chris committed
  const context = useContext(WaxContext);
chris's avatar
chris committed
  const [precise, setPrecise] = useState(
    node.attrs.answersPrecise.preciseAnswer || '',
  );
chris's avatar
chris committed

chris's avatar
chris committed
  const [preciseStudent, setPreciseStudent] = useState(
    node.attrs.answerPrecise || '',
  );

chris's avatar
chris committed
  const preciseRef = useRef(null);
chris's avatar
chris committed
  const preciseStudentRef = useRef(null);
chris's avatar
chris committed

  const onlyNumbers = value => {
    return value
chris's avatar
chris committed
      .replace(/[^0-9.;]/g, '')
      .replace(/(\..*?)\..*/g, '$1')
      .replace(/^0[^.]/, '0');
  };

chris's avatar
chris committed
  const SaveValuesToNode = () => {
    const allNodes = getNodes(context.pmViews.main);
    allNodes.forEach(singleNode => {
      if (singleNode.node.attrs.id === node.attrs.id) {
        const obj = {
chris's avatar
chris committed
          preciseAnswer: onlyNumbers(preciseRef.current.value),
chris's avatar
chris committed
        };

        context.pmViews.main.dispatch(
          context.pmViews.main.state.tr.setNodeMarkup(
            singleNode.pos,
            undefined,
            {
              ...singleNode.node.attrs,
              answersPrecise: obj,
            },
          ),
        );
      }
    });
  };

chris's avatar
chris committed
  const onChangePrecice = () => {
    setPrecise(onlyNumbers(preciseRef.current.value));
chris's avatar
chris committed
    SaveValuesToNode();
chris's avatar
chris committed
  };

chris's avatar
chris committed
  const onChangePreciseStudent = () => {
    setPreciseStudent(onlyNumbers(preciseStudentRef.current.value));
    const allNodes = getNodes(context.pmViews.main);
    allNodes.forEach(singleNode => {
      if (singleNode.node.attrs.id === node.attrs.id) {
        context.pmViews.main.dispatch(
          context.pmViews.main.state.tr.setNodeMarkup(
            singleNode.pos,
            undefined,
            {
              ...singleNode.node.attrs,
              answerPrecise: onlyNumbers(preciseStudentRef.current.value),
            },
          ),
        );
      }
    });
  };

chris's avatar
chris committed
  const isCorrect = precise
    .split(';')
    .find(element => element === preciseStudent.trim());

chris's avatar
chris committed
  return (
    <AnswerContainer>
chris's avatar
chris committed
      {!testMode && !showFeedBack && (
        <ValueContainer>
          <label htmlFor="preciseAnswer">
            <ValueInnerContainer>
              <span>Precise Answer</span>
              <input
                disabled={readOnly}
                name="preciseAnswer"
                onChange={onChangePrecice}
                ref={preciseRef}
                type="text"
                value={precise}
              />
            </ValueInnerContainer>
          </label>
        </ValueContainer>
      )}
      {testMode && (
        <ValueContainer>
          <label htmlFor="exactAnswerStudent">
            <ValueInnerContainer>
              <span>Precise Answer</span>
              <input
                name="exactAnswerStudent"
                onChange={onChangePreciseStudent}
                ref={preciseStudentRef}
                type="text"
                value={preciseStudent}
              />
            </ValueInnerContainer>
          </label>
        </ValueContainer>
      )}
chris's avatar
chris committed
      {readOnly && showFeedBack && (
        <ResultContainer>
chris's avatar
chris committed
          <span>{`(Accepted Answers : ${precise.replaceAll(';', ' -')})`}</span>
chris's avatar
chris committed
          <span>
            Answer:{' '}
            <FinalResult isCorrect={isCorrect}>{preciseStudent}</FinalResult>
          </span>
        </ResultContainer>
      )}
chris's avatar
chris committed
    </AnswerContainer>
  );
const getNodes = view => {
  const allNodes = DocumentHelpers.findBlockNodes(view.state.doc);
  const numericalAnswerpContainerNodes = [];
  allNodes.forEach(node => {
    if (node.node.type.name === 'numerical_answer_container') {
      numericalAnswerpContainerNodes.push(node);
    }
  });
  return numericalAnswerpContainerNodes;
};

chris's avatar
chris committed
export default PreciseAnswerComponent;