Skip to content

Commit

Permalink
Merge pull request #47848 from software-mansion-labs/approval-workflo…
Browse files Browse the repository at this point in the history
…ws/display-empty-state
  • Loading branch information
jasperhuangg authored Sep 2, 2024
2 parents 6a43eec + 203cc5f commit 72add22
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 29 deletions.
87 changes: 87 additions & 0 deletions assets/images/turtle-in-shell.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/components/Icon/Illustrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ import WalletAlt from '@assets/images/simple-illustrations/simple-illustration__
import Workflows from '@assets/images/simple-illustrations/simple-illustration__workflows.svg';
import ExpensifyApprovedLogoLight from '@assets/images/subscription-details__approvedlogo--light.svg';
import ExpensifyApprovedLogo from '@assets/images/subscription-details__approvedlogo.svg';
import TurtleInShell from '@assets/images/turtle-in-shell.svg';

export {
Abracadabra,
Expand Down Expand Up @@ -230,4 +231,5 @@ export {
AmexCompanyCards,
MasterCardCompanyCards,
VisaCompanyCards,
TurtleInShell,
};
5 changes: 5 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,11 @@ export default {
approverInMultipleWorkflows: 'This member already belongs to another approval workflow. Any updates here will reflect there too.',
approverCircularReference: ({name1, name2}: ApprovalWorkflowErrorParams) =>
`<strong>${name1}</strong> already approves reports to <strong>${name2}</strong>. Please choose a different approver to avoid a circular workflow.`,
emptyContent: {
title: 'No members to display',
expensesFromSubtitle: 'All workspace members already belong to an existing approval workflow.',
approverSubtitle: 'All approvers belong to an existing workflow.',
},
},
workflowsDelayedSubmissionPage: {
autoReportingErrorMessage: "Delayed submission couldn't be changed. Please try again or contact support.",
Expand Down
5 changes: 5 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,11 @@ export default {
approverInMultipleWorkflows: 'Este miembro ya pertenece a otro flujo de aprobación. Cualquier actualización aquí se reflejará allí también.',
approverCircularReference: ({name1, name2}: ApprovalWorkflowErrorParams) =>
`<strong>${name1}</strong> ya aprueba informes a <strong>${name2}</strong>. Por favor, elige un aprobador diferente para evitar un flujo de trabajo circular.`,
emptyContent: {
title: 'No hay miembros para mostrar',
expensesFromSubtitle: 'Todos los miembros del espacio de trabajo ya pertenecen a un flujo de aprobación existente.',
approverSubtitle: 'Todos los aprobadores pertenecen a un flujo de trabajo existente.',
},
},
workflowsDelayedSubmissionPage: {
autoReportingErrorMessage: 'El parámetro de envío retrasado no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import type {SectionListData} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {useOnyx, withOnyx} from 'react-native-onyx';
import Badge from '@components/Badge';
import BlockingView from '@components/BlockingViews/BlockingView';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import {FallbackAvatar} from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionList';
import InviteMemberListItem from '@components/SelectionList/InviteMemberListItem';
Expand All @@ -30,6 +32,7 @@ import * as PolicyUtils from '@libs/PolicyUtils';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
import variables from '@styles/variables';
import * as Policy from '@userActions/Policy/Policy';
import * as Workflow from '@userActions/Workflow';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -74,9 +77,8 @@ function WorkspaceWorkflowsApprovalsApproverPageWrapper(props: WorkspaceWorkflow
function WorkspaceWorkflowsApprovalsApproverPageBeta({policy, personalDetails, isLoadingReportData = true, route}: WorkspaceWorkflowsApprovalsApproverPageProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false);
const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState('');
const [approvalWorkflow, approvalWorkflowMetadata] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW);
const [approvalWorkflow] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW);
const [selectedApproverEmail, setSelectedApproverEmail] = useState<string | undefined>(undefined);

// eslint-disable-next-line rulesdir/no-negated-variables
Expand Down Expand Up @@ -165,6 +167,8 @@ function WorkspaceWorkflowsApprovalsApproverPageBeta({policy, personalDetails, i
translate,
]);

const shouldShowListEmptyContent = !debouncedSearchTerm && approvalWorkflow && !sections[0].data.length;

const nextStep = useCallback(() => {
if (selectedApproverEmail) {
const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList);
Expand All @@ -191,18 +195,23 @@ function WorkspaceWorkflowsApprovalsApproverPageBeta({policy, personalDetails, i
}
}, [approvalWorkflow, approverIndex, personalDetails, policy?.employeeList, route.params.policyID, selectedApproverEmail]);

const nextButton = useMemo(
() => (
const button = useMemo(() => {
let buttonText = isInitialCreationFlow ? translate('common.next') : translate('common.save');

if (shouldShowListEmptyContent) {
buttonText = translate('common.buttonConfirm');
}

return (
<FormAlertWithSubmitButton
isDisabled={!selectedApproverEmail && isInitialCreationFlow}
buttonText={isInitialCreationFlow ? translate('common.next') : translate('common.save')}
isDisabled={!shouldShowListEmptyContent && !selectedApproverEmail && isInitialCreationFlow}
buttonText={buttonText}
onSubmit={nextStep}
containerStyles={[styles.flexReset, styles.flexGrow0, styles.flexShrink0, styles.flexBasisAuto]}
enabledWhenOffline
/>
),
[isInitialCreationFlow, nextStep, selectedApproverEmail, styles.flexBasisAuto, styles.flexGrow0, styles.flexReset, styles.flexShrink0, translate],
);
);
}, [isInitialCreationFlow, nextStep, selectedApproverEmail, shouldShowListEmptyContent, styles.flexBasisAuto, styles.flexGrow0, styles.flexReset, styles.flexShrink0, translate]);

const goBack = useCallback(() => {
if (isInitialCreationFlow) {
Expand All @@ -221,6 +230,21 @@ function WorkspaceWorkflowsApprovalsApproverPageBeta({policy, personalDetails, i

const headerMessage = useMemo(() => (searchTerm && !sections[0].data.length ? translate('common.noResultsFound') : ''), [searchTerm, sections, translate]);

const listEmptyContent = useMemo(
() => (
<BlockingView
icon={Illustrations.TurtleInShell}
iconWidth={variables.emptyListIconWidth}
iconHeight={variables.emptyListIconHeight}
title={translate('workflowsPage.emptyContent.title')}
subtitle={translate('workflowsPage.emptyContent.approverSubtitle')}
subtitleStyle={styles.textSupporting}
containerStyle={styles.pb10}
/>
),
[translate, styles.textSupporting, styles.pb10],
);

return (
<AccessOrNotFoundWrapper
policyID={route.params.policyID}
Expand All @@ -229,7 +253,6 @@ function WorkspaceWorkflowsApprovalsApproverPageBeta({policy, personalDetails, i
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
testID={WorkspaceWorkflowsApprovalsApproverPageWrapper.displayName}
onEntryTransitionEnd={() => setDidScreenTransitionEnd(true)}
>
<FullPageNotFoundView
shouldShow={shouldShowNotFoundView}
Expand All @@ -241,21 +264,22 @@ function WorkspaceWorkflowsApprovalsApproverPageBeta({policy, personalDetails, i
title={translate('workflowsPage.approver')}
onBackButtonPress={goBack}
/>
{approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && (
{approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !shouldShowListEmptyContent && (
<Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{translate('workflowsApproverPage.header')}</Text>
)}
<SelectionList
sections={sections}
ListItem={InviteMemberListItem}
textInputLabel={translate('selectionList.findMember')}
textInputLabel={shouldShowListEmptyContent ? undefined : translate('selectionList.findMember')}
textInputValue={searchTerm}
onChangeText={setSearchTerm}
headerMessage={headerMessage}
onSelectRow={toggleApprover}
showScrollIndicator
showLoadingPlaceholder={!didScreenTransitionEnd || approvalWorkflowMetadata.status === 'loading'}
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
footerContent={nextButton}
footerContent={button}
listEmptyContent={listEmptyContent}
shouldShowListEmptyContent={shouldShowListEmptyContent}
/>
</FullPageNotFoundView>
</ScreenWrapper>
Expand Down
Loading

0 comments on commit 72add22

Please sign in to comment.