Skip to content

Commit

Permalink
UIORGS-387: add donors fetch modal
Browse files Browse the repository at this point in the history
  • Loading branch information
alisher-epam committed Oct 27, 2023
1 parent 4a25f88 commit f155ede
Show file tree
Hide file tree
Showing 14 changed files with 570 additions and 1 deletion.
62 changes: 62 additions & 0 deletions lib/Donors/DonorsForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useCallback, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { FieldArray } from 'react-final-form-arrays';

import {
Col,
Loading,
Row,
} from '@folio/stripes/components';

import { useDonorContacts } from './FindDonors/hooks';
import DonorsFormList from './DonorsFormList';

function DonorsForm({ name, donorOrganizationIds }) {
const [donors, setDonors] = useState([]);
const { fetchDonorsMutation, isLoading } = useDonorContacts();

const handleFetchDonors = useCallback(ids => {
fetchDonorsMutation({ donorOrganizationIds: ids })
.then((data) => {
setDonors(data);
});
}, [fetchDonorsMutation]);

useEffect(() => {
handleFetchDonors(donorOrganizationIds);
}, [donorOrganizationIds, handleFetchDonors]);

const donorsMap = donors.reduce((acc, contact) => {
acc[contact.id] = contact;

return acc;
}, {});

if (isLoading) {
return <Loading />;
}

return (
<Row>
<Col xs={12}>
<FieldArray
name={name}
component={DonorsFormList}
fetchDonors={handleFetchDonors}
donorsMap={donorsMap}
/>
</Col>
</Row>
);
}

DonorsForm.propTypes = {
name: PropTypes.string.isRequired,
donorOrganizationIds: PropTypes.arrayOf(PropTypes.string),
};

DonorsForm.defaultProps = {
donorOrganizationIds: [],
};

export default DonorsForm;
157 changes: 157 additions & 0 deletions lib/Donors/DonorsFormList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import {
map,
sortBy,
} from 'lodash';
import {
FormattedMessage,
useIntl,
} from 'react-intl';

import {
Button,
Icon,
MultiColumnList,
} from '@folio/stripes/components';
import { useStripes } from '@folio/stripes/core';

import FindDonors from './FindDonors/FindDonors';
import { acqRowFormatter } from '../utils';

const columnMapping = {
name: <FormattedMessage id="stripes-acq-components.donors.column.name" />,
code: <FormattedMessage id="stripes-acq-components.donors.column.code" />,
unassignDonor: null,
};

const visibleColumns = [
'name',
'code',
'unassignDonor',
];

const getResultsFormatter = ({
intl,
fields,
}) => ({
name: donor => donor.name,
code: donor => donor.code,
unassignDonor: (donor) => (
<Button
align="end"
aria-label={intl.formatMessage({ id: 'stripes-acq-components.donors.button.unassign' })}
buttonStyle="fieldControl"
data-test-unassign-donor
type="button"
onClick={(e) => {
e.preventDefault();
fields.remove(donor._index);
}}
>
<Icon icon="times-circle" />
</Button>
),
});

const getDonorUrl = (orgId) => {
return `/organizations/view/${orgId}`;
};

const AddDonorButton = ({ fetchDonors, fields, stripes }) => {
const addDonors = (contacts = []) => {
const addedContactIds = new Set(fields.value);
const newContactsIds = map(contacts.filter(({ id }) => !addedContactIds.has(id)), 'id');

if (newContactsIds.length) {
fetchDonors([...addedContactIds, ...newContactsIds]);
newContactsIds.forEach(contactId => fields.push(contactId));
}
};

return (
<FindDonors
aria-haspopup="true"
type="find-contact"
dataKey="contact"
searchLabel={<FormattedMessage id="stripes-acq-components.donors.button.addDonor" />}
searchButtonStyle="default"
disableRecordCreation
stripes={stripes}
addDonors={addDonors}
>
<span data-test-add-donor>
<FormattedMessage id="stripes-acq-components.donors.noFindDonorPlugin" />
</span>
</FindDonors>
);
};

