123123

123123

123123


/* eslint-disable */
import Fuse from 'fuse.js';
import FormControl from '@material-ui/core/FormControl';
import FormHelperText from '@material-ui/core/FormHelperText';
import InputLabel from '@material-ui/core/InputLabel';
import OutlinedInput from '@material-ui/core/OutlinedInput';
import PropTypes from 'prop-types';
import React from 'react';
import ReactDOM from 'react-dom';
import SelectMUI from '@material-ui/core/Select';
import Show from '@reviewpro/js-browser/lib/Show';

import Checkbox from '../Checkbox';
import Search from '../icons/Search';
import TextField from '../TextField';
import Typography from '../Typography';
import withStyles from '../styles/withStyles';
import FullScreenDelegator from '../FullScreenDelegator';

const ITEM_HEIGHT = 46;
const TEXT_FIELD_HEIGHT = 56;

const customIdNameValidator = (props, propName, componentName) => {
    const { id, name } = props;

    if (!id && !name) {
        return new Error(`${componentName} required a id or name prop`);
    }

    return null;
};

const styles = ({ palette, spacing, zIndex }) => ({
    filter: {
        margin: `${spacing.unit}px`,
    },
    formControl: {
        width: '100%',
    },
    input: {
        height: '24px',
        paddingBottom: `${spacing.unit}px`,
        paddingLeft: `${spacing.unit}px`,
        paddingRight: `${spacing.unit * 4}px`,
        paddingTop: `${spacing.unit * 2}px`,
    },
    inputFocused: {
        color: palette.secondary.main,
    },
    inputLabel: {
        '&$inputFocused': {
            color: palette.secondary.main,
        },
    },
    inputOutlinedInput: {
        '&$inputFocused $notchedOutline': {
            borderColor: palette.secondary.main,
        },
    },
    modal: {
        // TODO: Fix this after refactor of MobileFullScreen components
        zIndex: zIndex.tooltip,
    },
    notchedOutline: {},
    outlined: {
        '&$shrink': {
            transform: 'translate(14px, -6px) scale(0.75)',
        },
        pointerEvents: 'none',
        transform: 'translate(16px, 16px) scale(1)',
        zIndex: 1,
    },
    rootList: {
        backgroundColor: 'inherit',
    },
    shrink: {
        transform: 'translate(14px, -6px) scale(0.75)',
    },
});

class Select extends React.Component {
    static getDerivedStateFromProps(nextProps, prevState) {
        if (prevState.value !== nextProps.value) {
            return {
                ...prevState,
                value: nextProps.value,
            };
        }

        return null;
    }

    constructor(props) {
        super(props);

        this.state = {
            filter: '',
            handleResize: () => {},
            labelWidth: 0,
            focused: false,
            value: props.value,
        };
    }

    componentDidMount() {
        this.setState({
            labelWidth: ReactDOM.findDOMNode(this.InputLabelRef).offsetWidth,
        });
    }

    handleFocus = () => {
        this.setState({ focused: true });
    };

    handleBlur = () => {
        this.setState({ focused: false });
    };

    renderValue = item => {
        const { allSelectedText, children, partiallySelectedText } = this.props;
        const selectedChildren = React.Children.toArray(children).filter(({ props }) => item.includes(props.value));

        let resultString;
        if (allSelectedText && partiallySelectedText) {
            if (selectedChildren.length > 1) {
                const isAllSelected = selectedChildren.length === React.Children.toArray(children).length;

                if (isAllSelected) {
                    resultString = allSelectedText;
                } else {
                    resultString = partiallySelectedText;
                }
            } else if (selectedChildren.length) {
                resultString = selectedChildren[0].props.children;
            }
        } else {
            resultString = selectedChildren.map(child => child.props.children).join(', ');
        }

        return resultString;
    };

