Files

139 lines
4.3 KiB
TypeScript

import CheckboxElement from "../Checkbox/Checkbox";
import {
CategoryCheckboxOption,
CheckboxCategory,
} from "./CategoryCheckboxTypes";
import CheckBoxList from "./CheckboxList";
import React, { FunctionComponent, ReactElement, useEffect } from "react";
export type CategoryCheckboxValue = string | number | boolean;
export interface CategoryProps {
category?: CheckboxCategory | undefined;
options: Array<CategoryCheckboxOption>;
onChange: (value: Array<CategoryCheckboxValue>) => void;
initialValue?: undefined | Array<CategoryCheckboxValue>;
isLastCategory: boolean;
dataTestId?: string | undefined;
}
enum CategoryCheckboxValueState {
Checked,
Unchecked,
Indeterminate,
}
const Category: FunctionComponent<CategoryProps> = (
props: CategoryProps,
): ReactElement => {
const [currentValues, setCurrentValues] = React.useState<
Array<CategoryCheckboxValue>
>(props.initialValue || []);
const [categoryCheckboxState, setCategoryCheckboxState] =
React.useState<CategoryCheckboxValueState>(
CategoryCheckboxValueState.Unchecked,
);
useEffect(() => {
// check if all of the options are checked. and if so, check the category
const noOptionsChecked: boolean = currentValues.length === 0;
if (noOptionsChecked) {
setCategoryCheckboxState(CategoryCheckboxValueState.Unchecked);
return;
}
const allOptionsChecked: boolean = props.options.every(
(option: CategoryCheckboxOption) => {
return currentValues.includes(option.value);
},
);
if (allOptionsChecked) {
setCategoryCheckboxState(CategoryCheckboxValueState.Checked);
} else {
setCategoryCheckboxState(CategoryCheckboxValueState.Indeterminate);
}
}, [currentValues]);
useEffect(() => {
setCurrentValues(props.initialValue || []);
}, [props.initialValue]);
return (
<div>
{props.category && (
<div>
<CheckboxElement
title={props.category.title}
dataTestId={props.dataTestId}
value={categoryCheckboxState === CategoryCheckboxValueState.Checked}
isIndeterminate={
categoryCheckboxState === CategoryCheckboxValueState.Indeterminate
}
onChange={(
isChecked: boolean,
isIndeterminate?: boolean | undefined,
) => {
if (isIndeterminate && !isChecked) {
return;
}
if (isChecked) {
// add all of the options to the currentValues array
const newValues: Array<CategoryCheckboxValue> = [
...currentValues,
];
props.options.forEach((option: CategoryCheckboxOption) => {
// please make sure that the option.value is not already in the array
if (newValues.includes(option.value)) {
return;
}
newValues.push(option.value);
});
setCurrentValues(newValues);
props.onChange(newValues);
} else {
// remove all of the options from the currentValues array
const newValues: Array<CategoryCheckboxValue> = [
...currentValues,
];
props.options.forEach((option: CategoryCheckboxOption) => {
while (newValues.includes(option.value)) {
const index: number = newValues.findIndex(
(value: CategoryCheckboxValue) => {
return value === option.value;
},
);
newValues.splice(index, 1);
}
});
setCurrentValues(newValues);
props.onChange(newValues);
}
}}
/>
</div>
)}
<div className={`${props.category ? "ml-7" : ""}`}>
<CheckBoxList
options={props.options}
initialValue={currentValues}
onChange={(newValues: Array<CategoryCheckboxValue>) => {
setCurrentValues(newValues);
props.onChange(newValues);
}}
/>
</div>
{!props.isLastCategory ? <div className="mt-3 mb-3"></div> : <></>}
</div>
);
};
export default Category;