RocketChat/Rocket.Chat

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

Summary

Maintainability
A
2 hrs
Test Coverage
import { CheckOption, PaginatedMultiSelectFiltered } from '@rocket.chat/fuselage';
import type { PaginatedMultiSelectOption } from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { ComponentProps } from 'react';
import React, { memo, useMemo, useState } from 'react';

import { useRecordList } from '../hooks/lists/useRecordList';
import { AsyncStatePhase } from '../hooks/useAsyncState';
import { useDepartmentsList } from './Omnichannel/hooks/useDepartmentsList';

type AutoCompleteDepartmentMultipleProps = {
    value?: PaginatedMultiSelectOption[];
    onChange: (value: PaginatedMultiSelectOption[]) => void;
    onlyMyDepartments?: boolean;
    showArchived?: boolean;
    enabled?: boolean;
} & Omit<ComponentProps<typeof PaginatedMultiSelectFiltered>, 'options'>;

const AutoCompleteDepartmentMultiple = ({
    value = [],
    onlyMyDepartments = false,
    showArchived = false,
    enabled = false,
    onChange = () => undefined,
}: AutoCompleteDepartmentMultipleProps) => {
    const t = useTranslation();
    const [departmentsFilter, setDepartmentsFilter] = useState('');

    const debouncedDepartmentsFilter = useDebouncedValue(departmentsFilter, 500);

    const { itemsList: departmentsList, loadMoreItems: loadMoreDepartments } = useDepartmentsList(
        useMemo(
            () => ({ filter: debouncedDepartmentsFilter, onlyMyDepartments, ...(showArchived && { showArchived: true }), enabled }),
            [debouncedDepartmentsFilter, enabled, onlyMyDepartments, showArchived],
        ),
    );

    const { phase: departmentsPhase, items: departmentsItems, itemCount: departmentsTotal } = useRecordList(departmentsList);

    const departmentOptions = useMemo(() => {
        const pending = value.filter(({ value }) => !departmentsItems.find((dep) => dep.value === value)) || [];
        return [...departmentsItems, ...pending];
    }, [departmentsItems, value]);

    return (
        <PaginatedMultiSelectFiltered
            withTitle
            value={value}
            onChange={onChange}
            filter={departmentsFilter}
            setFilter={setDepartmentsFilter}
            options={departmentOptions}
            width='100%'
            flexShrink={0}
            flexGrow={0}
            placeholder={t('Select_an_option')}
            endReached={
                departmentsPhase === AsyncStatePhase.LOADING
                    ? () => undefined
                    : (start?: number) => {
                            if (start === undefined) {
                                return;
                            }
                            return loadMoreDepartments(start, Math.min(50, departmentsTotal));
                      }
            }
            renderItem={({ label, ...props }) => (
                <CheckOption
                    {...props}
                    label={<span style={{ whiteSpace: 'normal' }}>{label}</span>}
                    selected={value.some((item) => item.value === props.value)}
                />
            )}
        />
    );
};

export default memo(AutoCompleteDepartmentMultiple);