-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
22875 Add API Calls when clicking “Reveal details” buttons #29017
Changes from 2 commits
f73d601
5985ec1
df10ff7
36fb11a
bfdb546
9a8962c
c7dd8fa
ccf8f4e
ef623a4
f7ba68a
9f173af
8361350
36a6d4e
28ca868
a7bcbb6
f1aad79
42cb473
6dac4ca
dcb188b
8254860
586f20e
aaa7042
95d4a43
934344a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import PropTypes from 'prop-types'; | ||
import React, {useState} from 'react'; | ||
import React, {useReducer} from 'react'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should start with |
||
import {ScrollView, View} from 'react-native'; | ||
import {withOnyx} from 'react-native-onyx'; | ||
import _ from 'underscore'; | ||
|
@@ -18,6 +18,10 @@ import styles from '../../../styles/styles'; | |
import * as CardUtils from '../../../libs/CardUtils'; | ||
import Button from '../../../components/Button'; | ||
import CardDetails from './WalletPage/CardDetails'; | ||
// eslint-disable-next-line rulesdir/no-api-in-views | ||
import * as API from '../../../libs/API'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is here for a reason. If you want to call an API you need to create an "action" in the |
||
import CONST from '../../../CONST'; | ||
import * as revealCardDetailsUtils from './revealCardDetailsUtils'; | ||
|
||
const propTypes = { | ||
/* Onyx Props */ | ||
|
@@ -47,7 +51,7 @@ function ExpensifyCardPage({ | |
const virtualCard = _.find(domainCards, (card) => card.isVirtual) || {}; | ||
const physicalCard = _.find(domainCards, (card) => !card.isVirtual) || {}; | ||
|
||
const [shouldShowCardDetails, setShouldShowCardDetails] = useState(false); | ||
const [{loading, details, error}, dispatch] = useReducer(revealCardDetailsUtils.reducer, revealCardDetailsUtils.initialState); | ||
|
||
if (_.isEmpty(virtualCard) && _.isEmpty(physicalCard)) { | ||
return <NotFoundPage />; | ||
|
@@ -56,7 +60,19 @@ function ExpensifyCardPage({ | |
const formattedAvailableSpendAmount = CurrencyUtils.convertToDisplayString(physicalCard.availableSpend || virtualCard.availableSpend || 0); | ||
|
||
const handleRevealDetails = () => { | ||
setShouldShowCardDetails(true); | ||
dispatch({type: 'START'}); | ||
// eslint-disable-next-line | ||
API.makeRequestWithSideEffects('RevealVirtualCardDetails') | ||
.then((response) => { | ||
if (response.jsonCode !== CONST.JSON_CODE.SUCCESS) { | ||
dispatch({type: 'FAIL', payload: response.message}); | ||
return; | ||
} | ||
dispatch({type: 'SUCCESS', payload: response}); | ||
}) | ||
.catch((err) => { | ||
dispatch({type: 'FAIL', payload: err.message}); | ||
}); | ||
}; | ||
|
||
return ( | ||
|
@@ -83,12 +99,12 @@ function ExpensifyCardPage({ | |
/> | ||
{!_.isEmpty(virtualCard) && ( | ||
<> | ||
{shouldShowCardDetails ? ( | ||
{details.pan ? ( | ||
<CardDetails | ||
// This is just a temporary mock, it will be replaced in this issue https://github.com/orgs/Expensify/projects/58?pane=issue&itemId=33286617 | ||
pan="1234123412341234" | ||
expiration="11/02/2024" | ||
cvv="321" | ||
pan={details.pan} | ||
expiration={details.expiration} | ||
cvv={details.cvv} | ||
privatePersonalDetails={details.privatePersonalDetails} | ||
/> | ||
) : ( | ||
<MenuItemWithTopDescription | ||
|
@@ -97,11 +113,14 @@ function ExpensifyCardPage({ | |
interactive={false} | ||
titleStyle={styles.walletCardNumber} | ||
shouldShowRightComponent | ||
error={error} | ||
rightComponent={ | ||
<Button | ||
medium | ||
text={translate('cardPage.cardDetails.revealDetails')} | ||
onPress={handleRevealDetails} | ||
isDisabled={loading} | ||
isLoading={loading} | ||
/> | ||
} | ||
/> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
type State = { | ||
details: { | ||
pan: string; | ||
expiration: string; | ||
cvv: string; | ||
privatePersonalDetails: { | ||
address: { | ||
street: string; | ||
street2: string; | ||
city: string; | ||
state: string; | ||
zip: string; | ||
country: string; | ||
}; | ||
}; | ||
}; | ||
loading: boolean; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should be named |
||
error: string; | ||
}; | ||
|
||
type Action = {type: 'START'} | {type: 'SUCCESS'; payload: State['details']} | {type: 'FAIL'; payload: string}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit, Id move 'START', 'SUCCESS', 'FAIL' to some kind of const variable There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's TS typed, so the right values should be autocompleted by the IDE, hence no constants needed imo. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Card page is in .js tho. Im not sure if any checks happen there when dispatching actions |
||
|
||
const initialState: State = { | ||
details: { | ||
pan: '', | ||
expiration: '', | ||
cvv: '', | ||
privatePersonalDetails: { | ||
address: { | ||
street: '', | ||
street2: '', | ||
city: '', | ||
state: '', | ||
zip: '', | ||
country: '', | ||
}, | ||
}, | ||
}, | ||
loading: false, | ||
error: '', | ||
}; | ||
|
||
const reducer = (state: State, action: Action) => { | ||
switch (action.type) { | ||
case 'START': | ||
return {...state, loading: true}; | ||
case 'SUCCESS': | ||
return {details: action.payload, loading: false, error: ''}; | ||
case 'FAIL': { | ||
return {...state, error: action.payload, loading: false}; | ||
} | ||
default: | ||
return state; | ||
} | ||
}; | ||
|
||
export {initialState, reducer}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing should change in this file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're right!