RocketChat/Rocket.Chat

View on GitHub
apps/meteor/client/components/UserAutoComplete/UserAutoComplete.tsx

Summary

Maintainability
A
2 hrs
Test Coverage
import { AutoComplete, Option, Box, Chip } from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import { UserAvatar } from '@rocket.chat/ui-avatar';
import { useEndpoint } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';
import type { ComponentProps, ReactElement } from 'react';
import React, { memo, useMemo, useState } from 'react';

const query = (
    term = '',
    conditions = {},
): {
    selector: string;
} => ({ selector: JSON.stringify({ term, conditions }) });

type UserAutoCompleteProps = Omit<ComponentProps<typeof AutoComplete>, 'filter'> & {
    conditions?: { [key: string]: unknown };
};

const UserAutoComplete = ({ value, onChange, ...props }: UserAutoCompleteProps): ReactElement => {
    const { conditions = {} } = props;
    const [filter, setFilter] = useState('');
    const debouncedFilter = useDebouncedValue(filter, 1000);
    const usersAutoCompleteEndpoint = useEndpoint('GET', '/v1/users.autocomplete');

    const { data } = useQuery(['usersAutoComplete', debouncedFilter, conditions], async () =>
        usersAutoCompleteEndpoint(query(debouncedFilter, conditions)),
    );

    const options = useMemo(() => data?.items.map((user) => ({ value: user.username, label: user.name || user.username })) || [], [data]);

    return (
        <AutoComplete
            {...props}
            value={value}
            onChange={onChange}
            filter={filter}
            setFilter={setFilter}
            data-qa-id='UserAutoComplete'
            renderSelected={({ selected: { value, label } }): ReactElement | null => (
                <Chip height='x20' value={value} mie={4}>
                    <UserAvatar size='x20' username={value} />
                    <Box verticalAlign='middle' is='span' margin='none' mi={4}>
                        {label}
                    </Box>
                </Chip>
            )}
            renderItem={({ value, label, ...props }): ReactElement => (
                <Option key={value} label={label} avatar={<UserAvatar size='x20' username={value} />} {...props} />
            )}
            options={options}
        />
    );
};

export default memo(UserAutoComplete);