1- import type { IUser } from '@rocket.chat/core-typings' ;
21import { UserStatus as UserStatusType } from '@rocket.chat/core-typings' ;
2+ import { css } from '@rocket.chat/css-in-js' ;
33import type { SelectOption } from '@rocket.chat/fuselage' ;
44import {
55 Field ,
@@ -10,8 +10,7 @@ import {
1010 TextInput ,
1111 InputBox ,
1212 Select ,
13- SelectLegacy ,
14- Option ,
13+ Callout ,
1514 Margins ,
1615 Modal ,
1716 Button ,
@@ -25,20 +24,21 @@ import {
2524 ModalFooterControllers ,
2625} from '@rocket.chat/fuselage' ;
2726import { useEffectEvent , useLocalStorage } from '@rocket.chat/fuselage-hooks' ;
28- import { useToastMessageDispatch , useSetting , useEndpoint } from '@rocket.chat/ui-contexts' ;
27+ import { useToastMessageDispatch , useSetting , useEndpoint , useUser } from '@rocket.chat/ui-contexts' ;
2928import type { TFunction } from 'i18next' ;
3029import type { ReactElement , ChangeEvent , ComponentProps , FormEvent } from 'react' ;
3130import { useState , useCallback , useId , useMemo } from 'react' ;
3231import { useTranslation } from 'react-i18next' ;
3332
33+ import MarkdownText from '../../../components/MarkdownText' ;
3434import { UserStatus } from '../../../components/UserStatus' ;
35+ import UserStatusMenu from '../../../components/UserStatusMenu' ;
36+ import { useExpirationText } from '../../../components/UserStatusText' ;
3537import { useFormatTime } from '../../../hooks/useFormatTime' ;
3638import { USER_STATUS_TEXT_MAX_LENGTH } from '../../../lib/constants' ;
3739
3840type EditStatusModalProps = {
3941 onClose : ( ) => void ;
40- userStatus : IUser [ 'status' ] ;
41- userStatusText : IUser [ 'statusText' ] ;
4242} ;
4343
4444type DurationOption = {
@@ -73,27 +73,17 @@ const DURATION_OPTIONS: DurationOption[] = [
7373 { value : 'custom' , getLabel : ( t ) => t ( 'Status_choose_date_and_time' ) } ,
7474] ;
7575
76- const StatusOption = ( { status, label } : { status : UserStatusType ; label : string } ) => (
77- < Box display = 'flex' alignItems = 'center' >
78- < Box marginInlineEnd = { 8 } >
79- < UserStatus status = { status } />
80- </ Box >
81- { label }
82- </ Box >
83- ) ;
84-
85- // eslint-disable-next-line react/no-multi-comp
86- const EditStatusModal = ( { onClose, userStatus, userStatusText } : EditStatusModalProps ) : ReactElement => {
76+ const EditStatusModal = ( { onClose } : EditStatusModalProps ) : ReactElement => {
77+ const user = useUser ( ) ;
8778 const allowUserStatusMessageChange = useSetting ( 'Accounts_AllowUserStatusMessageChange' ) ;
88- const allowInvisibleStatus = useSetting ( 'Accounts_AllowInvisibleStatusOption' , true ) ;
8979 const dispatchToastMessage = useToastMessageDispatch ( ) ;
9080 const [ customStatus , setCustomStatus ] = useLocalStorage < string > ( 'Local_Custom_Status' , '' ) ;
91- const initialStatusText = customStatus || userStatusText || '' ;
81+ const initialStatusText = customStatus || user ?. statusText || '' ;
9282
9383 const { t } = useTranslation ( ) ;
9484 const modalId = useId ( ) ;
9585 const [ statusText , setStatusText ] = useState ( initialStatusText ) ;
96- const [ statusType , setStatusType ] = useState ( userStatus ) ;
86+ const [ statusType , setStatusType ] = useState ( user ?. status ?? UserStatusType . ONLINE ) ;
9787 const [ statusTextError , setStatusTextError ] = useState < string | undefined > ( ) ;
9888 const [ duration , setDuration ] = useState ( '' ) ;
9989 const [ customDate , setCustomDate ] = useState ( ( ) => new Date ( ) . toLocaleDateString ( 'en-CA' ) ) ;
@@ -103,19 +93,9 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
10393 const setUserStatus = useEndpoint ( 'POST' , '/v1/users.setStatus' ) ;
10494 const formatTime = useFormatTime ( ) ;
10595
106- const statusOptions : SelectOption [ ] = useMemo ( ( ) => {
107- const options : SelectOption [ ] = [
108- [ UserStatusType . ONLINE , t ( 'Online' ) ] ,
109- [ UserStatusType . AWAY , t ( 'Away' ) ] ,
110- [ UserStatusType . BUSY , t ( 'Busy' ) ] ,
111- ] ;
112-
113- if ( allowInvisibleStatus ) {
114- options . push ( [ UserStatusType . OFFLINE , t ( 'Offline' ) ] ) ;
115- }
116-
117- return options ;
118- } , [ t , allowInvisibleStatus ] ) ;
96+ const currentStatusText = user ?. statusText || t ( user ?. status ?? 'offline' ) ;
97+ const expirationText = useExpirationText ( user ?. statusExpiresAt ) ;
98+ const defaultStatusLabel = `${ t ( statusType ) } (${ t ( 'Default' ) } )` ;
11999
120100 const durationOptions : SelectOption [ ] = useMemo (
121101 ( ) => DURATION_OPTIONS . map ( ( { value, getLabel } ) => [ value , getLabel ( t , formatTime , new Date ( ) ) ] ) ,
@@ -154,7 +134,7 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
154134 }
155135 await setUserStatus ( {
156136 message : statusText ,
157- status : statusType as UserStatusType ,
137+ status : statusType ,
158138 ...( expiresAt && { expiresAt : expiresAt . toISOString ( ) } ) ,
159139 } ) ;
160140 setCustomStatus ( statusText ) ;
@@ -188,40 +168,44 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
188168 < ModalContent fontScale = 'p2' >
189169 < Box display = 'flex' flexDirection = 'column' rowGap = { 12 } >
190170 < Field >
191- < FieldLabel htmlFor = { `${ modalId } -status-type` } > { t ( 'Status' ) } </ FieldLabel >
192- < FieldRow >
193- < SelectLegacy
194- id = { `${ modalId } -status-type` }
195- aria-label = { t ( 'Status' ) }
196- value = { statusType }
197- options = { statusOptions }
198- onChange = { ( value : string ) => setStatusType ( value as UserStatusType ) }
199- renderSelected = { ( { value, label } ) => (
200- < Box flexGrow = '1' >
201- < StatusOption status = { value as UserStatusType } label = { label } />
171+ < FieldLabel > { t ( 'Status_current' ) } </ FieldLabel >
172+ < Box display = 'flex' alignItems = 'center' mbs = { 8 } >
173+ < UserStatus status = { user ?. status } />
174+ < Box mis = { 8 } >
175+ < MarkdownText content = { currentStatusText } parseEmoji variant = 'inlineWithoutBreaks' />
176+ { expirationText && (
177+ < Box color = 'hint' fontScale = 'c1' >
178+ { expirationText }
202179 </ Box >
203180 ) }
204- renderItem = { ( { value, label, ...props } ) => (
205- < Option { ...props } label = { < StatusOption status = { value as UserStatusType } label = { label } /> } />
206- ) }
207- />
208- </ FieldRow >
181+ </ Box >
182+ </ Box >
209183 </ Field >
210184 < Field >
211- < FieldLabel htmlFor = { `${ modalId } -status-message` } > { t ( 'StatusMessage ' ) } </ FieldLabel >
185+ < FieldLabel htmlFor = { `${ modalId } -status-message` } > { t ( 'Status ' ) } </ FieldLabel >
212186 < FieldRow >
213187 < TextInput
214188 id = { `${ modalId } -status-message` }
215- aria-label = { t ( 'StatusMessage ' ) }
189+ aria-label = { t ( 'Status ' ) }
216190 error = { statusTextError }
217191 disabled = { ! allowUserStatusMessageChange }
218192 flexGrow = { 1 }
219193 value = { statusText }
220194 onChange = { handleStatusText }
221- placeholder = { t ( 'StatusMessage_Placeholder' ) }
195+ placeholder = { defaultStatusLabel }
196+ className = { css `
197+ align-items : center;
198+
199+ & > .rcx-input-box__addon {
200+ order : -1 ;
201+ margin-inline-end : 0.5rem ;
202+ }
203+ ` }
204+ addon = { < UserStatusMenu margin = 'none' initialStatus = { statusType } onChange = { setStatusType } placement = 'bottom-start' /> }
222205 />
223206 </ FieldRow >
224207 { ! allowUserStatusMessageChange && < FieldHint > { t ( 'StatusMessage_Change_Disabled' ) } </ FieldHint > }
208+ { allowUserStatusMessageChange && < FieldHint > { t ( 'Status_you_can_use_emoji' ) } </ FieldHint > }
225209 < FieldError > { statusTextError } </ FieldError >
226210 </ Field >
227211 < Field >
@@ -256,22 +240,18 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
256240 </ Box >
257241 ) }
258242 </ Field >
243+ < Callout type = 'info' > { t ( 'Status_new_status_warning' ) } </ Callout >
259244 </ Box >
260245 </ ModalContent >
261246 < ModalFooter >
262- < Box display = 'flex' justifyContent = 'space-between' alignItems = 'center' width = '100%' >
263- < Box fontScale = 'c1' color = 'hint' >
264- { t ( 'Status_calendar_events_wont_override' ) }
265- </ Box >
266- < ModalFooterControllers >
267- < Button secondary onClick = { onClose } >
268- { t ( 'Cancel' ) }
269- </ Button >
270- < Button primary type = 'submit' disabled = { ! ! statusTextError } >
271- { t ( 'Save' ) }
272- </ Button >
273- </ ModalFooterControllers >
274- </ Box >
247+ < ModalFooterControllers >
248+ < Button secondary onClick = { onClose } >
249+ { t ( 'Cancel' ) }
250+ </ Button >
251+ < Button primary type = 'submit' disabled = { ! ! statusTextError } >
252+ { t ( 'Save' ) }
253+ </ Button >
254+ </ ModalFooterControllers >
275255 </ ModalFooter >
276256 </ Modal >
277257 ) ;
0 commit comments