diff options
| -rw-r--r-- | src/components/InputTypes/Checkbox.tsx | 2 | ||||
| -rw-r--r-- | src/components/InputTypes/ShortText.tsx | 2 | ||||
| -rw-r--r-- | src/components/InputTypes/index.tsx | 5 | ||||
| -rw-r--r-- | src/components/Question.tsx | 46 | ||||
| -rw-r--r-- | src/pages/FormPage.tsx | 10 | ||||
| -rw-r--r-- | src/store/form/actions.ts | 4 | ||||
| -rw-r--r-- | src/store/form/reducers.ts | 42 | ||||
| -rw-r--r-- | src/store/form/types.ts | 6 |
8 files changed, 65 insertions, 52 deletions
diff --git a/src/components/InputTypes/Checkbox.tsx b/src/components/InputTypes/Checkbox.tsx index b3130c6..38b8ee8 100644 --- a/src/components/InputTypes/Checkbox.tsx +++ b/src/components/InputTypes/Checkbox.tsx @@ -61,7 +61,7 @@ export default function Checkbox(props: CheckboxProps): JSX.Element { 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.get(`${("000" + props.index).slice(-4)}. ${props.option}`)}/> + <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}`]}/> <span className="checkmark"/> </label> {props.option}<br/> diff --git a/src/components/InputTypes/ShortText.tsx b/src/components/InputTypes/ShortText.tsx index e40612f..87fef84 100644 --- a/src/components/InputTypes/ShortText.tsx +++ b/src/components/InputTypes/ShortText.tsx @@ -20,7 +20,7 @@ export default function ShortText(props: ShortTextProps): JSX.Element { const values = useSelector<FormState, FormState["values"]>( state => state.values ); - const value = values.get(props.question.id); + const value = values[props.question.id]; return ( <div css={invalidStyles}> diff --git a/src/components/InputTypes/index.tsx b/src/components/InputTypes/index.tsx index fd99ce8..ff02259 100644 --- a/src/components/InputTypes/index.tsx +++ b/src/components/InputTypes/index.tsx @@ -26,10 +26,7 @@ export default function create_input(props: QuestionProp & QuestionStateProp & Q // eslint-disable-next-line // @ts-ignore let options: string[] = question.data["options"]; - let valid = true; - if (!props.valid.get(question.id)) { - valid = false; - } + const valid = props.valid[question.id]; // Catch input types that require options but don't have any if ((options === undefined || typeof options !== "object") && require_options.includes(question.type)) { diff --git a/src/components/Question.tsx b/src/components/Question.tsx index 74c4a71..7212a2d 100644 --- a/src/components/Question.tsx +++ b/src/components/Question.tsx @@ -26,13 +26,13 @@ export type QuestionProp = { } export type QuestionStateProp = { - values: Map<string, string | Map<string, boolean> | null>, - errors: Map<string, string>, - valid: Map<string, boolean>, + values: { [key: string]: string | { [subKey: string]: boolean } | null }, + errors: { [key: string]: string }, + valid: { [key: string]: boolean } }; export type QuestionDispatchProp = { - setValue: (question: Question, value: string | Map<string, boolean> | null) => SetValueAction, + setValue: (question: Question, value: string | { [key: string]: boolean } | null) => SetValueAction, setValid: (question: Question, valid: boolean) => SetValidAction, setError: (question: Question, error: string) => SetErrorAction }; @@ -60,7 +60,7 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta blurHandler(): void { if (this.props.question.required) { - if (!this.props.values.get(this.props.question.id)) { + if (!this.props.values[this.props.question.id]) { this.props.setError(this.props.question, "Field must be filled."); this.props.setValid(this.props.question, false); } else { @@ -92,11 +92,11 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta } if (value instanceof Array) { - let values = this.props.values.get(this.props.question.id); - if (!(values instanceof Map)) { - values = new Map<string, boolean>(); + let values = this.props.values[this.props.question.id]; + if (typeof values !== "object" || !values) { + values = {}; } - values.set(value[0], value[1]); + values[value[0]] = value[1]; this.props.setValue(this.props.question, values); } else { this.props.setValue(this.props.question, value); @@ -121,8 +121,8 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta options.forEach((val, index) => { keys.push(`${("000" + index).slice(-4)}. ${val}`); }); - const values = this.props.values.get(this.props.question.id); - if (values instanceof Map && keys.every(v => !values.get(v))) { + const values = this.props.values[this.props.question.id]; + if (typeof values === "object" && values && keys.every(v => !values[v])) { this.props.setError(this.props.question, "Field must be filled."); this.props.setValid(this.props.question, false); } else { @@ -157,7 +157,7 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta switch (this.props.question.type) { case QuestionType.TextArea: case QuestionType.ShortText: - if (this.props.values.get(this.props.question.id) === "") { + if (this.props.values[this.props.question.id] === "") { invalid = true; } break; @@ -165,7 +165,7 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta case QuestionType.Select: case QuestionType.Range: case QuestionType.Radio: - if (!this.props.values.get(this.props.question.id)) { + if (!this.props.values[this.props.question.id]) { invalid = true; } break; @@ -176,8 +176,8 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta options.forEach((val, index) => { keys.push(`${("000" + index).slice(-4)}. ${val}`); }); - const values = this.props.values.get(this.props.question.id); - if (values instanceof Map && keys.every(v => !values.get(v))) { + const values = this.props.values[this.props.question.id]; + if (typeof values === "object" && values && keys.every(v => !values[v])) { invalid = true; } } @@ -196,16 +196,16 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta componentDidMount(): void { // Initialize defaults for complex and nested fields const options: string | string[] = this.props.question.data["options"]; - const values = this.props.values.get(this.props.question.id); + const values = this.props.values[this.props.question.id]; switch (this.props.question.type) { case QuestionType.Checkbox: - if (typeof options === "string" || !(values instanceof Map)) { + if (typeof options === "string" || !(typeof values === "object") || !values) { return; } options.forEach((option, index) => { - values.set(`${("000" + index).slice(-4)}. ${option}`, false); + values[`${("000" + index).slice(-4)}. ${option}`] = false; }); this.props.setValue(this.props.question, values); break; @@ -266,13 +266,13 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta } `; let valid = true; - if (!this.props.valid.get(this.props.question.id)) { - valid = false; + if (this.props.question.id in this.props.valid) { + valid = this.props.valid[this.props.question.id]; } - const rawError = this.props.errors.get(this.props.question.id); + let error = ""; - if (typeof rawError === "string") { - error = rawError; + if (this.props.question.id in this.props.errors) { + error = this.props.errors[this.props.question.id]; } return <div ref={this.props.scroll_ref}> diff --git a/src/pages/FormPage.tsx b/src/pages/FormPage.tsx index 865497c..e7d40cf 100644 --- a/src/pages/FormPage.tsx +++ b/src/pages/FormPage.tsx @@ -249,7 +249,7 @@ function FormPage(): JSX.Element { questionRef.current.validateField(); } // In case when field is invalid, add this to invalid fields list - if (valid.get(question.id) === false) { + if (!valid[question.id]) { invalidFieldIDs.push(i); } }); @@ -293,15 +293,15 @@ function FormPage(): JSX.Element { case QuestionType.Checkbox: { if (typeof options !== "string") { - const checkbox_values = values.get(question.id); + const checkbox_values = values[question.id]; const keys: Map<string, string> = new Map(); options.forEach((val: string, index) => { keys.set(val, `${("000" + index).slice(-4)}. ${val}`); }); - if (checkbox_values instanceof Map) { + if (typeof checkbox_values === "object" && checkbox_values) { const pairs: { [key: string]: boolean } = { }; keys.forEach((val, key) => { - pairs[key] = !!checkbox_values.get(val); + pairs[key] = checkbox_values[val]; }); answers[question.id] = pairs; } @@ -311,7 +311,7 @@ function FormPage(): JSX.Element { case QuestionType.Code: default: - answers[question.id] = values.get(question.id); + answers[question.id] = values[question.id]; } }); diff --git a/src/store/form/actions.ts b/src/store/form/actions.ts index dc43729..90a23b0 100644 --- a/src/store/form/actions.ts +++ b/src/store/form/actions.ts @@ -19,7 +19,7 @@ export interface SetValueAction extends DefaultFormAction { type: FormAction.SET_VALUE, payload: { question: Question, - value: string | Map<string, boolean> | null + value: string | { [key: string]: boolean } | null } } @@ -50,7 +50,7 @@ export interface SetCaptchaTokenAction extends DefaultFormAction { export type Action = SetValueAction | SetErrorAction | SetValidAction | CleanAction | SetCaptchaTokenAction; -export function setValue(question: Question, value: string | Map<string, boolean> | null): SetValueAction { +export function setValue(question: Question, value: string | { [key: string]: boolean } | null): SetValueAction { return { type: FormAction.SET_VALUE, payload: { diff --git a/src/store/form/reducers.ts b/src/store/form/reducers.ts index d7d3388..69730c3 100644 --- a/src/store/form/reducers.ts +++ b/src/store/form/reducers.ts @@ -2,33 +2,49 @@ import {Action, FormAction} from "./actions"; import {FormState} from "./types"; export const initialState: FormState = { - values: new Map(), - errors: new Map(), - valid: new Map(), + values: {}, + errors: {}, + valid: {}, captchaToken: null }; export function formReducer(state = initialState, action: Action): FormState { - const new_state = {...state}; switch (action.type) { case FormAction.SET_VALUE: - new_state.values.set(action.payload.question.id, action.payload.value); - break; + return { + ...state, + values: { + ...state.values, + [action.payload.question.id]: action.payload.value + } + }; case FormAction.SET_ERROR: - new_state.errors.set(action.payload.question.id, action.payload.error); - break; + return { + ...state, + errors: { + ...state.errors, + [action.payload.question.id]: action.payload.error + } + }; case FormAction.SET_VALID: - new_state.valid.set(action.payload.question.id, action.payload.valid); - break; + return { + ...state, + valid: { + ...state.valid, + [action.payload.question.id]: action.payload.valid + } + }; case FormAction.CLEAN: return initialState; case FormAction.SET_CAPTCHA_TOKEN: - new_state.captchaToken = action.payload; - break; + return { + ...state, + captchaToken: action.payload + }; } - return new_state; + return {...state}; } diff --git a/src/store/form/types.ts b/src/store/form/types.ts index 3f8557e..280ef92 100644 --- a/src/store/form/types.ts +++ b/src/store/form/types.ts @@ -1,6 +1,6 @@ export interface FormState { - values: Map<string, string | Map<string, boolean> | null>, - errors: Map<string, string>, - valid: Map<string, boolean>, + values: { [key: string]: string | { [subKey: string]: boolean } | null }, + errors: { [key: string]: string }, + valid: { [key: string]: boolean }, captchaToken: string | null } |