import { UserStatus as UserStatusType } from '@rocket.chat/core-typings'; import type { SelectOption } from '@rocket.chat/fuselage'; import { InputBox, Margins, Box } from '@rocket.chat/fuselage'; import { Field, FieldGroup, FieldLabel, FieldRow, FieldError, FieldHint, TextInput, Select } from '@rocket.chat/fuselage-forms'; import { useLocalStorage } from '@rocket.chat/fuselage-hooks'; import { GenericModal } from '@rocket.chat/ui-client'; import { useToastMessageDispatch, useSetting, useEndpoint, useUser, useTranslation } from '@rocket.chat/ui-contexts'; import type { ChangeEvent, ComponentProps } from 'react'; import { useEffect, useMemo } from 'react'; import { Controller, useForm } from 'react-hook-form'; import UserStatusMenu from '../../../components/UserStatusMenu'; import { USER_STATUS_TEXT_MAX_LENGTH } from '../../../lib/constants'; import { getUserStatusInitialValues } from '../../../lib/getUserInitialStatus'; import { STATUS_DURATION_OPTIONS, validateStatusExpiration } from '../../../lib/statusDurations'; export type EditStatusModalProps = { onClose: () => void; }; type StatusFormValues = { statusText: string; statusType: UserStatusType; statusDuration: string; statusCustomDate: string; statusCustomTime: string; }; const EditStatusModal = ({ onClose }: EditStatusModalProps) => { const t = useTranslation(); const user = useUser(); const allowUserStatusMessageChange = useSetting('Accounts_AllowUserStatusMessageChange'); const dispatchToastMessage = useToastMessageDispatch(); const [customStatus, setCustomStatus] = useLocalStorage('Local_Custom_Status', ''); const { control, handleSubmit, setValue, watch, formState: { errors, isDirty }, } = useForm({ defaultValues: getUserStatusInitialValues(user, customStatus), }); const { statusDuration, statusType, statusText } = watch(); const isExpirationDisabled = statusType === UserStatusType.ONLINE && !statusText.trim(); useEffect(() => { if (isExpirationDisabled) { setValue('statusDuration', '', { shouldValidate: true }); } }, [isExpirationDisabled, setValue]); const isStatusFromCall = user?.statusSource === 'internal' || user?.statusSource === 'external'; const setUserStatus = useEndpoint('POST', '/v1/users.setStatus'); const durationOptions: SelectOption[] = useMemo(() => STATUS_DURATION_OPTIONS.map(({ value, labelKey }) => [value, t(labelKey)]), [t]); const handleSaveStatus = async ({ statusText, statusType, statusDuration, statusCustomDate, statusCustomTime, }: StatusFormValues): Promise => { const expiresAt = STATUS_DURATION_OPTIONS.find((o) => o.value === statusDuration)?.getExpiresAt?.({ now: new Date(), customDate: statusCustomDate, customTime: statusCustomTime, }); try { await setUserStatus({ message: statusText, status: statusType, ...(expiresAt && { expiresAt: expiresAt.toISOString() }), }); setCustomStatus(statusText); dispatchToastMessage({ type: 'success', message: t('StatusMessage_Changed_Successfully') }); onClose(); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } }; return ( ) => } > {t('Status')} ( } /> } /> )} /> {t(allowUserStatusMessageChange ? 'Status_you_can_use_emoji' : 'StatusMessage_Change_Disabled')} {errors.statusText && {errors.statusText.message}} {t('Status_clear_after')} validateStatusExpiration(value, { statusCustomDate, statusCustomTime }, t), }} render={({ field: { value, onChange } }) => (