diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/InputTypes/Checkbox.tsx | 18 | ||||
| -rw-r--r-- | src/components/InputTypes/Radio.tsx | 8 | ||||
| -rw-r--r-- | src/components/InputTypes/Range.tsx | 8 | ||||
| -rw-r--r-- | src/components/InputTypes/Select.tsx | 6 | ||||
| -rw-r--r-- | src/components/InputTypes/TextArea.tsx | 12 | ||||
| -rw-r--r-- | src/components/InputTypes/index.tsx | 8 | ||||
| -rw-r--r-- | src/components/Question.tsx | 43 | 
7 files changed, 70 insertions, 33 deletions
| diff --git a/src/components/InputTypes/Checkbox.tsx b/src/components/InputTypes/Checkbox.tsx index 38b8ee8..9c633f0 100644 --- a/src/components/InputTypes/Checkbox.tsx +++ b/src/components/InputTypes/Checkbox.tsx @@ -3,13 +3,15 @@ import { jsx, css } from "@emotion/react";  import React, { ChangeEvent } from "react";  import colors from "../../colors";  import { multiSelectInput, hiddenInput } from "../../commonStyles"; -import {useSelector} from "react-redux"; -import {FormState} from "../../store/form/types"; +import { useSelector } from "react-redux"; +import { FormState } from "../../store/form/types"; +import { Question } from "../../api/question";  interface CheckboxProps {      index: number,      option: string, -    handler: (event: ChangeEvent<HTMLInputElement>) => void +    handler: (event: ChangeEvent<HTMLInputElement>) => void, +    question: Question  }  const generalStyles = css` @@ -58,10 +60,16 @@ export default function Checkbox(props: CheckboxProps): JSX.Element {      const values = useSelector<FormState, FormState["values"]>(          state => state.values      ); +    let value = values[props.question.id]; +    if (typeof value !== "object" || !value) { +        value = {}; +    } +    const checked = value[`${("000" + props.index).slice(-4)}. ${props.option}`]; +      return (          <label css={[generalStyles, activeStyles]}> -            <label className="unselected" css={multiSelectInput}> -                <input type="checkbox" value={props.option} css={hiddenInput} name={`${("000" + props.index).slice(-4)}. ${props.option}`} onChange={props.handler} checked={!!values[`${("000" + props.index).slice(-4)}. ${props.option}`]}/> +            <label className={checked ? "selected" : "unselected"} css={multiSelectInput}> +                <input type="checkbox" value={props.option} css={hiddenInput} name={`${("000" + props.index).slice(-4)}. ${props.option}`} onChange={props.handler} checked={checked}/>                  <span className="checkmark"/>              </label>              {props.option}<br/> diff --git a/src/components/InputTypes/Radio.tsx b/src/components/InputTypes/Radio.tsx index a857964..68c9519 100644 --- a/src/components/InputTypes/Radio.tsx +++ b/src/components/InputTypes/Radio.tsx @@ -3,6 +3,8 @@ import { jsx, css } from "@emotion/react";  import React, { ChangeEvent } from "react";  import colors from "../../colors";  import { multiSelectInput, hiddenInput } from "../../commonStyles"; +import { useSelector } from "react-redux"; +import { FormState } from "../../store/form/types";  interface RadioProps {      option: string, @@ -30,9 +32,13 @@ const styles = css`  `;  export default function Radio(props: RadioProps): JSX.Element { +    const values = useSelector<FormState, FormState["values"]>( +        state => state.values +    ); +    const value = values[props.question_id];      return (          <label css={styles}> -            <input type="radio" name={props.question_id} onChange={props.handler} css={hiddenInput} onBlur={props.onBlurHandler}/> +            <input type="radio" name={props.question_id} onChange={props.handler} css={hiddenInput} onBlur={props.onBlurHandler} checked={value === props.option}/>              <div css={multiSelectInput}/>              {props.option}<br/>          </label> diff --git a/src/components/InputTypes/Range.tsx b/src/components/InputTypes/Range.tsx index 23cb3f6..8d37b8a 100644 --- a/src/components/InputTypes/Range.tsx +++ b/src/components/InputTypes/Range.tsx @@ -3,6 +3,8 @@ import { jsx, css } from "@emotion/react";  import React, { ChangeEvent } from "react";  import colors from "../../colors";  import { hiddenInput, multiSelectInput } from "../../commonStyles"; +import { useSelector } from "react-redux"; +import { FormState } from "../../store/form/types";  interface RangeProps {      question_id: string, @@ -97,11 +99,15 @@ const sliderStyles = css`  `;  export default function Range(props: RangeProps): JSX.Element { +    const values = useSelector<FormState, FormState["values"]>( +        state => state.values +    ); +    const value = values[props.question_id];      const range = props.options.map((option, index) => {          return (              <label css={[selectorStyles, css`width: 1rem`]} key={index}>                  <span css={optionStyles}>{option}</span> -                <input type="radio" name={props.question_id} css={hiddenInput} onChange={props.handler} onBlur={props.onBlurHandler}/> +                <input type="radio" name={props.question_id} css={hiddenInput} onChange={props.handler} onBlur={props.onBlurHandler} checked={value === option}/>                  <div css={multiSelectInput}/>              </label>          ); diff --git a/src/components/InputTypes/Select.tsx b/src/components/InputTypes/Select.tsx index c0f5425..82e0975 100644 --- a/src/components/InputTypes/Select.tsx +++ b/src/components/InputTypes/Select.tsx @@ -16,11 +16,11 @@ interface SelectProps {  }  interface SelectStateProps { -    values: Map<string, string | Map<string, boolean> | null> +    values: { [key: string]: string | { [subKey: string]: boolean; } | null; }  }  interface SelectDispatchProps { -    setValue: (question: Question, value: string | Map<string, boolean> | null) => SetValueAction +    setValue: (question: Question, value: string | { [key: string]: boolean } | null) => SetValueAction  }  const containerStyles = css` @@ -191,7 +191,7 @@ class Select extends React.Component<SelectProps & SelectStateProps & SelectDisp      }      focusOption(): void { -        if (!this.props.values.get(this.props.question.id)) { +        if (!(this.props.question.id in this.props.values) || !this.props.values[this.props.question.id]) {              this.props.setValue(this.props.question, "temporary");              this.props.onBlurHandler();              this.props.setValue(this.props.question, null); diff --git a/src/components/InputTypes/TextArea.tsx b/src/components/InputTypes/TextArea.tsx index 08424fb..a32094c 100644 --- a/src/components/InputTypes/TextArea.tsx +++ b/src/components/InputTypes/TextArea.tsx @@ -2,13 +2,17 @@  import { jsx, css } from "@emotion/react";  import React, { ChangeEvent } from "react";  import { invalidStyles, textInputs } from "../../commonStyles"; +import { useSelector } from "react-redux"; +import { FormState } from "../../store/form/types"; +import { Question } from "../../api/question";  interface TextAreaProps {      handler: (event: ChangeEvent<HTMLTextAreaElement>) => void,      onBlurHandler: () => void,      valid: boolean,      // eslint-disable-next-line @typescript-eslint/no-explicit-any -    focus_ref: React.RefObject<any> +    focus_ref: React.RefObject<any>, +    question: Question  }  const styles = css` @@ -21,9 +25,13 @@ const styles = css`  `;  export default function TextArea(props: TextAreaProps): JSX.Element { +    const values = useSelector<FormState, FormState["values"]>( +        state => state.values +    ); +    const value = values[props.question.id];      return (          <div css={invalidStyles}> -            <textarea css={[textInputs, styles]} placeholder="Enter Text..." onChange={props.handler} onBlur={props.onBlurHandler} className={!props.valid ? "invalid-box" : ""} ref={props.focus_ref}/> +            <textarea css={[textInputs, styles]} value={typeof value === "string" ? value : ""} placeholder="Enter Text..." onChange={props.handler} onBlur={props.onBlurHandler} className={!props.valid ? "invalid-box" : ""} ref={props.focus_ref}/>          </div>      );  } diff --git a/src/components/InputTypes/index.tsx b/src/components/InputTypes/index.tsx index ff02259..97fd790 100644 --- a/src/components/InputTypes/index.tsx +++ b/src/components/InputTypes/index.tsx @@ -37,11 +37,11 @@ export default function create_input(props: QuestionProp & QuestionStateProp & Q      /* eslint-disable react/react-in-jsx-scope */      switch (question.type) {          case QuestionType.TextArea: -            result = <TextArea handler={handler} valid={valid} onBlurHandler={onBlurHandler} focus_ref={focus_ref}/>; +            result = <TextArea question={question} handler={handler} valid={valid} onBlurHandler={onBlurHandler} focus_ref={focus_ref}/>;              break;          case QuestionType.Checkbox: -            result = options.map((option, index) => <Checkbox index={index} option={option} handler={handler} key={index}/>); +            result = options.map((option, index) => <Checkbox question={question} index={index} option={option} handler={handler} key={index}/>);              break;          case QuestionType.Radio: @@ -53,7 +53,7 @@ export default function create_input(props: QuestionProp & QuestionStateProp & Q              break;          case QuestionType.ShortText: -            result = <ShortText handler={handler} onBlurHandler={onBlurHandler} valid={valid} focus_ref={focus_ref} question={question}/>; +            result = <ShortText key={props.question.id} handler={handler} onBlurHandler={onBlurHandler} valid={valid} focus_ref={focus_ref} question={question}/>;              break;          case QuestionType.Range: @@ -66,7 +66,7 @@ export default function create_input(props: QuestionProp & QuestionStateProp & Q              break;          default: -            result = <TextArea handler={handler} valid={valid} onBlurHandler={onBlurHandler} focus_ref={focus_ref}/>; +            result = <TextArea question={question} handler={handler} valid={valid} onBlurHandler={onBlurHandler} focus_ref={focus_ref}/>;      }      /* eslint-enable react/react-in-jsx-scope */ diff --git a/src/components/Question.tsx b/src/components/Question.tsx index 7212a2d..74ee86f 100644 --- a/src/components/Question.tsx +++ b/src/components/Question.tsx @@ -1,14 +1,14 @@  /** @jsx jsx */  import { jsx, css } from "@emotion/react"; -import React, { ChangeEvent } from "react"; -import { connect } from "react-redux"; +import React, {ChangeEvent} from "react"; +import {connect} from "react-redux"; -import { Question, QuestionType } from "../api/question"; -import { selectable } from "../commonStyles"; +import {Question, QuestionType} from "../api/question"; +import {selectable} from "../commonStyles";  import create_input from "./InputTypes";  import ErrorMessage from "./ErrorMessage"; -import { FormState } from "../store/form/types"; -import { setError, SetErrorAction, setValid, SetValidAction, setValue, SetValueAction } from "../store/form/actions"; +import {FormState} from "../store/form/types"; +import {setError, SetErrorAction, setValid, SetValidAction, setValue, SetValueAction} from "../store/form/actions";  const skip_normal_state: Array<QuestionType> = [      QuestionType.Radio, @@ -47,10 +47,14 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta          }          this.blurHandler = this.blurHandler.bind(this); -        props.setValid(props.question, true); -        props.setError(props.question, ""); +        if (!(props.question.id in props.valid)) { +            props.setValid(props.question, true); +        } +        if (!(props.question.id in props.errors)) { +            props.setError(props.question, ""); +        } -        if (!skip_normal_state.includes(props.question.type)) { +        if (!skip_normal_state.includes(props.question.type) && !(props.question.id in props.values)) {              props.setValue(props.question, "");          }      } @@ -102,12 +106,6 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta              this.props.setValue(this.props.question, value);          } -        // Toggle checkbox class -        if (event.target.type == "checkbox" && event.target.parentElement !== null) { -            event.target.parentElement.classList.toggle("unselected"); -            event.target.parentElement.classList.toggle("selected"); -        } -          const options: string | string[] = this.props.question.data["options"];          switch (event.target.type) {              case "text": @@ -194,17 +192,28 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta      }      componentDidMount(): void { +        // We don't want to set if we already have them in values. +        if (this.props.question.id in this.props.values) { +            return; +        } +          // Initialize defaults for complex and nested fields          const options: string | string[] = this.props.question.data["options"]; -        const values = this.props.values[this.props.question.id]; +        let values = this.props.values[this.props.question.id];          switch (this.props.question.type) {              case QuestionType.Checkbox: -                if (typeof options === "string" || !(typeof values === "object") || !values) { +                if (typeof options === "string") {                      return;                  } +                if (!(typeof values === "object") || !values) { +                    values = {}; +                } +                  options.forEach((option, index) => { +                    // eslint-disable-next-line @typescript-eslint/ban-ts-comment +                    // @ts-ignore                      values[`${("000" + index).slice(-4)}. ${option}`] = false;                  });                  this.props.setValue(this.props.question, values); | 
