@selfcommunity/react-ui
Version:
React UI Components to integrate a Community created with SelfCommunity Platform.
133 lines (132 loc) • 6.46 kB
JavaScript
import { __rest } from "tslib";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Autocomplete, Avatar, Box, Fade, IconButton, styled, TextField, Typography } from '@mui/material';
import Icon from '@mui/material/Icon';
import { useEffect, useState } from 'react';
import classNames from 'classnames';
import { useThemeProps } from '@mui/system';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { SuggestionType } from '@selfcommunity/types';
import { SuggestionService } from '@selfcommunity/api-services';
import { SCPreferences, useSCPreferences } from '@selfcommunity/react-core';
const messages = defineMessages({
placeholder: {
id: 'ui.searchAutocomplete.placeholder',
defaultMessage: 'ui.searchAutocomplete.placeholder'
}
});
const PREFIX = 'SCSearchAutocomplete';
const classes = {
root: `${PREFIX}-root`,
icon: `${PREFIX}-icon`,
input: `${PREFIX}-input`,
clear: `${PREFIX}-clear`
};
const Root = styled(Autocomplete, {
name: PREFIX,
slot: 'Root',
overridesResolver: (props, styles) => styles.root
})(({ theme }) => ({
[`& .${classes.input}`]: {
flexGrow: 1
}
}));
export default function SearchAutocomplete(inProps) {
// PROPS
const props = useThemeProps({
props: inProps,
name: PREFIX
});
const { id = `${PREFIX}-autocomplete`, className, blurOnSelect, autoFocus = false, onSearch = null, onClear = null, onSuggestionSelect = (suggestion) => null } = props, rest = __rest(props, ["id", "className", "blurOnSelect", "autoFocus", "onSearch", "onClear", "onSuggestionSelect"]);
// CONTEXT
const scPreferences = useSCPreferences();
// STATE
const [value, setValue] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [options, setOptions] = useState([]);
// INTL
const intl = useIntl();
const handleInputChange = (event, value, reason) => {
switch (reason) {
case 'input':
setValue(value);
!value && setOptions([]);
break;
}
};
const handleChange = (event, value, reason, detail) => {
event.preventDefault();
event.stopPropagation();
switch (reason) {
case 'selectOption':
onSuggestionSelect && onSuggestionSelect(value);
handleClear(event);
break;
case 'createOption':
onSearch && onSearch(value);
handleClear(event);
break;
}
return false;
};
const handleClear = (event) => {
setValue('');
setOptions([]);
onClear && onClear();
};
const getOptionData = (option) => {
let data = {};
if (option.type === SuggestionType.USER) {
data.name = option[SuggestionType.USER]['username'];
data.image = option[SuggestionType.USER]['avatar'];
data.variant = 'circular';
}
else if (option.type === SuggestionType.CATEGORY) {
data.name = option[SuggestionType.CATEGORY]['name'];
data.image = option[SuggestionType.CATEGORY]['image_medium'];
data.variant = 'square';
}
else if (option.type === SuggestionType.GROUP) {
data.name = option[SuggestionType.GROUP]['name'];
data.image = option[SuggestionType.GROUP]['image_big'];
data.variant = 'circular';
}
return data;
};
function fetchResults() {
setIsLoading(true);
SuggestionService.getSearchSuggestion(value)
.then((data) => {
setIsLoading(false);
setOptions(data.results);
})
.catch((error) => {
setIsLoading(false);
console.log(error);
});
}
const optionLabel = (option) => {
var _a, _b, _c, _d;
switch (option.type) {
case SuggestionType.CATEGORY:
return `${((_a = option[option.type]) === null || _a === void 0 ? void 0 : _a.name_synonyms) || ''} ${((_b = option[option.type]) === null || _b === void 0 ? void 0 : _b.name) || ''}`.trim();
case SuggestionType.USER:
return `${((_c = option[option.type]) === null || _c === void 0 ? void 0 : _c.username) || ''} ${((_d = option[option.type]) === null || _d === void 0 ? void 0 : _d.real_name) || ''}`.trim();
default:
return option[option.type]['name'];
}
};
useEffect(() => {
if (value) {
fetchResults();
}
}, [value]);
return (_jsx(Root, Object.assign({ id: id, className: classNames(classes.root, className), blurOnSelect: blurOnSelect, onChange: handleChange, onInputChange: handleInputChange, inputValue: value, freeSolo: true, autoComplete: true, disableClearable: true, loading: isLoading, loadingText: _jsx(FormattedMessage, { id: "ui.searchAutocomplete.loading", defaultMessage: "ui.searchAutocomplete.loading" }), noOptionsText: _jsx(FormattedMessage, { id: "ui.searchAutocomplete.noOptions", defaultMessage: "ui.searchAutocomplete.noOptions" }), options: options, getOptionLabel: (option) => {
if (typeof option === 'string') {
return option;
}
return optionLabel(option);
}, renderOption: (props, option) => (_jsxs(Box, Object.assign({ component: "li" }, props, { children: [_jsx(Avatar, { alt: getOptionData(option).name, src: getOptionData(option).image, variant: getOptionData(option).variant }), _jsx(Typography, Object.assign({ ml: 1 }, { children: getOptionData(option).name }))] }))), renderInput: (params) => (_jsx(TextField, Object.assign({}, params, { placeholder: `${intl.formatMessage(messages.placeholder, {
community: scPreferences.preferences[SCPreferences.TEXT_APPLICATION_NAME].value
})}`, InputProps: Object.assign(Object.assign({}, params.InputProps), { autoFocus, name: 'search-autocomplete', className: classes.input, startAdornment: _jsx(Icon, Object.assign({ className: classes.icon }, { children: "search" })), endAdornment: (_jsx(Fade, Object.assign({ in: value.length > 0 || Boolean(onClear), appear: false }, { children: _jsx(IconButton, Object.assign({ className: classes.clear, onClick: handleClear, size: "small" }, { children: _jsx(Icon, { children: "close" }) })) }))) }) }))) }, rest)));
}