Skip to content

Commit b0f4a78

Browse files
authored
Merge pull request Expensify#68409 from callstack-internal/feat/waterim/uber/invite
2 parents ae5f666 + 1fee87b commit b0f4a78

32 files changed

Lines changed: 1300 additions & 21 deletions

File tree

assets/images/product-illustrations/todd-in-car.svg

Lines changed: 292 additions & 0 deletions
Loading

src/CONST/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,6 +2997,15 @@ const CONST = {
29972997
NAME_USER_FRIENDLY: {
29982998
uber: 'Uber for Business',
29992999
},
3000+
UBER_EMPLOYEE_STATUS: {
3001+
CREATED: 'CREATED',
3002+
INVITED: 'INVITED',
3003+
LINKED_PENDING_APPROVAL: 'LINKED_PENDING_APPROVAL',
3004+
LINKED: 'LINKED',
3005+
SUSPENDED: 'SUSPENDED',
3006+
DELETED: 'DELETED',
3007+
NONE: 'NONE',
3008+
},
30003009
},
30013010
CONNECTIONS: {
30023011
NAME: {
@@ -5170,6 +5179,12 @@ const CONST = {
51705179
SHARE: 'ShareTab',
51715180
SUBMIT: 'SubmitTab',
51725181
},
5182+
RECEIPT_PARTNERS: {
5183+
NAVIGATOR_ID: 'ReceiptPartnersID',
5184+
ALL: 'ReceiptPartnersAllTab',
5185+
LINKED: 'ReceiptPartnersLinkedTab',
5186+
OUTSTANDING: 'ReceiptPartnersOutstandingTab',
5187+
},
51735188
},
51745189
TAB_REQUEST: {
51755190
MANUAL: 'manual',

src/ROUTES.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,6 +1895,28 @@ const ROUTES = {
18951895
return getUrlWithBackToParam(`workspaces/${policyID}/receipt-partners`, backTo);
18961896
},
18971897
},
1898+
WORKSPACE_RECEIPT_PARTNERS_INVITE: {
1899+
route: 'workspaces/:policyID/receipt-partners/:integration/invite',
1900+
getRoute: (policyID: string | undefined, integration: string, backTo?: string) => {
1901+
if (!policyID) {
1902+
Log.warn('Invalid policyID is used to build the WORKSPACE_RECEIPT_PARTNERS_INVITE route');
1903+
}
1904+
return getUrlWithBackToParam(`workspaces/${policyID}/receipt-partners/${integration}/invite`, backTo);
1905+
},
1906+
},
1907+
WORKSPACE_RECEIPT_PARTNERS_INVITE_EDIT: {
1908+
route: 'workspaces/:policyID/receipt-partners/:integration/invite/edit',
1909+
getRoute: (policyID: string | undefined, integration: string, backTo?: string) => {
1910+
if (!policyID) {
1911+
Log.warn('Invalid policyID is used to build the WORKSPACE_RECEIPT_PARTNERS_INVITE_EDIT route');
1912+
}
1913+
return getUrlWithBackToParam(`workspaces/${policyID}/receipt-partners/${integration}/invite/edit`, backTo);
1914+
},
1915+
},
1916+
WORKSPACE_RECEIPT_PARTNERS_INVITE_EDIT_ALL: 'workspaces/:policyID/receipt-partners/:integration/invite/edit/ReceiptPartnersAllTab',
1917+
WORKSPACE_RECEIPT_PARTNERS_INVITE_EDIT_LINKED: 'workspaces/:policyID/receipt-partners/:integration/invite/edit/ReceiptPartnersLinkedTab',
1918+
WORKSPACE_RECEIPT_PARTNERS_INVITE_EDIT_OUTSTANDING: 'workspaces/:policyID/receipt-partners/:integration/invite/edit/ReceiptPartnersOutstandingTab',
1919+
18981920
WORKSPACE_PER_DIEM_IMPORT: {
18991921
route: 'workspaces/:policyID/per-diem/import',
19001922
getRoute: (policyID: string) => `workspaces/${policyID}/per-diem/import` as const,

src/SCREENS.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,8 @@ const SCREENS = {
637637
DOWNGRADE: 'Workspace_Downgrade',
638638
PAY_AND_DOWNGRADE: 'Workspace_Pay_And_Downgrade',
639639
RECEIPT_PARTNERS: 'Workspace_Receipt_Partners',
640+
RECEIPT_PARTNERS_INVITE: 'Workspace_Receipt_Partners_Invite',
641+
RECEIPT_PARTNERS_INVITE_EDIT: 'Workspace_Receipt_Partners_Invite_Edit',
640642
RULES: 'Policy_Rules',
641643
REPORTS_DEFAULT_TITLE: 'Reports_Default_Title',
642644
RULES_AUTO_APPROVE_REPORTS_UNDER: 'Rules_Auto_Approve_Reports_Under',

src/components/Icon/Illustrations.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import TadaYellow from '@assets/images/product-illustrations/tada--yellow.svg';
6868
import TeleScope from '@assets/images/product-illustrations/telescope.svg';
6969
import ThreeLeggedLaptopWoman from '@assets/images/product-illustrations/three_legged_laptop_woman.svg';
7070
import ToddBehindCloud from '@assets/images/product-illustrations/todd-behind-cloud.svg';
71+
import ToddInCar from '@assets/images/product-illustrations/todd-in-car.svg';
7172
import ToddWithPhones from '@assets/images/product-illustrations/todd-with-phones.svg';
7273
import RunningTurtle from '@assets/images/running-turtle.svg';
7374
import BigVault from '@assets/images/simple-illustrations/emptystate__big-vault.svg';
@@ -209,6 +210,7 @@ export {
209210
TadaBlue,
210211
ToddBehindCloud,
211212
ToddWithPhones,
213+
ToddInCar,
212214
GpsTrackOrange,
213215
ShieldYellow,
214216
MoneyReceipts,

src/components/TabSelector/TabLabel.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,20 @@ type TabLabelProps = {
1313

1414
/** Animated opacity value while the label is in active state */
1515
activeOpacity?: number | Animated.AnimatedInterpolation<number>;
16+
17+
/** Whether an icon is present - used to conditionally apply margin */
18+
hasIcon?: boolean;
1619
};
1720

18-
function TabLabel({title = '', activeOpacity = 0, inactiveOpacity = 1}: TabLabelProps) {
21+
function TabLabel({title = '', activeOpacity = 0, inactiveOpacity = 1, hasIcon = false}: TabLabelProps) {
1922
const styles = useThemeStyles();
2023
return (
2124
<View>
2225
<Animated.View style={[{opacity: activeOpacity}]}>
23-
<Text style={styles.tabText(true)}>{title}</Text>
26+
<Text style={styles.tabText(true, hasIcon)}>{title}</Text>
2427
</Animated.View>
2528
<Animated.View style={[StyleSheet.absoluteFill, {opacity: inactiveOpacity}]}>
26-
<Text style={styles.tabText(false)}>{title}</Text>
29+
<Text style={styles.tabText(false, hasIcon)}>{title}</Text>
2730
</Animated.View>
2831
</View>
2932
);

src/components/TabSelector/TabSelector.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,25 @@ type TabSelectorProps = MaterialTopTabBarProps & {
3030

3131
/** Function to render the content of the product training tooltip. */
3232
renderProductTrainingTooltip?: () => React.JSX.Element;
33+
34+
/** Whether tabs should have equal width */
35+
equalWidth?: boolean;
3336
};
3437

3538
type IconTitleAndTestID = {
36-
icon: IconAsset;
39+
icon?: IconAsset;
3740
title: string;
3841
testID?: string;
3942
};
4043

4144
function getIconTitleAndTestID(route: string, translate: LocaleContextProps['translate']): IconTitleAndTestID {
4245
switch (route) {
46+
case CONST.TAB.RECEIPT_PARTNERS.ALL:
47+
return {title: translate('workspace.receiptPartners.uber.all'), testID: 'all'};
48+
case CONST.TAB.RECEIPT_PARTNERS.LINKED:
49+
return {title: translate('workspace.receiptPartners.uber.linked'), testID: 'linked'};
50+
case CONST.TAB.RECEIPT_PARTNERS.OUTSTANDING:
51+
return {title: translate('workspace.receiptPartners.uber.outstanding'), testID: 'outstanding'};
4352
case CONST.TAB_REQUEST.MANUAL:
4453
return {icon: Expensicons.Pencil, title: translate('tabSelector.manual'), testID: 'manual'};
4554
case CONST.TAB_REQUEST.SCAN:
@@ -70,6 +79,7 @@ function TabSelector({
7079
shouldShowLabelWhenInactive = true,
7180
shouldShowProductTrainingTooltip = false,
7281
renderProductTrainingTooltip,
82+
equalWidth = false,
7383
}: TabSelectorProps) {
7484
const {translate} = useLocalize();
7585
const theme = useTheme();
@@ -160,6 +170,7 @@ function TabSelector({
160170
renderProductTrainingTooltip={renderProductTrainingTooltip}
161171
parentWidth={selectorWidth}
162172
parentX={selectorX}
173+
equalWidth={equalWidth}
163174
/>
164175
);
165176
})}

src/components/TabSelector/TabSelectorItem.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ type TabSelectorItemProps = {
5454

5555
/** Parent width, for computing tooltip placement */
5656
parentWidth?: number;
57+
58+
/** Whether tabs should have equal width */
59+
equalWidth?: boolean;
5760
};
5861

5962
function TabSelectorItem({
@@ -70,6 +73,7 @@ function TabSelectorItem({
7073
renderProductTrainingTooltip,
7174
parentX = 0,
7275
parentWidth = 0,
76+
equalWidth = false,
7377
}: TabSelectorItemProps) {
7478
const styles = useThemeStyles();
7579
const [isHovered, setIsHovered] = useState(false);
@@ -112,7 +116,7 @@ function TabSelectorItem({
112116
<AnimatedPressableWithFeedback
113117
accessibilityLabel={title}
114118
style={[styles.tabSelectorButton, styles.tabBackground(isHovered, isActive, backgroundColor), styles.userSelectNone]}
115-
wrapperStyle={[styles.flexGrow1]}
119+
wrapperStyle={[equalWidth ? styles.flex1 : styles.flexGrow1]}
116120
onPress={onPress}
117121
onHoverIn={() => setIsHovered(true)}
118122
onHoverOut={() => setIsHovered(false)}
@@ -131,6 +135,7 @@ function TabSelectorItem({
131135
title={title}
132136
activeOpacity={styles.tabOpacity(isHovered, isActive, activeOpacity, inactiveOpacity).opacity}
133137
inactiveOpacity={styles.tabOpacity(isHovered, isActive, inactiveOpacity, activeOpacity).opacity}
138+
hasIcon={!!icon}
134139
/>
135140
)}
136141
</AnimatedPressableWithFeedback>

src/languages/de.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3550,11 +3550,33 @@ const translations = {
35503550
connect: 'Jetzt verbinden',
35513551
uber: {
35523552
subtitle: 'Automatisieren Sie die Reisekosten und Essenslieferungskosten in Ihrem gesamten Unternehmen.',
3553+
sendInvites: 'Mitglieder einladen',
3554+
sendInvitesDescription: 'Diese Workspace-Mitglieder haben noch kein Uber for Business-Konto. Deaktivieren Sie alle Mitglieder, die Sie derzeit nicht einladen möchten.',
3555+
confirmInvite: 'Einladung bestätigen',
3556+
manageInvites: 'Einladungen verwalten',
3557+
confirm: 'Bestätigen',
3558+
allSet: 'Alles erledigt',
3559+
readyToRoll: 'Sie sind startklar',
3560+
takeBusinessRideMessage: "Machen Sie eine Geschäftsfahrt und Ihre Uber-Belege werden in Expensify importiert. Los geht's!",
3561+
all: 'Alle',
3562+
linked: 'Verknüpft',
3563+
outstanding: 'Ausstehend',
3564+
status: {
3565+
resend: 'Erneut senden',
3566+
invite: 'Einladen',
3567+
[CONST.POLICY.RECEIPT_PARTNERS.UBER_EMPLOYEE_STATUS.LINKED]: 'Verknüpft',
3568+
[CONST.POLICY.RECEIPT_PARTNERS.UBER_EMPLOYEE_STATUS.LINKED_PENDING_APPROVAL]: 'Ausstehend',
3569+
[CONST.POLICY.RECEIPT_PARTNERS.UBER_EMPLOYEE_STATUS.SUSPENDED]: 'Gesperrt',
3570+
},
3571+
invitationFailure: 'Mitglieder konnten nicht zu Uber for Business eingeladen werden',
35533572
autoRemove: 'Neue Workspace-Mitglieder zu Uber for Business einladen',
35543573
autoInvite: 'Entfernte Workspace-Mitglieder von Uber for Business deaktivieren',
3555-
manageInvites: 'Einladungen verwalten',
35563574
bannerTitle: 'Expensify + Uber ren pekin angang',
35573575
bannerDescription: 'Kopwe riri ngeni Uber ren Business pwe epwe otot ren monien sai me mongo non unusen om mwicheich.',
3576+
emptyContent: {
3577+
title: 'Keine Mitglieder zur Anzeige',
3578+
subtitle: 'Wir haben überall gesucht und nichts gefunden.',
3579+
},
35583580
},
35593581
},
35603582
perDiem: {

src/languages/en.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3547,11 +3547,33 @@ const translations = {
35473547
connect: 'Connect now',
35483548
uber: {
35493549
subtitle: 'Automate travel and meal delivery expenses across your organization.',
3550+
sendInvites: 'Send invites',
3551+
sendInvitesDescription: "These workspace members don't have an Uber for Business account yet. Unselect any members you do not wish to invite at this time.",
3552+
confirmInvite: 'Confirm invite',
3553+
manageInvites: 'Manage invites',
3554+
confirm: 'Confirm',
3555+
allSet: 'All set',
3556+
readyToRoll: "You're ready to roll",
3557+
takeBusinessRideMessage: 'Take a business ride and your Uber receipts will import into Expensify. Scoot!',
3558+
all: 'All',
3559+
linked: 'Linked',
3560+
outstanding: 'Outstanding',
3561+
status: {
3562+
resend: 'Resend',
3563+
invite: 'Invite',
3564+
[CONST.POLICY.RECEIPT_PARTNERS.UBER_EMPLOYEE_STATUS.LINKED]: 'Linked',
3565+
[CONST.POLICY.RECEIPT_PARTNERS.UBER_EMPLOYEE_STATUS.LINKED_PENDING_APPROVAL]: 'Pending',
3566+
[CONST.POLICY.RECEIPT_PARTNERS.UBER_EMPLOYEE_STATUS.SUSPENDED]: 'Suspended',
3567+
},
3568+
invitationFailure: 'Failed to invite members to Uber for Business',
35503569
autoRemove: 'Invite new workspace members to Uber for Business',
35513570
autoInvite: 'Deactivate removed workspace members from Uber for Business',
3552-
manageInvites: 'Manage invites',
35533571
bannerTitle: 'Expensify + Uber for Business',
35543572
bannerDescription: 'Connect Uber for Business to automate travel and meal delivery expenses across your organization.',
3573+
emptyContent: {
3574+
title: 'No members to display',
3575+
subtitle: 'We looked everywhere and couldn’t find anything.',
3576+
},
35553577
},
35563578
},
35573579
perDiem: {

0 commit comments

Comments
 (0)