Skip to content

Commit

Permalink
Revert "Updates to AddClaimantModal (#14202)" (#14434)
Browse files Browse the repository at this point in the history
This reverts commit 9b70c85.

build and bake are failing. Likely a .js dependency in assets precompile step.
  • Loading branch information
pkarman authored May 29, 2020
1 parent 9b70c85 commit 7908ca0
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 641 deletions.
120 changes: 53 additions & 67 deletions client/app/components/SearchableDropdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const NO_RESULTS_TEXT = 'Not an option';
const DEFAULT_PLACEHOLDER = 'Select option';

class SearchableDropdown extends React.Component {

constructor(props) {
super(props);

Expand Down Expand Up @@ -42,19 +43,17 @@ class SearchableDropdown extends React.Component {
this.setState({ value: newValue });
}

if (
this.state.value &&
value &&
Array.isArray(value) &&
Array.isArray(this.state.value) &&
value.length < this.state.value.length
) {
if (this.state.value &&
value &&
Array.isArray(value) &&
Array.isArray(this.state.value) &&
value.length < this.state.value.length) {
deletedValue = _.differenceWith(this.state.value, value, _.isEqual);
}
if (this.props.onChange) {
this.props.onChange(newValue, deletedValue);
}
};
}

// Override the default keys to create a new tag (allows creating options that contain a comma)
shouldKeyDownEventCreateNewOption = ({ keyCode }) => {
Expand Down Expand Up @@ -82,9 +81,6 @@ class SearchableDropdown extends React.Component {
const {
async,
options,
filterOption,
filterOptions,
loading,
placeholder,
errorMessage,
label,
Expand Down Expand Up @@ -118,10 +114,12 @@ class SearchableDropdown extends React.Component {
* custom tag entered already exits.
* promptTextCreator: this is a function called to show the text when a tag
* entered doesn't exist in the current list of options.
*/
*/
if (creatable) {
addCreatableOptions = {
noResultsText: _.get(creatableOptions, 'tagAlreadyExistsMsg', TAG_ALREADY_EXISTS_MSG),
noResultsText: _.get(
creatableOptions, 'tagAlreadyExistsMsg', TAG_ALREADY_EXISTS_MSG
),

// eslint-disable-next-line no-shadow
newOptionCreator: ({ label, labelKey, valueKey }) => ({
Expand All @@ -146,46 +144,44 @@ class SearchableDropdown extends React.Component {
addCreatableOptions.noResultsText = '';
}

const labelContents = (
const labelContents =
<span>
{label || name}
{required && <span className="cf-required">Required</span>}
</span>
);

return (
<div className={dropdownClasses} {...dropdownStyling}>
<label className={labelClasses} htmlFor={name}>
{strongLabel ? <strong>{labelContents}</strong> : labelContents}
</label>
<div className={errorMessage ? 'usa-input-error' : ''}>
{errorMessage && <span className="usa-input-error-message">{errorMessage}</span>}
<SelectComponent
inputProps={{
id: name,
autoComplete: 'off'
}}
options={options}
filterOption={filterOption}
filterOptions={filterOptions}
loadOptions={async}
isLoading={loading}
onChange={this.onChange}
value={this.state.value}
placeholder={placeholder === null ? DEFAULT_PLACEHOLDER : placeholder}
clearable={false}
noResultsText={noResultsText ? noResultsText : NO_RESULTS_TEXT}
searchable={searchable}
disabled={readOnly}
multi={multi}
cache={false}
onBlurResetsInput={false}
shouldKeyDownEventCreateNewOption={this.shouldKeyDownEventCreateNewOption}
{...addCreatableOptions}
/>
</div>
</span>;

return <div className={dropdownClasses} {...dropdownStyling}>
<label className={labelClasses} htmlFor={name}>
{
strongLabel ?
<strong>{labelContents}</strong> :
labelContents
}
</label>
<div className={errorMessage ? 'usa-input-error' : ''}>
{errorMessage && <span className="usa-input-error-message">{errorMessage}</span>}
<SelectComponent
inputProps={{
id: name,
autoComplete: 'off'
}}
options={options}
loadOptions={async}
onChange={this.onChange}
value={this.state.value}
placeholder={placeholder === null ? DEFAULT_PLACEHOLDER : placeholder}
clearable={false}
noResultsText={noResultsText ? noResultsText : NO_RESULTS_TEXT}
searchable={searchable}
disabled={readOnly}
multi={multi}
cache={false}
onBlurResetsInput={false}
shouldKeyDownEventCreateNewOption={this.shouldKeyDownEventCreateNewOption}
{...addCreatableOptions}
/>
</div>
);
</div>;
}
}

Expand All @@ -198,23 +194,21 @@ SearchableDropdown.propTypes = {
}),
dropdownStyling: PropTypes.object,
errorMessage: PropTypes.string,
filterOption: PropTypes.func,
filterOptions: PropTypes.func,
label: PropTypes.string,
strongLabel: PropTypes.bool,
hideLabel: PropTypes.bool,
loading: PropTypes.bool,
multi: PropTypes.bool,
name: PropTypes.string.isRequired,
noResultsText: PropTypes.string,
onChange: PropTypes.func,
options: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.any,
label: PropTypes.string
})
),
placeholder: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
options: PropTypes.arrayOf(PropTypes.shape({
value: PropTypes.any,
label: PropTypes.string
})),
placeholder: PropTypes.oneOfType([
PropTypes.string,
PropTypes.object
]),
readOnly: PropTypes.bool,
required: PropTypes.bool,
searchable: PropTypes.bool,
Expand All @@ -223,12 +217,4 @@ SearchableDropdown.propTypes = {
value: PropTypes.object
};

/* eslint-disable no-undefined */
SearchableDropdown.defaultProps = {
loading: false,
filterOption: undefined,
filterOptions: undefined
};
/* eslint-enable no-undefined */

export default SearchableDropdown;
82 changes: 22 additions & 60 deletions client/app/intake/components/AddClaimantModal.jsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,31 @@
import React, { useState, useMemo } from 'react';
import React, { useState, useMemo, useEffect } from 'react';
import PropTypes from 'prop-types';
import { debounce } from 'lodash';
import Modal from '../../components/Modal';
import { ADD_CLAIMANT_MODAL_TITLE, ADD_CLAIMANT_MODAL_DESCRIPTION } from '../../../COPY';
import ReactMarkdown from 'react-markdown';
import SearchableDropdown from '../../components/SearchableDropdown';
import ApiUtil from '../../util/ApiUtil';

const relationshipOpts = [{ label: 'Attorney (previously or currently)', value: 'attorney' }];
const sampleData = [
{ id: 1, fullName: 'Attorney 1', cssId: 'CSS_ID_1', participantId: 1 },
{ id: 2, fullName: 'Attorney 2', cssId: 'CSS_ID_2', participantId: 2 },
{ id: 3, fullName: 'Attorney 3', cssId: 'CSS_ID_3', participantId: 3 }
];

const fetchAttorneys = async (search = '') => {
const res = await ApiUtil.get('/intake/attorneys', { query: { query: search } });

return res?.body;
};
const debouncedFetch = (fetchFn) => debounce(fetchFn, 250, { leading: true, trailing: false });
const getClaimantOpts = async (search = '', asyncFn) => {
// Enforce minimum search length (we'll simply return empty array rather than throw error)
const options =
search.length < 3 ?
[] :
(await debouncedFetch(asyncFn)(search)).map((item) => ({
label: item.name,
value: item.participant_id
}));

return { options };
};
// We'll show all items returned from the backend instead of using default substring matching
const filterOptions = (options) => options;

export const AddClaimantModal = ({ onCancel, onSubmit, onSearch = fetchAttorneys }) => {
export const AddClaimantModal = ({ onCancel, onSubmit }) => {
const [claimant, setClaimant] = useState(null);
const [loading, setLoading] = useState(false);
const [relationship, setRelationship] = useState(relationshipOpts[0]);
const [searchResults] = useState(sampleData);
const [dropdownOpts, setDropdownOpts] = useState([]);
const isInvalid = useMemo(() => !claimant, [claimant]);
const handleChangeRelationship = (value) => setRelationship(value);
const handleChangeClaimant = (value) => setClaimant(value);
const asyncFn = async (search) => {
setLoading(true);
const results = await getClaimantOpts(search, onSearch);

setLoading(false);
const handleChange = (value) => setClaimant(value);

return results;
};
useEffect(() => {
setDropdownOpts(
searchResults.map((item) => ({
label: item.fullName,
value: item.participantId
}))
);
}, [searchResults]);

const buttons = [
{
Expand All @@ -55,41 +36,22 @@ export const AddClaimantModal = ({ onCancel, onSubmit, onSearch = fetchAttorneys
{
classNames: ['usa-button', 'usa-button-primary'],
name: 'Add this claimant',
onClick: () => onSubmit({ name: claimant.label, participantId: claimant.value }),
onClick: () => onSubmit({ participantId: claimant.value }),
disabled: isInvalid
}
];

return (
<Modal title={ADD_CLAIMANT_MODAL_TITLE} buttons={buttons} closeHandler={onCancel} id="add_claimant_modal">
<Modal title={ADD_CLAIMANT_MODAL_TITLE} buttons={buttons} closeHandler={onCancel}>
<div>
<ReactMarkdown source={ADD_CLAIMANT_MODAL_DESCRIPTION} />
</div>
<SearchableDropdown
name="relationship"
label="Claimant's relationship to the veteran"
onChange={handleChangeRelationship}
value={relationship}
options={relationshipOpts}
debounce={250}
/>
<SearchableDropdown
name="claimant"
label="Claimant's name"
onChange={handleChangeClaimant}
value={claimant}
filterOptions={filterOptions}
async={asyncFn}
loading={loading}
options={[]}
debounce={250}
/>
<SearchableDropdown label="Claimant's name" options={dropdownOpts} onChange={handleChange} value={claimant} />
</Modal>
);
};

AddClaimantModal.propTypes = {
onCancel: PropTypes.func,
onSubmit: PropTypes.func,
onSearch: PropTypes.func
onSubmit: PropTypes.func
};
20 changes: 1 addition & 19 deletions client/app/intake/components/AddClaimantModal.stories.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import faker from 'faker';

import { action } from '@storybook/addon-actions';
import { AddClaimantModal } from './AddClaimantModal';
Expand All @@ -10,25 +9,8 @@ export default {
decorators: []
};

// Set up sample data & async fn for performing fuzzy search
// Actual implementation performs fuzzy search via backend ruby gem
const totalRecords = 500;
const data = Array.from({ length: totalRecords }, () => ({
name: faker.name.findName(),
participant_id: faker.random.number({ min: 600000000, max: 600000000 + totalRecords })
}));
const performQuery = async (search = '') => {
const regex = RegExp(search, 'i');

return data.filter((item) => regex.test(item.name));
};

export const standard = () => (
<AddClaimantModal
onCancel={action('cancel', 'standard')}
onSubmit={action('submit', 'standard')}
onSearch={performQuery}
/>
<AddClaimantModal onCancel={action('cancel', 'standard')} onSubmit={action('submit', 'standard')} />
);

standard.story = {
Expand Down
Loading

0 comments on commit 7908ca0

Please sign in to comment.