Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | 26x 21x 21x 21x 42x 126x 126x 126x 126x 21x 21x 21x 21x 7x 21x 21x 7x 7x 2x 2x 2x 2x 5x 5x 7x 7x 21x 63x 7x 26x | import { useCallback, useEffect, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import isEqual from 'lodash/isEqual';
import { Checkbox } from '@folio/stripes/components';
import { usePrevNextPagination, useQIndex } from '../hooks';
import css from '../../../styles/SearchKeyControl.css';
/*
IMPORTANT -- This component is controlled by the qIndex, rather than the other way around.
It should inject values in/remove values from the qIndex, but not replace the entire thing.
*/
const SearchKeyControl = ({
options = []
}) => {
// This component expects a qIndex comprising of a comma separated list
const [qIndex, setQIndex] = useQIndex();
const qIndexArray = useMemo(() => qIndex?.split(',')?.map(index => index.trim()) ?? [], [qIndex]);
// Memoise this process so keyState changes if and only if options/qIndex change
const createKeyState = useCallback(() => (
options.reduce((acc, curr) => {
// Is in use if URL contains ALL of the indexes
const subindexes = ((curr?.indexes?.length ?? 0) > 0) ? curr.indexes : [curr.key];
acc[curr.key] = {
inUse: subindexes.every(si => qIndexArray.includes(si)),
label: curr.label ?? curr.key,
subIndexes: curr.indexes
};
return acc;
}, {})
), [options, qIndexArray]);
const [keyState, setKeyState] = useState(createKeyState());
// Keep keyState up to date as options/qIndex change
useEffect(() => {
const newKeyState = createKeyState();
if (!isEqual(newKeyState, keyState)) {
setKeyState(newKeyState);
}
}, [createKeyState, keyState]);
// Check to see if page param exists, and if it does then changing qIndex should reset it
const { currentPage, resetPage } = usePrevNextPagination({ defaultToPageOne: false });
const handleSearchKeyChange = useCallback(({ e: { target: { checked: targetIsChecked } = {} } = {}, key, value }) => {
// Set up which indexes need to change
const indicesToChange = ((value?.subIndexes?.length ?? 0) > 0) ? value.subIndexes : [key];
// If false, we must remove from the qIndex
if (!targetIsChecked) {
indicesToChange.forEach(ind => {
const indexOfKey = qIndexArray.indexOf(ind);
Eif (indexOfKey > -1) { // only splice array when item is found
qIndexArray.splice(indexOfKey, 1); // 2nd parameter means remove one item only
}
});
} else {
// If true, we need to add to qIndex
indicesToChange.forEach(ind => {
qIndexArray.push(ind);
});
}
setQIndex(qIndexArray?.join(','));
Iif (currentPage) {
resetPage();
}
}, [currentPage, qIndexArray, resetPage, setQIndex]);
return (
<>
<div className={css.searchKeyControlContainer}>
{
Object.entries(keyState).map(([key, value]) => {
/* At this point we have "key" corresponding to a searchKey option,
* and "value" an object of the shape
{
inUse: a bool determining if it is in use or not,
label: the label to display on the checkbox
}
*/
return (
<Checkbox
key={`search-key-control-${key}`}
checked={value?.inUse}
className={css.searchKeyControlElement}
label={value?.label}
onChange={e => handleSearchKeyChange({ e, key, value })}
/>
);
})
}
</div>
</>
);
};
SearchKeyControl.propTypes = {
options: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.node
]).isRequired,
key: PropTypes.string.isRequired
}))
};
export default SearchKeyControl;
|