AddDonorButton.propTypes = {
fetchDonors: PropTypes.func.isRequired,
fields: PropTypes.object,
stripes: PropTypes.object,
};

const alignRowProps = { alignLastColToEnd: true };

const DonorsFormList = ({ fetchDonors, fields, donorsMap, orgId, categoriesDict }) => {
const intl = useIntl();
const stripes = useStripes();
const contacts = (fields.value || [])
.map((contactId, _index) => {
const contact = donorsMap?.[contactId];

return {
...(contact || { isDeleted: true }),
_index,
};
});
const contentData = sortBy(contacts, [({ lastName }) => lastName?.toLowerCase()]);

const anchoredRowFormatter = ({ rowProps, ...rest }) => {
// console.log(rowProps, rest)
return acqRowFormatter({
...rest,
rowProps: {
...rowProps,
to: getDonorUrl(rest.rowData.id),
},
});
};

const resultsFormatter = useMemo(() => {
return getResultsFormatter({ intl, categoriesDict, fields });
}, [categoriesDict, fields, intl]);

return (
<>
<MultiColumnList
id="contact-list"
columnMapping={columnMapping}
contentData={contentData}
formatter={resultsFormatter}
rowFormatter={anchoredRowFormatter}
rowProps={alignRowProps}
visibleColumns={visibleColumns}
/>
<br />
<AddDonorButton
fetchDonors={fetchDonors}
fields={fields}
stripes={stripes}
orgId={orgId}
/>
</>
);
};

DonorsFormList.propTypes = {
fetchDonors: PropTypes.func.isRequired,
fields: PropTypes.object,
orgId: PropTypes.string,
categoriesDict: PropTypes.arrayOf(PropTypes.object),
donorsMap: PropTypes.object,
};

export default DonorsFormList;
56 changes: 56 additions & 0 deletions lib/Donors/FindDonors/DonorsListFilters/DonorsListFilters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import PropTypes from 'prop-types';
import { useCallback } from 'react';

import { AccordionSet } from '@folio/stripes/components';
// import { TypeFilter } from '@folio/plugin-find-organization';

import { AcqTagsFilter } from '../../../AcqTagsFilter';
import { AcqCheckboxFilter } from '../../../AcqCheckboxFilter';
import {
DONOR_FILTERS,
DONOR_STATUS_OPTIONS,
} from '../constants';

export const DonorsListFilters = ({
activeFilters,
applyFilters,
disabled,
}) => {
const adaptedApplyFilters = useCallback(({ name, values }) => applyFilters(name, values), [applyFilters]);

return (
<AccordionSet>
{/* <TypeFilter
activeFilters={activeFilters[DONOR_FILTERS.TYPES]}
disabled={disabled}
id={`org-filter-${DONOR_FILTERS.TYPES}`}
name={DONOR_FILTERS.TYPES}
onChange={adaptedApplyFilters}
/> */}

<AcqTagsFilter
activeFilters={activeFilters[DONOR_FILTERS.TAGS]}
disabled={disabled}
id={DONOR_FILTERS.TAGS}
name={DONOR_FILTERS.TAGS}
onChange={adaptedApplyFilters}
/>

<AcqCheckboxFilter
id={DONOR_FILTERS.IS_VENDOR}
disabled={disabled}
activeFilters={activeFilters[DONOR_FILTERS.IS_VENDOR]}
labelId="stripes-acq-components.donors.filter.isVendor"
name={DONOR_FILTERS.IS_VENDOR}
onChange={adaptedApplyFilters}
options={DONOR_STATUS_OPTIONS}
/>
</AccordionSet>
);
};

DonorsListFilters.propTypes = {
activeFilters: PropTypes.object.isRequired,
applyFilters: PropTypes.func.isRequired,
disabled: PropTypes.bool,
};
1 change: 1 addition & 0 deletions lib/Donors/FindDonors/DonorsListFilters/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { DonorsListFilters } from './DonorsListFilters';
Loading

0 comments on commit f155ede

Please sign in to comment.