UNPKG

@selfcommunity/react-ui

Version:

React UI Components to integrate a Community created with SelfCommunity Platform.

133 lines (132 loc) • 6.46 kB
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))); }