RocketChat/Rocket.Chat

View on GitHub
apps/meteor/client/components/Omnichannel/modals/ForwardChatModal.tsx

Summary

Maintainability
A
1 hr
Test Coverage
import type { IOmnichannelRoom } from '@rocket.chat/core-typings';
import {
    Field,
    FieldGroup,
    Button,
    TextAreaInput,
    Modal,
    Box,
    PaginatedSelectFiltered,
    Divider,
    FieldLabel,
    FieldRow,
    Option,
} from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import { useEndpoint, useSetting, useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';

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

const ForwardChatModal = ({
    onForward,
    onCancel,
    room,
    ...props
}: {
    onForward: (departmentId?: string, userId?: string, comment?: string) => Promise<void>;
    onCancel: () => void;
    room: IOmnichannelRoom;
}): ReactElement => {
    const t = useTranslation();
    const getUserData = useEndpoint('GET', '/v1/users.info');
    const idleAgentsAllowedForForwarding = useSetting('Livechat_enabled_when_agent_idle') as boolean;

    const {
        getValues,
        handleSubmit,
        register,
        setFocus,
        setValue,
        watch,
        formState: { isSubmitting },
    } = useForm();

    useEffect(() => {
        setFocus('comment');
    }, [setFocus]);

    const department = watch('department');
    const username = watch('username');

    const [departmentsFilter, setDepartmentsFilter] = useState<string | number | undefined>('');
    const debouncedDepartmentsFilter = useDebouncedValue(departmentsFilter, 500);

    const { itemsList: departmentsList, loadMoreItems: loadMoreDepartments } = useDepartmentsList(
        useMemo(() => ({ filter: debouncedDepartmentsFilter as string, enabled: true }), [debouncedDepartmentsFilter]),
    );
    const { phase: departmentsPhase, items: departments, itemCount: departmentsTotal } = useRecordList(departmentsList);

    const endReached = useCallback(
        (start) => {
            if (departmentsPhase !== AsyncStatePhase.LOADING) {
                loadMoreDepartments(start, Math.min(50, departmentsTotal));
            }
        },
        [departmentsPhase, departmentsTotal, loadMoreDepartments],
    );

    const onSubmit = useCallback(
        async ({ department: departmentId, username, comment }) => {
            let uid;

            if (username) {
                const { user } = await getUserData({ username });
                uid = user?._id;
            }

            await onForward(departmentId, uid, comment);
        },
        [getUserData, onForward],
    );

    useEffect(() => {
        register('department');
        register('username');
    }, [register]);

    return (
        <Modal
            wrapperFunction={(props) => <Box is='form' onSubmit={handleSubmit(onSubmit)} {...props} />}
            {...props}
            data-qa-id='forward-chat-modal'
        >
            <Modal.Header>
                <Modal.Icon name='baloon-arrow-top-right' />
                <Modal.Title>{t('Forward_chat')}</Modal.Title>
                <Modal.Close onClick={onCancel} />
            </Modal.Header>
            <Modal.Content fontScale='p2'>
                <FieldGroup>
                    <Field>
                        <FieldLabel>{t('Forward_to_department')}</FieldLabel>
                        <FieldRow>
                            <PaginatedSelectFiltered
                                withTitle={false}
                                filter={departmentsFilter as string}
                                setFilter={setDepartmentsFilter}
                                options={departments}
                                maxWidth='100%'
                                placeholder={t('Select_an_option')}
                                data-qa-id='forward-to-department'
                                onChange={(value: string): void => {
                                    setValue('department', value);
                                }}
                                flexGrow={1}
                                endReached={endReached}
                                renderItem={({ label, ...props }) => <Option {...props} label={<span style={{ whiteSpace: 'normal' }}>{label}</span>} />}
                            />
                        </FieldRow>
                    </Field>
                    <Divider p={0} children={t('or')} />
                    <Field>
                        <FieldLabel>{t('Forward_to_user')}</FieldLabel>
                        <FieldRow>
                            <AutoCompleteAgent
                                withTitle
                                onlyAvailable
                                value={getValues().username}
                                excludeId={room.servedBy?._id}
                                showIdleAgents={idleAgentsAllowedForForwarding}
                                placeholder={t('Username_name_email')}
                                onChange={(value) => {
                                    setValue('username', value);
                                }}
                            />
                        </FieldRow>
                    </Field>
                    <Field marginBlock={15}>
                        <FieldLabel>
                            {t('Leave_a_comment')}{' '}
                            <Box is='span' color='annotation'>
                                ({t('Optional')})
                            </Box>
                        </FieldLabel>
                        <FieldRow>
                            <TextAreaInput data-qa-id='ForwardChatModalTextAreaInputComment' {...register('comment')} rows={8} flexGrow={1} />
                        </FieldRow>
                    </Field>
                </FieldGroup>
            </Modal.Content>
            <Modal.Footer>
                <Modal.FooterControllers>
                    <Button onClick={onCancel}>{t('Cancel')}</Button>
                    <Button type='submit' disabled={!username && !department} primary loading={isSubmitting}>
                        {t('Forward')}
                    </Button>
                </Modal.FooterControllers>
            </Modal.Footer>
        </Modal>
    );
};

export default ForwardChatModal;