Passed
Push — feature/add-2fa-support ( 23e818...85b1f3 )
by Chris
24:19 queued 11:16
created

resources/assets/js/components/Form/CheckboxGroup.tsx   A

Complexity

Total Complexity 2
Complexity/F 0

Size

Lines of Code 90
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 66
dl 0
loc 90
rs 10
c 0
b 0
f 0
wmc 2
mnd 2
bc 2
fnc 0
bpm 0
cpm 0
noi 0
1
import * as React from "react";
2
import { FormikActions } from "formik";
3
import { FormattedMessage } from "react-intl";
4
import { inputMessages } from "./Messages";
5
6
interface CheckboxGroupProps {
7
  /** HTML ID of the input. */
8
  id: string;
9
  /** Text for the associated label of the input. */
10
  label: string;
11
  /** data-clone-grid-item value, see https://designwithclone.ca/#flexbox-grid. */
12
  grid: string;
13
  /** If this input is required for submission. */
14
  required?: boolean;
15
  /** Error to display. */
16
  error: (string | undefined)[] | undefined;
17
  /** If this group has been affected by user input or a submission. */
18
  touched: (boolean | undefined)[] | undefined;
19
  /** Array of all selected values */
20
  value: (string | number)[];
21
  /** Function which takes an id and value as arguments, and sets the field (id) to the value */
22
  onChange: FormikActions<any>["setFieldValue"];
23
  /** Function which takes an id and boolean value as arguments, and sets the field (id) to the boolean value */
24
  onBlur: FormikActions<any>["setFieldTouched"];
25
}
26
27
const CheckboxGroup: React.FunctionComponent<CheckboxGroupProps> = ({
28
  id,
29
  label: checkboxGroupLabel,
30
  grid,
31
  required,
32
  children,
33
  value,
34
  error,
35
  touched,
36
  onChange,
37
  onBlur,
38
}): React.ReactElement => {
39
  const handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
40
    // Get target checkbox element
41
    const target = event.currentTarget;
42
43
    // if the target is checked push the "name" to the values array
44
    if (target.checked) {
45
      value.push(target.id);
46
    } else {
47
      // if the target is unchecked then filter out the "name" from the array
48
      value.splice(value.indexOf(target.id), 1);
49
    }
50
51
    onChange(id, value);
52
  };
53
54
  const handleBlur = (): void => {
55
    onBlur(id, true);
56
  };
57
58
  return (
59
    <div
60
      data-c-grid-item={grid}
61
      data-c-input="checkbox"
62
      data-c-required={required || null}
63
      data-c-invalid={touched && error ? true : null}
64
    >
65
      <label>{checkboxGroupLabel}</label>
66
      <span>
67
        <FormattedMessage {...inputMessages.required} />
68
      </span>
69
      <div data-c-grid>
70
        {React.Children.map(
71
          children,
72
          (child: React.ReactElement): React.ReactElement => {
73
            return React.cloneElement(child, {
74
              field: {
75
                value: value.includes(child.props.id),
76
                onChange: handleChange,
77
                onBlur: handleBlur,
78
              },
79
              checked: value.includes(child.props.id),
80
            });
81
          },
82
        )}
83
      </div>
84
      <span>{error}</span>
85
    </div>
86
  );
87
};
88
89
export default CheckboxGroup;
90