|
| 1 | +import { map, sortBy, uniqBy } from 'lodash'; |
| 2 | +import { |
| 3 | + useCallback, |
| 4 | + useEffect, |
| 5 | + useMemo, |
| 6 | + useState, |
| 7 | +} from 'react'; |
| 8 | +import PropTypes from 'prop-types'; |
| 9 | +import { FormattedMessage, useIntl } from 'react-intl'; |
| 10 | + |
| 11 | +import { MultiSelection } from '@folio/stripes/components'; |
| 12 | + |
| 13 | +import { |
| 14 | + DonorsLookup, |
| 15 | + useFetchDonors, |
| 16 | +} from '../Donors'; |
| 17 | +import { FilterAccordion } from '../FilterAccordion'; |
| 18 | + |
| 19 | +export const PluggableDonorsFilter = ({ |
| 20 | + id, |
| 21 | + activeFilters, |
| 22 | + closedByDefault, |
| 23 | + disabled, |
| 24 | + labelId, |
| 25 | + name, |
| 26 | + onChange, |
| 27 | +}) => { |
| 28 | + const { donors } = useFetchDonors(activeFilters); |
| 29 | + const [selectedDonors, setSelectedDonors] = useState([]); |
| 30 | + |
| 31 | + useEffect(() => { |
| 32 | + // set initial selected donors from active filters prop |
| 33 | + if (activeFilters?.length && !selectedDonors?.length) { |
| 34 | + setSelectedDonors(donors); |
| 35 | + } |
| 36 | + }, [activeFilters, donors, selectedDonors]); |
| 37 | + |
| 38 | + const onSelectDonor = useCallback((values) => { |
| 39 | + const updatedDonorIds = uniqBy([...donors, ...values], 'id'); |
| 40 | + |
| 41 | + setSelectedDonors(updatedDonorIds); |
| 42 | + onChange({ |
| 43 | + name, |
| 44 | + values: map(updatedDonorIds, 'id'), |
| 45 | + }); |
| 46 | + }, [donors, name, onChange]); |
| 47 | + |
| 48 | + const onRemove = useCallback((donor) => { |
| 49 | + const updatedDonorIds = selectedDonors.filter(({ id: donorId }) => donorId !== donor.value); |
| 50 | + |
| 51 | + setSelectedDonors(updatedDonorIds); |
| 52 | + onChange({ |
| 53 | + name, |
| 54 | + values: map(updatedDonorIds, 'id'), |
| 55 | + }); |
| 56 | + }, [name, onChange, selectedDonors]); |
| 57 | + |
| 58 | + const intl = useIntl(); |
| 59 | + const label = intl.formatMessage({ id: labelId }); |
| 60 | + const dataOptions = useMemo(() => { |
| 61 | + return selectedDonors.map(donor => ({ value: donor.id, label: donor.name })); |
| 62 | + }, [selectedDonors]); |
| 63 | + |
| 64 | + const onClearAll = () => { |
| 65 | + onChange({ |
| 66 | + name, |
| 67 | + values: [], |
| 68 | + }); |
| 69 | + setSelectedDonors([]); |
| 70 | + }; |
| 71 | + |
| 72 | + return ( |
| 73 | + <FilterAccordion |
| 74 | + activeFilters={activeFilters} |
| 75 | + closedByDefault={closedByDefault} |
| 76 | + disabled={disabled} |
| 77 | + id={id} |
| 78 | + labelId={labelId} |
| 79 | + name={name} |
| 80 | + onChange={onClearAll} |
| 81 | + > |
| 82 | + <MultiSelection |
| 83 | + id="input-tag" |
| 84 | + aria-label={label} |
| 85 | + disabled |
| 86 | + dataOptions={sortBy(dataOptions, ['value'])} |
| 87 | + value={sortBy(dataOptions, ['value'])} |
| 88 | + onRemove={onRemove} |
| 89 | + /> |
| 90 | + <DonorsLookup |
| 91 | + searchButtonStyle="link" |
| 92 | + onAddDonors={onSelectDonor} |
| 93 | + searchLabel={<FormattedMessage id="stripes-acq-components.filter.donor.lookup" />} |
| 94 | + /> |
| 95 | + </FilterAccordion> |
| 96 | + ); |
| 97 | +}; |
| 98 | + |
| 99 | +PluggableDonorsFilter.propTypes = { |
| 100 | + activeFilters: PropTypes.arrayOf(PropTypes.string), |
| 101 | + closedByDefault: PropTypes.bool, |
| 102 | + disabled: PropTypes.bool, |
| 103 | + id: PropTypes.string, |
| 104 | + labelId: PropTypes.string.isRequired, |
| 105 | + name: PropTypes.string.isRequired, |
| 106 | + onChange: PropTypes.func.isRequired, |
| 107 | +}; |
| 108 | + |
| 109 | +PluggableDonorsFilter.defaultProps = { |
| 110 | + closedByDefault: true, |
| 111 | + disabled: false, |
| 112 | +}; |
0 commit comments