Skip to content

Commit

Permalink
Merge pull request #53118 from dukenv0307/feat/update-empty-state-for…
Browse files Browse the repository at this point in the history
…-ws-feed

update empty state for ws feed
  • Loading branch information
mountiny authored Nov 27, 2024
2 parents 675c738 + 4a1a92d commit fe6f1e7
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 48 deletions.
4 changes: 3 additions & 1 deletion src/components/EmptyStateComponent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function EmptyStateComponent({
<Text style={[styles.textAlignCenter, styles.textHeadlineH1, styles.mb2, titleStyles]}>{title}</Text>
{typeof subtitle === 'string' ? <Text style={[styles.textAlignCenter, styles.textSupporting, styles.textNormal]}>{subtitle}</Text> : subtitle}
<View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : undefined]}>
{buttons?.map(({buttonText, buttonAction, success}, index) => (
{buttons?.map(({buttonText, buttonAction, success, icon, isDisabled}, index) => (
<View
// eslint-disable-next-line react/no-array-index-key
key={index}
Expand All @@ -109,7 +109,9 @@ function EmptyStateComponent({
success={success}
onPress={buttonAction}
text={buttonText}
icon={icon}
large
isDisabled={isDisabled}
/>
</View>
))}
Expand Down
2 changes: 1 addition & 1 deletion src/components/EmptyStateComponent/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type IconAsset from '@src/types/utils/IconAsset';

type ValidSkeletons = typeof SearchRowSkeleton | typeof TableRowSkeleton;
type MediaTypes = ValueOf<typeof CONST.EMPTY_STATE_MEDIA>;
type Button = {buttonText?: string; buttonAction?: () => void; success?: boolean};
type Button = {buttonText?: string; buttonAction?: () => void; success?: boolean; icon?: IconAsset; isDisabled?: boolean};

type SharedProps<T> = {
SkeletonComponent: ValidSkeletons;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import React from 'react';
import EmptyStateComponent from '@components/EmptyStateComponent';
import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import CardRowSkeleton from '@components/Skeletons/CardRowSkeleton';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import colors from '@styles/theme/colors';
import CONST from '@src/CONST';

function WorkspaceCompanyCardsFeedAddedEmptyPage() {
type WorkspaceCompanyCardsFeedAddedEmptyPageProps = {
/** Handle assign card action */
handleAssignCard: () => void;

/** Whether to disable assign card button */
isDisabledAssignCardButton?: boolean;
};

function WorkspaceCompanyCardsFeedAddedEmptyPage({handleAssignCard, isDisabledAssignCardButton}: WorkspaceCompanyCardsFeedAddedEmptyPageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();

Expand All @@ -21,6 +30,15 @@ function WorkspaceCompanyCardsFeedAddedEmptyPage() {
headerContentStyles={styles.emptyStateCardIllustration}
title={translate('workspace.moreFeatures.companyCards.emptyAddedFeedTitle')}
subtitle={translate('workspace.moreFeatures.companyCards.emptyAddedFeedDescription')}
buttons={[
{
buttonText: translate('workspace.companyCards.assignCard'),
buttonAction: handleAssignCard,
icon: Expensicons.Plus,
success: true,
isDisabled: isDisabledAssignCardButton,
},
]}
/>
);
}
Expand Down
15 changes: 13 additions & 2 deletions src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ type WorkspaceCompanyCardsListProps = {

/** Current policy id */
policyID: string;

/** Handle assign card action */
handleAssignCard: () => void;

/** Whether to disable assign card button */
isDisabledAssignCardButton?: boolean;
};

function WorkspaceCompanyCardsList({cardsList, policyID}: WorkspaceCompanyCardsListProps) {
function WorkspaceCompanyCardsList({cardsList, policyID, handleAssignCard, isDisabledAssignCardButton}: WorkspaceCompanyCardsListProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
Expand Down Expand Up @@ -90,7 +96,12 @@ function WorkspaceCompanyCardsList({cardsList, policyID}: WorkspaceCompanyCardsL
);

if (sortedCards.length === 0) {
return <WorkspaceCompanyCardsFeedAddedEmptyPage />;
return (
<WorkspaceCompanyCardsFeedAddedEmptyPage
handleAssignCard={handleAssignCard}
isDisabledAssignCardButton={isDisabledAssignCardButton}
/>
);
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,28 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as CardUtils from '@libs/CardUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import Navigation from '@navigation/Navigation';
import variables from '@styles/variables';
import * as CompanyCards from '@userActions/CompanyCards';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {CompanyCardFeed} from '@src/types/onyx';
import type {AssignCardData, AssignCardStep} from '@src/types/onyx/AssignCard';

type WorkspaceCompanyCardsListHeaderButtonsProps = {
/** Current policy id */
policyID: string;

/** Currently selected feed */
selectedFeed: CompanyCardFeed;

/** Whether to show assign card button */
shouldShowAssignCardButton?: boolean;

/** Handle assign card action */
handleAssignCard: () => void;
};

function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: WorkspaceCompanyCardsListHeaderButtonsProps) {
function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed, shouldShowAssignCardButton, handleAssignCard}: WorkspaceCompanyCardsListHeaderButtonsProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const theme = useTheme();
Expand All @@ -45,36 +47,6 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp
const isCustomFeed = CardUtils.isCustomFeed(selectedFeed);
const companyFeeds = CardUtils.getCompanyFeeds(cardFeeds);
const currentFeedData = companyFeeds?.[selectedFeed];
const policy = PolicyUtils.getPolicy(policyID);

const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`);
const filteredCardList = CardUtils.getFilteredCardList(list);

const handleAssignCard = () => {
const data: Partial<AssignCardData> = {
bankName: selectedFeed,
};

let currentStep: AssignCardStep = CONST.COMPANY_CARD.STEP.ASSIGNEE;

if (Object.keys(policy?.employeeList ?? {}).length === 1) {
const userEmail = Object.keys(policy?.employeeList ?? {}).at(0) ?? '';
data.email = userEmail;
const personalDetails = PersonalDetailsUtils.getPersonalDetailByEmail(userEmail);
const memberName = personalDetails?.firstName ? personalDetails.firstName : personalDetails?.login;
data.cardName = `${memberName}'s card`;
currentStep = CONST.COMPANY_CARD.STEP.CARD;

if (CardUtils.hasOnlyOneCardToAssign(filteredCardList)) {
currentStep = CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE;
data.cardNumber = Object.keys(filteredCardList).at(0);
data.encryptedCardNumber = Object.values(filteredCardList).at(0);
}
}

CompanyCards.setAssignCardStepAndData({data, currentStep});
Navigation.setNavigationActionToMicrotaskQueue(() => Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed)));
};

return (
<OfflineWithFeedback
Expand Down Expand Up @@ -111,14 +83,16 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp
</PressableWithFeedback>

<View style={[styles.flexRow, styles.gap2]}>
<Button
success
isDisabled={!currentFeedData || !!currentFeedData?.pending || !!currentFeedData?.errors}
onPress={handleAssignCard}
icon={Expensicons.Plus}
text={translate('workspace.companyCards.assignCard')}
style={shouldChangeLayout && styles.flex1}
/>
{!!shouldShowAssignCardButton && (
<Button
success
isDisabled={!currentFeedData || !!currentFeedData?.pending || !!currentFeedData?.errors}
onPress={handleAssignCard}
icon={Expensicons.Plus}
text={translate('workspace.companyCards.assignCard')}
style={shouldChangeLayout && styles.flex1}
/>
)}
<Button
onPress={() => Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS.getRoute(policyID))}
icon={Expensicons.Gear}
Expand Down
41 changes: 41 additions & 0 deletions src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ import useNetwork from '@hooks/useNetwork';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as CardUtils from '@libs/CardUtils';
import Navigation from '@libs/Navigation/Navigation';
import type {FullScreenNavigatorParamList} from '@libs/Navigation/types';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
import WorkspacePageWithSections from '@pages/workspace/WorkspacePageWithSections';
import * as CompanyCards from '@userActions/CompanyCards';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import type {AssignCardData, AssignCardStep} from '@src/types/onyx/AssignCard';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import WorkspaceCompanyCardPageEmptyState from './WorkspaceCompanyCardPageEmptyState';
import WorkspaceCompanyCardsFeedPendingPage from './WorkspaceCompanyCardsFeedPendingPage';
Expand All @@ -36,6 +40,10 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
const selectedFeed = CardUtils.getSelectedFeed(lastSelectedFeed, cardFeeds);
const [cardsList] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`);

const policy = PolicyUtils.getPolicy(policyID);

const filteredCardList = CardUtils.getFilteredCardList(cardsList);

const companyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds);
const selectedFeedData = selectedFeed && companyCards[selectedFeed];
const isNoFeed = isEmptyObject(companyCards) && !selectedFeedData;
Expand All @@ -59,6 +67,35 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
CompanyCards.openPolicyCompanyCardsFeed(policyID, selectedFeed);
}, [selectedFeed, isLoading, policyID, isPending]);

const handleAssignCard = () => {
if (!selectedFeed) {
return;
}
const data: Partial<AssignCardData> = {
bankName: selectedFeed,
};

let currentStep: AssignCardStep = CONST.COMPANY_CARD.STEP.ASSIGNEE;

if (Object.keys(policy?.employeeList ?? {}).length === 1) {
const userEmail = Object.keys(policy?.employeeList ?? {}).at(0) ?? '';
data.email = userEmail;
const personalDetails = PersonalDetailsUtils.getPersonalDetailByEmail(userEmail);
const memberName = personalDetails?.firstName ? personalDetails.firstName : personalDetails?.login;
data.cardName = `${memberName}'s card`;
currentStep = CONST.COMPANY_CARD.STEP.CARD;

if (CardUtils.hasOnlyOneCardToAssign(filteredCardList)) {
currentStep = CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE;
data.cardNumber = Object.keys(filteredCardList).at(0);
data.encryptedCardNumber = Object.values(filteredCardList).at(0);
}
}

CompanyCards.setAssignCardStepAndData({data, currentStep});
Navigation.setNavigationActionToMicrotaskQueue(() => Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed)));
};

return (
<AccessOrNotFoundWrapper
policyID={route.params.policyID}
Expand Down Expand Up @@ -86,6 +123,8 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
<WorkspaceCompanyCardsListHeaderButtons
policyID={policyID}
selectedFeed={selectedFeed}
shouldShowAssignCardButton={isPending || !isEmptyObject(cardsList)}
handleAssignCard={handleAssignCard}
/>
)}
{isNoFeed && <WorkspaceCompanyCardPageEmptyState route={route} />}
Expand All @@ -94,6 +133,8 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
<WorkspaceCompanyCardsList
cardsList={cardsList}
policyID={policyID}
handleAssignCard={handleAssignCard}
isDisabledAssignCardButton={!selectedFeedData || !!selectedFeedData?.errors}
/>
)}
</WorkspacePageWithSections>
Expand Down

0 comments on commit fe6f1e7

Please sign in to comment.