    render() {
        const { allSelectedText, children, classes, disabled, helperText, id, label, minItems, multiple, name, noItemsText, onChange, ...props } = this.props;
        const { filter, labelWidth, focused, handleResize, value } = this.state;
        let extendedProps = {};
        let items = React.Children.toArray(children);
        console.log(items);
        const trimFilter = filter.trim().toLowerCase();
        if (trimFilter) {
            if (multiple && allSelectedText) {
                items.shift();
            }
            items = items.filter(({ props: p }) => {
                const searchObject = [
                    {
                        child: typeof p.children === 'string' || p.children instanceof String ? p.children : undefined,
                        searchFields: (Array.isArray(p.searchFields) ? p.searchFields : Array.of(p.searchFields))
                            .filter(field => !!field)
                            .map(field => field.toString()),
                        value: p.value,
                    },
                ];
                const fuseValues = new Fuse(searchObject, {
                    distance: 100,
                    keys: ['child', 'searchFields', 'value'],
                    location: 0,
                    matchAllTokens: true,
                    maxPatternLength: 32,
                    minMatchCharLength: 1,
                    threshold: 0.3,
                    tokenize: true,
                });
                return !!fuseValues.search(trimFilter).length;
            });
        }

        if (multiple && Array.isArray(value)) {
            extendedProps = {
                renderValue: this.renderValue,
            };
            items = items.map(child =>
                React.cloneElement(
                    child,
                    {},
                    <React.Fragment>
                        <Checkbox checked={value.includes(child.props.value)} />
                        {child.props.children}
                    </React.Fragment>
                )
            );
        }

        const handleItemClick = item => {
            console.log(item);
            debugger;
            setState({ value: item.value, focused: false });
        };

        items = items.map(item => {
            React.cloneElement(item, {
                onClick: (...args) => {
                    handleItemClick(item);
                    item.onClick && item.onClick(...args);
                },
            });
        });

        return (
            <FormControl className={classes.formControl} variant="outlined">
                <InputLabel
                    classes={{
                        focused: classes.inputFocused,
                        outlined: classes.outlined,
                        root: classes.inputLabel,
                        shrink: classes.shrink,
                    }}
                    htmlFor={id || name}
                    ref={ref => {
                        this.InputLabelRef = ref;
                    }}
                >
                    {label}
                </InputLabel>
                <SelectMUI
                    {...props}
                    {...extendedProps}
                    input={
                        <OutlinedInput
                            classes={{
                                focused: classes.inputFocused,
                                input: classes.input,
                                notchedOutline: classes.notchedOutline,
                                root: classes.inputOutlinedInput,
                            }}
                            disabled={disabled}
                            id={id || name}
                            labelWidth={labelWidth}
                            name={name || id}
                        />
                    }
                    MenuProps={{
                        action: actions => this.setState({ handleResize: actions.updatePosition }),
                        anchorOrigin: {
                            horizontal: 'center',
                            vertical: 'center',
                        },
                        disableAutoFocusItem: React.Children.count(children) > minItems,
                        getContentAnchorEl: null,
                        MenuListProps: {
                            classes: {
                                root: classes.rootList,
                            },
                            disablePadding: true,
                        },
                        onExited: () => {
                            this.setState({ filter: '' });
                            handleResize();
                        },
                        PaperProps: {
                            style: {
                                // This will show minItems and a half item to display scroll
                                // It also prevent the size of the filter text field
                                maxHeight: ITEM_HEIGHT * minItems + (React.Children.count(children) > minItems ? TEXT_FIELD_HEIGHT : 0) + ITEM_HEIGHT * 0.5,
                            },
                        },
                        transformOrigin: {
                            horizontal: 'center',
                            vertical: 'center',
                        },
                    }}
                    multiple={multiple}
                    onChange={onChange}
                    onOpen={this.handleFocus}
                    value={value}
                >
                    <Show condition={React.Children.count(children) > minItems}>
                        <div className={classes.filter}>
                            <TextField
                                onFocus={this.handleFocus}
                                autoFocus
                                icon={Search}
                                onChange={event => {
                                    this.setState({ filter: event.target.value });
                                    handleResize();
                                }}
                                placeholder={label}
                                type="text"
                                value={filter}
                            />
                        </div>
                    </Show>
                    <Show condition={!!(items.length <= 0 && noItemsText)}>
                        <Typography variant="caption">{noItemsText}</Typography>
                    </Show>
                    {items}
                </SelectMUI>
                {focused && (
                    <FullScreenDelegator>
                        <Show condition={React.Children.count(children) > minItems}>
                            <div className={classes.filter}>
                                <TextField
                                    onFocus={this.handleFocus}
                                    autoFocus
                                    icon={Search}
                                    onChange={event => {
                                        this.setState({ filter: event.target.value });
                                        handleResize();
                                    }}
                                    placeholder={label}
                                    type="text"
                                    value={filter}
                                />
                            </div>
                        </Show>
                        <Show condition={!!(items.length <= 0 && noItemsText)}>
                            <Typography variant="caption">{noItemsText}</Typography>
                        </Show>
                        {items}
                    </FullScreenDelegator>
                )}
                <Show condition={!!helperText}>
                    <FormHelperText>{helperText}</FormHelperText>
                </Show>
            </FormControl>
        );
    }
}

/**
 * Definition of props types
 *
 * @param {string}    allSelectedText - This string shows when Select has more
 *                                      than 1 item and all of them are selected
 * @param {node}          children    - A node to render as an icon
 * @param {Object}        classes     - A serie of clases defined in the styles
 * @param {bool}          disabled    - Bool to disable component
 * @param {string}        helperText  - String to show in the bottom
 * @param {string}        label       - Label to show inside/top component
 * @param {string}        id          - Identifier for component
 * @param {number}        minItems    - The number of min items to show the
 *                                      filter box
 * @param {bool}          multiple    - Bool to enable multiple selection
 * @param {string}        name        - Component name
 * @param {func}          onChange    - Callback function fired when a menu item
 *                                      is selected. "Event" is received, you
 *                                      can pick the value with
 *                                      "event.target.value"
 * @param {string}        noItemsText - The string to show when no items found
 *                                      with the filter in the box
 * @param {string} partiallySelectedText - String to show when Select have more
 *                                         than 1 item, but not all of them are
 *                                         selected
 * @param {string|array}  value       - The value or values (multiple) selected
 */
Select.propTypes = {
    allSelectedText: PropTypes.string,
    children: PropTypes.node.isRequired,
    classes: PropTypes.object.isRequired,
    disabled: PropTypes.bool,
    helperText: PropTypes.string,
    id: customIdNameValidator,
    label: PropTypes.string.isRequired,
    minItems: PropTypes.number,
    multiple: PropTypes.bool,
    name: customIdNameValidator,
    noItemsText: PropTypes.string,
    onChange: PropTypes.func.isRequired,
    partiallySelectedText: PropTypes.string,
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array]).isRequired,
};

Select.defaultProps = {
    allSelectedText: '',
    disabled: false,
    helperText: '',
    id: null,
    minItems: 10,
    multiple: false,
    name: null,
    noItemsText: '',
    partiallySelectedText: '',
};

Select.rpName = 'Select';

export default withStyles(styles)(Select);


Report Page