diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 7fb5533fd172b..259ae3170825d 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -224,6 +224,9 @@ type MenuItemBaseProps = { /** Whether the secondary right avatar should show as a subscript */ shouldShowSubscriptRightAvatar?: boolean; + /** Whether the secondary avatar should show as a subscript */ + shouldShowSubscriptAvatar?: boolean; + /** Affects avatar size */ viewMode?: ValueOf; @@ -345,6 +348,15 @@ type MenuItemBaseProps = { }; type MenuItemProps = (IconProps | AvatarProps | NoIcon) & MenuItemBaseProps; + +const getSubscriptpAvatarBackgroundColor = (isHovered: boolean, isPressed: boolean, hoveredBackgroundColor: string, pressedBackgroundColor: string) => { + if (isPressed) { + return pressedBackgroundColor; + } + if (isHovered) { + return hoveredBackgroundColor; + } +}; function MenuItem( { interactive = true, @@ -407,6 +419,7 @@ function MenuItem( floatRightAvatars = [], floatRightAvatarSize, shouldShowSubscriptRightAvatar = false, + shouldShowSubscriptAvatar: shouldShowSubscriptAvatarProp = false, avatarSize = CONST.AVATAR_SIZE.DEFAULT, isSmallAvatarSubscriptMenu = false, brickRoadIndicator, @@ -457,7 +470,7 @@ function MenuItem( const isDeleted = style && Array.isArray(style) ? style.includes(styles.offlineFeedback.deleted) : false; const descriptionVerticalMargin = shouldShowDescriptionOnTop ? styles.mb1 : styles.mt1; const fallbackAvatarSize = viewMode === CONST.OPTION_MODE.COMPACT ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT; - const firstIcon = floatRightAvatars.at(0); + const firstRightIcon = floatRightAvatars.at(0); const combinedTitleTextStyle = StyleUtils.combineStyles( [ styles.flexShrink1, @@ -472,6 +485,9 @@ function MenuItem( ], titleStyle ?? {}, ); + const shouldShowAvatar = !!icon && Array.isArray(icon); + const firstIcon = Array.isArray(icon) && !!icon.length ? icon.at(0) : undefined; + const shouldShowSubscriptAvatar = shouldShowSubscriptAvatarProp && !!firstIcon; const descriptionTextStyles = StyleUtils.combineStyles([ styles.textLabelSupporting, icon && !Array.isArray(icon) ? styles.ml3 : {}, @@ -621,7 +637,7 @@ function MenuItem( )} - {!!icon && Array.isArray(icon) && ( + {shouldShowAvatar && !shouldShowSubscriptAvatar && ( )} + {shouldShowAvatar && shouldShowSubscriptAvatar && ( + + )} {!icon && shouldPutLeftPaddingWhenNoIcon && ( {subtitle} )} - {floatRightAvatars?.length > 0 && !!firstIcon && ( + {floatRightAvatars?.length > 0 && !!firstRightIcon && ( {shouldShowSubscriptRightAvatar ? ( diff --git a/src/languages/en.ts b/src/languages/en.ts index c1067e195985e..4254cd7764ce7 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2525,6 +2525,7 @@ const translations = { return 'Member'; } }, + submitExpense: 'Submit expenses using your workspace chat below:', defaultCategory: 'Default category', }, perDiem: { diff --git a/src/languages/es.ts b/src/languages/es.ts index f7af1be451395..bdbf306ef5548 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2549,6 +2549,7 @@ const translations = { return 'Miembro'; } }, + submitExpense: 'Envíe los gastos utilizando el chat de su espacio de trabajo:', defaultCategory: 'Categoría predeterminada', }, perDiem: { diff --git a/src/pages/workspace/WorkspaceInitialPage.tsx b/src/pages/workspace/WorkspaceInitialPage.tsx index e89b83846f1d9..c4f08f46704fd 100644 --- a/src/pages/workspace/WorkspaceInitialPage.tsx +++ b/src/pages/workspace/WorkspaceInitialPage.tsx @@ -9,9 +9,11 @@ import ConfirmModal from '@components/ConfirmModal'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import HighlightableMenuItem from '@components/HighlightableMenuItem'; import * as Expensicons from '@components/Icon/Expensicons'; +import MenuItem from '@components/MenuItem'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; +import Text from '@components/Text'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -25,7 +27,7 @@ import * as CurrencyUtils from '@libs/CurrencyUtils'; import getTopmostRouteName from '@libs/Navigation/getTopmostRouteName'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; -import {getDefaultWorkspaceAvatar} from '@libs/ReportUtils'; +import {getDefaultWorkspaceAvatar, getIcons, getPolicyExpenseChat, getReportName, getReportOfflinePendingActionAndErrors} from '@libs/ReportUtils'; import type {FullScreenNavigatorParamList} from '@navigation/types'; import * as App from '@userActions/App'; import * as Policy from '@userActions/Policy/Policy'; @@ -93,6 +95,8 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac const [connectionSyncProgress] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policy?.id}`); const [currentUserLogin] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email}); const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${route.params?.policyID ?? '-1'}`); + const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); + const {login, accountID} = useCurrentUserPersonalDetails(); const hasSyncError = PolicyUtils.shouldShowSyncError(policy, isConnectionInProgress(connectionSyncProgress, policy)); const waitForNavigate = useWaitForNavigation(); const {singleExecution, isExecuting} = useSingleExecution(); @@ -100,6 +104,9 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac const {translate} = useLocalize(); const {isOffline} = useNetwork(); const wasRendered = useRef(false); + const currentUserPolicyExpenseChatReportID = getPolicyExpenseChat(accountID, policy?.id ?? '-1')?.reportID ?? '-1'; + const [currentUserPolicyExpenseChat] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${currentUserPolicyExpenseChatReportID}`); + const {reportPendingAction} = getReportOfflinePendingActionAndErrors(currentUserPolicyExpenseChat); const prevPendingFields = usePrevious(policy?.pendingFields); const policyFeatureStates = useMemo( @@ -159,7 +166,6 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac !isEmptyObject(policy?.errorFields?.avatarURL ?? {}) || !isEmptyObject(policy?.errorFields?.ouputCurrency ?? {}) || !isEmptyObject(policy?.errorFields?.address ?? {}); - const {login} = useCurrentUserPersonalDetails(); const shouldShowProtectedItems = PolicyUtils.isPolicyAdmin(policy, login); const isPaidGroupPolicy = PolicyUtils.isPaidGroupPolicy(policy); const [featureStates, setFeatureStates] = useState(policyFeatureStates); @@ -408,7 +414,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac style={styles.headerBarDesktopHeight} /> - + dismissError(policyID, policy?.pendingAction)} @@ -440,6 +446,20 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac ))} + + {translate('workspace.common.submitExpense')} + + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(currentUserPolicyExpenseChat?.reportID ?? '-1'))} + shouldShowRightIcon + wrapperStyle={[styles.br2, styles.pl2, styles.pr0, styles.pv3, styles.mt1, styles.alignItemsCenter]} + shouldShowSubscriptAvatar + /> + +