Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions src/components/Skeletons/WorkspaceRowSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React from 'react';
import {Rect} from 'react-native-svg';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import variables from '@styles/variables';
import ItemListSkeletonView from './ItemListSkeletonView';

const barHeight = 7;
const longBarWidth = 120;
const shortBarWidth = 60;
const leftPaneWidth = variables.navigationTabBarSize;
const gapWidth = 12;

type WorkspaceRowSkeletonProps = {
shouldAnimate?: boolean;
fixedNumItems?: number;
gradientOpacityEnabled?: boolean;
};

function WorkspaceRowSkeleton({shouldAnimate = true, fixedNumItems, gradientOpacityEnabled = false}: WorkspaceRowSkeletonProps) {
const styles = useThemeStyles();
const {windowWidth} = useWindowDimensions();
const {shouldUseNarrowLayout} = useResponsiveLayout();
// We calculate the width of the sections on the skeleton by first calculating the skeleton view width
// Then we subtract the width by 66, which is the x position of the first part.
const partWidth = Math.floor((windowWidth - leftPaneWidth - gapWidth * 2 - 66) / 3);
Comment thread
daledah marked this conversation as resolved.
return (
<ItemListSkeletonView
shouldAnimate={shouldAnimate}
fixedNumItems={fixedNumItems}
gradientOpacityEnabled={gradientOpacityEnabled}
itemViewStyle={[styles.highlightBG, styles.mb2, styles.br3, styles.ml5]}
renderSkeletonItem={() => (
<>
<Rect
x={12}
y={12}
rx={5}
ry={5}
width={36}
height={40}
/>
<Rect
x={66}
y={22}
width={longBarWidth}
height={barHeight}
/>
<Rect
x={66}
y={36}
width={shortBarWidth}
height={barHeight}
/>
{!shouldUseNarrowLayout && (
<>
<Rect
x={66 + partWidth}
y={22}
width={longBarWidth}
height={barHeight}
/>
<Rect
x={66 + partWidth}
y={36}
width={shortBarWidth}
height={barHeight}
/>
<Rect
x={66 + partWidth * 2}
y={22}
width={longBarWidth}
height={barHeight}
/>
<Rect
x={66 + partWidth * 2}
y={36}
width={shortBarWidth}
height={barHeight}
/>
</>
)}
</>
)}
/>
);
}
WorkspaceRowSkeleton.displayName = 'WorkspaceRowSkeleton';
export default WorkspaceRowSkeleton;
5 changes: 2 additions & 3 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4882,9 +4882,8 @@ const translations = {
updateTaxCodeFailureMessage: 'Beim Aktualisieren des Steuercodes ist ein Fehler aufgetreten, bitte versuchen Sie es erneut.',
},
emptyWorkspace: {
title: 'Erstellen Sie einen Arbeitsbereich',
subtitle:
'Erstellen Sie einen Arbeitsbereich, um Belege zu verfolgen, Ausgaben zu erstatten, Reisen zu verwalten, Rechnungen zu senden und mehr – alles in der Geschwindigkeit eines Chats.',
title: 'Sie haben keine Arbeitsbereiche',
subtitle: 'Verfolgen Sie Belege, erstatten Sie Ausgaben, verwalten Sie Reisen, senden Sie Rechnungen und mehr.',
createAWorkspaceCTA: 'Loslegen',
features: {
trackAndCollect: 'Belege verfolgen und sammeln',
Expand Down
4 changes: 2 additions & 2 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4865,8 +4865,8 @@ const translations = {
updateTaxCodeFailureMessage: 'An error occurred while updating the tax code, please try again',
},
emptyWorkspace: {
title: 'Create a workspace',
subtitle: 'Create a workspace to track receipts, reimburse expenses, manage travel, send invoices, and more — all at the speed of chat.',
title: 'You have no workspaces',
subtitle: 'Track receipts, reimburse expenses, manage travel, send invoices, and more.',
createAWorkspaceCTA: 'Get Started',
features: {
trackAndCollect: 'Track and collect receipts',
Expand Down
4 changes: 2 additions & 2 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4875,8 +4875,8 @@ const translations = {
updateTaxCodeFailureMessage: 'Se produjo un error al actualizar el código tributario, inténtelo nuevamente',
},
emptyWorkspace: {
title: 'Crea un espacio de trabajo',
subtitle: 'Crea un espacio de trabajo para organizar recibos, reembolsar gastos, gestionar viajes, enviar facturas y mucho más, todo a la velocidad del chat.',
title: 'No tienes espacios de trabajo',
subtitle: 'Organiza recibos, reembolsa gastos, gestiona viajes, envía facturas y mucho más.',
createAWorkspaceCTA: 'Comenzar',
features: {
trackAndCollect: 'Organiza recibos',
Expand Down
4 changes: 2 additions & 2 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4898,8 +4898,8 @@ const translations = {
updateTaxCodeFailureMessage: "Une erreur s'est produite lors de la mise à jour du code fiscal, veuillez réessayer.",
},
emptyWorkspace: {
title: 'Créer un espace de travail',
subtitle: 'Créez un espace de travail pour suivre les reçus, rembourser les dépenses, gérer les voyages, envoyer des factures, et plus encore — le tout à la vitesse du chat.',
title: "Vous n'avez aucun espace de travail",
subtitle: 'Suivez les reçus, remboursez les dépenses, gérez les déplacements, envoyez des factures, et plus encore.',
createAWorkspaceCTA: 'Commencer',
features: {
trackAndCollect: 'Suivre et collecter les reçus',
Expand Down
4 changes: 2 additions & 2 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4897,8 +4897,8 @@ const translations = {
updateTaxCodeFailureMessage: "Si è verificato un errore durante l'aggiornamento del codice fiscale, riprova.",
},
emptyWorkspace: {
title: "Crea un'area di lavoro",
subtitle: 'Crea uno spazio di lavoro per tracciare le ricevute, rimborsare le spese, gestire i viaggi, inviare fatture e altro ancora, tutto alla velocità della chat.',
title: 'Non hai spazi di lavoro',
subtitle: 'Traccia ricevute, rimborsa spese, gestisci viaggi, invia fatture e altro ancora.',
createAWorkspaceCTA: 'Inizia',
features: {
trackAndCollect: 'Traccia e raccogli ricevute',
Expand Down
4 changes: 2 additions & 2 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4876,8 +4876,8 @@ const translations = {
updateTaxCodeFailureMessage: '税コードの更新中にエラーが発生しました。もう一度お試しください。',
},
emptyWorkspace: {
title: 'ワークスペースを作成',
subtitle: '領収書を追跡し、経費を払い戻し、旅行を管理し、請求書を送信するためのワークスペースを作成し、チャットの速度でこれらすべてを行いましょう。',
title: 'ワークスペースがありません',
subtitle: '領収書の管理、経費精算、出張管理、請求書の送信などができます。',
createAWorkspaceCTA: '開始する',
features: {
trackAndCollect: '領収書を追跡して収集する',
Expand Down
4 changes: 2 additions & 2 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4899,8 +4899,8 @@ const translations = {
updateTaxCodeFailureMessage: 'Er is een fout opgetreden bij het bijwerken van de belastingcode, probeer het opnieuw.',
},
emptyWorkspace: {
title: 'Maak een werkruimte aan',
subtitle: 'Maak een werkruimte om bonnetjes bij te houden, uitgaven te vergoeden, reizen te beheren, facturen te versturen en meer — allemaal op de snelheid van chat.',
title: 'Je hebt geen werkruimtes',
subtitle: 'Beheer bonnetjes, vergoed uitgaven, regel reizen, verstuur facturen en meer.',
createAWorkspaceCTA: 'Aan de slag',
features: {
trackAndCollect: 'Volg en verzamel bonnetjes',
Expand Down
4 changes: 2 additions & 2 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4888,8 +4888,8 @@ const translations = {
updateTaxCodeFailureMessage: 'Wystąpił błąd podczas aktualizacji kodu podatkowego, spróbuj ponownie.',
},
emptyWorkspace: {
title: 'Utwórz przestrzeń roboczą',
subtitle: 'Utwórz przestrzeń roboczą do śledzenia paragonów, zwracania wydatków, zarządzania podróżami, wysyłania faktur i nie tylko — wszystko z prędkością czatu.',
title: 'Nie masz żadnych przestrzeni roboczych',
subtitle: 'Śledź paragony, zwracaj wydatki, zarządzaj podróżami, wysyłaj faktury i nie tylko.',
createAWorkspaceCTA: 'Rozpocznij',
features: {
trackAndCollect: 'Śledź i zbieraj paragony',
Expand Down
4 changes: 2 additions & 2 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4894,8 +4894,8 @@ const translations = {
updateTaxCodeFailureMessage: 'Ocorreu um erro ao atualizar o código de imposto, por favor, tente novamente.',
},
emptyWorkspace: {
title: 'Criar um espaço de trabalho',
subtitle: 'Crie um espaço de trabalho para rastrear recibos, reembolsar despesas, gerenciar viagens, enviar faturas e muito mais — tudo na velocidade do chat.',
title: 'Você não tem espaços de trabalho',
subtitle: 'Acompanhe recibos, reembolse despesas, gerencie viagens, envie faturas e muito mais.',
createAWorkspaceCTA: 'Começar',
features: {
trackAndCollect: 'Acompanhe e colete recibos',
Expand Down
4 changes: 2 additions & 2 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4811,8 +4811,8 @@ const translations = {
updateTaxCodeFailureMessage: '更新税码时发生错误,请重试',
},
emptyWorkspace: {
title: '创建一个工作区',
subtitle: '创建一个工作区来跟踪收据、报销费用、管理差旅、发送发票等——一切都在聊天的速度下完成。',
title: '您没有任何工作区',
subtitle: '跟踪收据、报销费用、管理差旅、发送发票等。',
createAWorkspaceCTA: '开始使用',
features: {
trackAndCollect: '跟踪并收集收据',
Expand Down
58 changes: 25 additions & 33 deletions src/pages/workspace/WorkspacesListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import {FlatList, View} from 'react-native';
import type {ValueOf} from 'type-fest';
import Button from '@components/Button';
import ConfirmModal from '@components/ConfirmModal';
import type {FeatureListItem} from '@components/FeatureList';
import FeatureList from '@components/FeatureList';
import EmptyStateComponent from '@components/EmptyStateComponent';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import LottieAnimations from '@components/LottieAnimations';
import type {MenuItemProps} from '@components/MenuItem';
import NavigationTabBar from '@components/Navigation/NavigationTabBar';
Expand All @@ -22,6 +20,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import ScrollView from '@components/ScrollView';
import SearchBar from '@components/SearchBar';
import type {ListItem} from '@components/SelectionList/types';
import WorkspaceRowSkeleton from '@components/Skeletons/WorkspaceRowSkeleton';
import SupportalActionRestrictedModal from '@components/SupportalActionRestrictedModal';
import Text from '@components/Text';
import useCardFeeds from '@hooks/useCardFeeds';
Expand All @@ -32,6 +31,7 @@ import useOnyx from '@hooks/useOnyx';
import usePayAndDowngrade from '@hooks/usePayAndDowngrade';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSearchResults from '@hooks/useSearchResults';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {isConnectionInProgress} from '@libs/actions/connections';
Expand All @@ -46,6 +46,8 @@ import {getDefaultApprover, getPolicy, getPolicyBrickRoadIndicatorStatus, isPoli
import {getDefaultWorkspaceAvatar} from '@libs/ReportUtils';
import {shouldCalculateBillNewDot as shouldCalculateBillNewDotFn} from '@libs/SubscriptionUtils';
import type {AvatarSource} from '@libs/UserUtils';
import colors from '@styles/theme/colors';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
Expand All @@ -72,21 +74,6 @@ type WorkspaceItem = ListItem &
// eslint-disable-next-line react/no-unused-prop-types
type GetMenuItem = {item: WorkspaceItem; index: number};

const workspaceFeatures: FeatureListItem[] = [
{
icon: Illustrations.MoneyReceipts,
translationKey: 'workspace.emptyWorkspace.features.trackAndCollect',
},
{
icon: Illustrations.CreditCardsNew,
translationKey: 'workspace.emptyWorkspace.features.companyCards',
},
{
icon: Illustrations.MoneyWings,
translationKey: 'workspace.emptyWorkspace.features.reimbursements',
},
];

/**
* Dismisses the errors on one item
*/
Expand All @@ -107,6 +94,7 @@ function dismissWorkspaceError(policyID: string, pendingAction: OnyxCommon.Pendi
function WorkspacesListPage() {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {translate, localeCompare} = useLocalize();
const {isOffline} = useNetwork();
const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
Expand Down Expand Up @@ -448,23 +436,27 @@ function WorkspacesListPage() {
</View>
) : (
<ScrollView
contentContainerStyle={styles.pt2}
contentContainerStyle={[styles.pt2, styles.flexGrow1, styles.flexShrink0]}
addBottomSafeAreaPadding
>
<View style={[styles.flex1, isLessThanMediumScreen ? styles.workspaceSectionMobile : styles.workspaceSection]}>
<FeatureList
menuItems={workspaceFeatures}
title={translate('workspace.emptyWorkspace.title')}
subtitle={translate('workspace.emptyWorkspace.subtitle')}
ctaText={translate('workspace.new.newWorkspace')}
ctaAccessibilityLabel={translate('workspace.new.newWorkspace')}
onCtaPress={() => interceptAnonymousUser(() => Navigation.navigate(ROUTES.WORKSPACE_CONFIRMATION.getRoute(ROUTES.WORKSPACES_LIST.route)))}
illustration={LottieAnimations.WorkspacePlanet}
// We use this style to vertically center the illustration, as the original illustration is not centered
illustrationStyle={styles.emptyWorkspaceIllustrationStyle}
titleStyles={styles.textHeadlineH1}
/>
</View>
<EmptyStateComponent
SkeletonComponent={WorkspaceRowSkeleton}
headerMediaType={CONST.EMPTY_STATE_MEDIA.ANIMATION}
headerMedia={LottieAnimations.WorkspacePlanet}
title={translate('workspace.emptyWorkspace.title')}
subtitle={translate('workspace.emptyWorkspace.subtitle')}
titleStyles={styles.pt2}
headerStyles={[styles.overflowHidden, StyleUtils.getBackgroundColorStyle(colors.pink800), StyleUtils.getHeight(variables.sectionIllustrationHeight)]}
lottieWebViewStyles={styles.emptyWorkspaceListIllustrationStyle}
headerContentStyles={styles.emptyWorkspaceListIllustrationStyle}
buttons={[
{
success: true,
buttonAction: () => interceptAnonymousUser(() => Navigation.navigate(ROUTES.WORKSPACE_CONFIRMATION.getRoute(ROUTES.WORKSPACES_LIST.route))),
buttonText: translate('workspace.new.newWorkspace'),
},
]}
/>
</ScrollView>
)}
{shouldDisplayLHB && <NavigationTabBar selectedTab={NAVIGATION_TABS.WORKSPACES} />}
Expand Down
6 changes: 6 additions & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2018,6 +2018,12 @@ const styles = (theme: ThemeColors) =>
marginBottom: -20,
},

emptyWorkspaceListIllustrationStyle: {
marginTop: 12,
marginBottom: -20,
height: '100%',
},

overlayStyles: (current: OverlayStylesParams, isModalOnTheLeft: boolean) =>
({
...positioning.pFixed,
Expand Down
Loading