import type { ILivechatCustomField, Serialized } from '@rocket.chat/core-typings'; import type { SelectOption } from '@rocket.chat/fuselage'; import { FieldError, Button, ButtonGroup, Field, FieldGroup, FieldLabel, FieldRow, Select, TextInput, ToggleSwitch, Box, } from '@rocket.chat/fuselage'; import { ContextualbarTitle, ContextualbarHeader, ContextualbarClose, ContextualbarFooter, ContextualbarScrollableContent, } from '@rocket.chat/ui-client'; import { useToastMessageDispatch, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; import { useId, useMemo } from 'react'; import { FormProvider, useForm, Controller } from 'react-hook-form'; import { CustomFieldsAdditionalForm } from '../additionalForms'; import { useRemoveCustomField } from './useRemoveCustomField'; import { useFormSubmitWithDirtyCheck } from '../../../hooks/useFormSubmitWithDirtyCheck'; import { omnichannelQueryKeys } from '../../../lib/queryKeys'; export type EditCustomFieldsFormData = { field: string; label: string; scope: 'visitor' | 'room'; visibility: boolean; searchable: boolean; regexp: string; type: string; required: boolean; defaultValue: string; options: string; public: boolean; }; const getInitialValues = (customFieldData: Serialized | undefined) => ({ field: customFieldData?._id || '', label: customFieldData?.label || '', scope: customFieldData?.scope || 'visitor', visibility: customFieldData?.visibility === 'visible', searchable: !!customFieldData?.searchable, regexp: customFieldData?.regexp || '', // additional props type: customFieldData?.type || 'input', required: !!customFieldData?.required, defaultValue: customFieldData?.defaultValue || '', options: customFieldData?.options || '', public: !!customFieldData?.public, }); const EditCustomFields = ({ customFieldData, onClose }: { customFieldData?: Serialized; onClose: () => void }) => { const t = useTranslation(); const queryClient = useQueryClient(); const dispatchToastMessage = useToastMessageDispatch(); const handleDelete = useRemoveCustomField(); const methods = useForm({ values: getInitialValues(customFieldData), }); const { control, handleSubmit, formState: { isDirty, errors }, } = methods; const saveCustomField = useEndpoint('POST', '/v1/livechat/custom-fields.save'); const handleSave = useFormSubmitWithDirtyCheck( async ({ visibility, ...data }: EditCustomFieldsFormData) => { try { await saveCustomField({ customFieldId: customFieldData?._id as unknown as string, customFieldData: { visibility: visibility ? 'visible' : 'hidden', ...data, }, }); dispatchToastMessage({ type: 'success', message: t('Saved') }); queryClient.invalidateQueries({ queryKey: omnichannelQueryKeys.livechat.customFields(), }); onClose(); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } }, { isDirty }, ); const scopeOptions: SelectOption[] = useMemo( () => [ ['visitor', t('Visitor')], ['room', t('Room')], ], [t], ); const formId = useId(); const fieldField = useId(); const labelField = useId(); const scopeField = useId(); const visibilityField = useId(); const searchableField = useId(); const regexpField = useId(); return ( <> {customFieldData?._id ? t('Edit_Custom_Field') : t('New_Custom_Field')}
{t('Field')} (!/^[0-9a-zA-Z-_]+$/.test(value) ? t('error-invalid-custom-field-name') : undefined), }} render={({ field }) => ( )} /> {errors?.field && ( {errors.field.message} )} {t('Label')} ( )} /> {errors?.label && ( {errors.label.message} )} {t('Scope')}