Coursemology/coursemology2

View on GitHub
client/app/lib/components/form/fields/MultiSelectField.jsx

Summary

Maintainability
A
1 hr
Test Coverage
import { memo } from 'react';
import { Autocomplete, TextField } from '@mui/material';
import PropTypes from 'prop-types';

import { formatErrorMessage } from 'lib/components/form/fields/utils/mapError';

import propsAreEqual from './utils/propsAreEqual';

const styles = {
  listboxStyle: {
    maxHeight: '80vh',
    overflowY: 'auto',
  },
};

const FormMultiSelectField = (props) => {
  const { field, fieldState, disabled, label, options, renderIf, ...custom } =
    props;
  if (!renderIf) {
    return null;
  }
  const selectedOptions = field.value.map((v) =>
    options.find((o) => o.id === v),
  );

  return (
    <Autocomplete
      {...field}
      disabled={disabled}
      filterSelectedOptions
      fullWidth
      getOptionLabel={(option) => option.title}
      isOptionEqualToValue={(option, val) => option.id === val.id}
      ListboxProps={{ style: styles.listboxStyle }}
      multiple
      onChange={(event, val) => {
        const selectedOptionIds = val.map((option) => option.id);
        field.onChange(selectedOptionIds);
      }}
      options={options}
      value={selectedOptions}
      {...custom}
      renderInput={(params) => (
        <TextField
          {...params}
          error={!!fieldState.error}
          helperText={
            fieldState.error && formatErrorMessage(fieldState.error.message)
          }
          InputLabelProps={{
            shrink: true,
          }}
          label={label}
          variant="standard"
        />
      )}
    />
  );
};

FormMultiSelectField.defaultProps = {
  renderIf: true,
};

export const optionShape = PropTypes.shape({
  id: PropTypes.number,
  title: PropTypes.string,
});

FormMultiSelectField.propTypes = {
  field: PropTypes.object.isRequired,
  fieldState: PropTypes.object.isRequired,
  disabled: PropTypes.bool,
  label: PropTypes.node,
  options: PropTypes.arrayOf(optionShape),
  renderIf: PropTypes.bool,
};

export default memo(FormMultiSelectField, propsAreEqual);