Skip to content

Commit a3ca8ef

Browse files
author
Jon Tzeng
committed
Add Gift Card Account Information scene
New scene to view Phaze account credentials behind a confirmation wall. Shows quoteId context when accessed from a specific card. After the user confirms a ConfirmContinueModal warning about redemption risk, identity data (email, user ID) is revealed with copy buttons.
1 parent fed4396 commit a3ca8ef

5 files changed

Lines changed: 169 additions & 0 deletions

File tree

src/components/Main.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import { EdgeHeader } from './navigation/EdgeHeader'
4949
import { PluginBackButton } from './navigation/GuiPluginBackButton'
5050
import { HeaderBackground } from './navigation/HeaderBackground'
5151
import { HeaderTextButton } from './navigation/HeaderTextButton'
52+
import { HeaderTitle } from './navigation/HeaderTitle'
5253
import { ParamHeaderTitle } from './navigation/ParamHeaderTitle'
5354
import { SideMenuButton } from './navigation/SideMenuButton'
5455
import { TransactionDetailsTitle } from './navigation/TransactionDetailsTitle'
@@ -96,6 +97,7 @@ import { FioSentRequestDetailsScene as FioSentRequestDetailsSceneComponent } fro
9697
import { FioStakingChangeScene as FioStakingChangeSceneComponent } from './scenes/Fio/FioStakingChangeScene'
9798
import { FioStakingOverviewScene as FioStakingOverviewSceneComponent } from './scenes/Fio/FioStakingOverviewScene'
9899
import { GettingStartedScene } from './scenes/GettingStartedScene'
100+
import { GiftCardAccountInfoScene as GiftCardAccountInfoSceneComponent } from './scenes/GiftCardAccountInfoScene'
99101
import { GiftCardListScene as GiftCardListSceneComponent } from './scenes/GiftCardListScene'
100102
import { GiftCardMarketScene as GiftCardMarketSceneComponent } from './scenes/GiftCardMarketScene'
101103
import { GiftCardPurchaseScene as GiftCardPurchaseSceneComponent } from './scenes/GiftCardPurchaseScene'
@@ -244,6 +246,7 @@ const FioStakingChangeScene = ifLoggedIn(FioStakingChangeSceneComponent)
244246
const FioStakingOverviewScene = ifLoggedIn(FioStakingOverviewSceneComponent)
245247
const GuiPluginViewScene = ifLoggedIn(GuiPluginViewSceneComponent)
246248
const HomeScene = ifLoggedIn(HomeSceneComponent)
249+
const GiftCardAccountInfoScene = ifLoggedIn(GiftCardAccountInfoSceneComponent)
247250
const GiftCardListScene = ifLoggedIn(GiftCardListSceneComponent)
248251
const GiftCardMarketScene = ifLoggedIn(GiftCardMarketSceneComponent)
249252
const GiftCardPurchaseScene = ifLoggedIn(GiftCardPurchaseSceneComponent)
@@ -951,6 +954,15 @@ const EdgeAppStack: React.FC = () => {
951954
name="fioStakingOverview"
952955
component={FioStakingOverviewScene}
953956
/>
957+
<AppStack.Screen
958+
name="giftCardAccountInfo"
959+
component={GiftCardAccountInfoScene}
960+
options={{
961+
headerTitle: () => (
962+
<HeaderTitle title={lstrings.gift_card_account_info_title} />
963+
)
964+
}}
965+
/>
954966
<AppStack.Screen name="giftCardList" component={GiftCardListScene} />
955967
<AppStack.Screen name="giftCardMarket" component={GiftCardMarketScene} />
956968
<AppStack.Screen
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import Clipboard from '@react-native-clipboard/clipboard'
2+
import { useQuery } from '@tanstack/react-query'
3+
import * as React from 'react'
4+
import { View } from 'react-native'
5+
6+
import { ENV } from '../../env'
7+
import { useGiftCardProvider } from '../../hooks/useGiftCardProvider'
8+
import { useHandler } from '../../hooks/useHandler'
9+
import { lstrings } from '../../locales/strings'
10+
import { useSelector } from '../../types/reactRedux'
11+
import type { EdgeAppSceneProps } from '../../types/routerTypes'
12+
import { SceneButtons } from '../buttons/SceneButtons'
13+
import { EdgeCard } from '../cards/EdgeCard'
14+
import { SceneWrapper } from '../common/SceneWrapper'
15+
import { ConfirmContinueModal } from '../modals/ConfirmContinueModal'
16+
import { EdgeRow } from '../rows/EdgeRow'
17+
import { Airship, showError, showToast } from '../services/AirshipInstance'
18+
import { cacheStyles, type Theme, useTheme } from '../services/ThemeContext'
19+
import { Paragraph } from '../themed/EdgeText'
20+
21+
export interface GiftCardAccountInfoParams {
22+
quoteId?: string
23+
}
24+
25+
/**
26+
* Displays Phaze gift card account credentials behind a confirmation wall.
27+
* Accessible from the kebab menu (with quoteId context) or developer settings.
28+
*/
29+
export const GiftCardAccountInfoScene: React.FC<
30+
EdgeAppSceneProps<'giftCardAccountInfo'>
31+
> = props => {
32+
const { route } = props
33+
const { quoteId } = route.params
34+
const theme = useTheme()
35+
const styles = getStyles(theme)
36+
37+
const account = useSelector(state => state.core.account)
38+
39+
// Provider for identity lookup
40+
const phazeConfig = (ENV.PLUGIN_API_KEYS as Record<string, unknown>)
41+
?.phaze as { apiKey?: string; baseUrl?: string } | undefined
42+
const { provider } = useGiftCardProvider({
43+
account,
44+
apiKey: phazeConfig?.apiKey ?? '',
45+
baseUrl: phazeConfig?.baseUrl ?? ''
46+
})
47+
48+
const [isRevealed, setIsRevealed] = React.useState(false)
49+
50+
const { data: identities = [], error } = useQuery({
51+
queryKey: ['phazeIdentities', account.id],
52+
queryFn: async () => {
53+
if (provider == null) throw new Error('Provider not ready')
54+
return await provider.listIdentities(account)
55+
},
56+
enabled: isRevealed && provider != null
57+
})
58+
59+
React.useEffect(() => {
60+
if (error != null) showError(error)
61+
}, [error])
62+
63+
const handleReveal = useHandler(async () => {
64+
const confirmed = await Airship.show<boolean>(bridge => (
65+
<ConfirmContinueModal
66+
bridge={bridge}
67+
title={lstrings.gift_card_account_info_title}
68+
body={lstrings.gift_card_account_info_warning}
69+
warning
70+
onPress={async () => true}
71+
/>
72+
))
73+
if (confirmed) {
74+
setIsRevealed(true)
75+
}
76+
})
77+
78+
const handleCopyAll = useHandler(async () => {
79+
const lines: string[] = []
80+
81+
if (quoteId != null) {
82+
lines.push(`${lstrings.gift_card_quote_id_label}: ${quoteId}`)
83+
}
84+
85+
identities.forEach(identity => {
86+
lines.push(`${lstrings.gift_card_account_info_email}: ${identity.email}`)
87+
})
88+
89+
const text = lines.join('\n')
90+
Clipboard.setString(text)
91+
showToast(lstrings.fragment_copied)
92+
})
93+
94+
return (
95+
<SceneWrapper scroll={isRevealed}>
96+
<View style={styles.container}>
97+
<Paragraph>{lstrings.gift_card_account_info_body}</Paragraph>
98+
99+
{isRevealed && (
100+
<EdgeCard sections>
101+
{quoteId != null && (
102+
<EdgeRow
103+
title={lstrings.gift_card_quote_id_label}
104+
body={quoteId}
105+
/>
106+
)}
107+
{identities.map(identity => (
108+
<EdgeRow
109+
key={String(identity.id)}
110+
title={lstrings.gift_card_account_info_email}
111+
body={identity.email}
112+
/>
113+
))}
114+
</EdgeCard>
115+
)}
116+
117+
<SceneButtons
118+
primary={
119+
isRevealed
120+
? {
121+
label: lstrings.fragment_request_copy_title,
122+
onPress: handleCopyAll
123+
}
124+
: {
125+
label: lstrings.gift_card_account_info_reveal_button,
126+
onPress: handleReveal
127+
}
128+
}
129+
/>
130+
</View>
131+
</SceneWrapper>
132+
)
133+
}
134+
135+
const getStyles = cacheStyles((theme: Theme) => ({
136+
container: {
137+
padding: theme.rem(0.5)
138+
}
139+
}))

src/locales/en_US.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,6 +1966,15 @@ const strings = {
19661966
gift_card_active_cards: 'Active Cards',
19671967
gift_card_confirming: 'Awaiting Payment Confirmations...',
19681968
gift_card_failed: 'Failed',
1969+
gift_card_get_help: 'Get Help',
1970+
gift_card_account_info_title: 'Gift Card Account Information',
1971+
gift_card_account_info_body:
1972+
'The information below is your customer credentials used with our Phaze gift card provider. Share this with our support team to troubleshoot gift card purchases.',
1973+
gift_card_account_info_reveal_button: 'View Phaze Account Info',
1974+
gift_card_account_info_warning:
1975+
'Anyone with access to this information may be able to redeem your unredeemed gift cards. Do not share this publicly.',
1976+
gift_card_account_info_email: 'Account Email',
1977+
gift_card_account_info_user_id: 'Phaze User ID',
19691978
gift_card_pending: 'Pending Delivery, Please Wait...',
19701979
gift_card_pending_toast:
19711980
'Your gift card is being delivered. Please wait for a few minutes for it to arrive.',

src/locales/strings/enUS.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,6 +1528,13 @@
15281528
"gift_card_active_cards": "Active Cards",
15291529
"gift_card_confirming": "Awaiting Payment Confirmations...",
15301530
"gift_card_failed": "Failed",
1531+
"gift_card_get_help": "Get Help",
1532+
"gift_card_account_info_title": "Gift Card Account Information",
1533+
"gift_card_account_info_body": "The information below is your customer credentials used with our Phaze gift card provider. Share this with our support team to troubleshoot gift card purchases.",
1534+
"gift_card_account_info_reveal_button": "View Phaze Account Info",
1535+
"gift_card_account_info_warning": "Anyone with access to this information may be able to redeem your unredeemed gift cards. Do not share this publicly.",
1536+
"gift_card_account_info_email": "Account Email",
1537+
"gift_card_account_info_user_id": "Phaze User ID",
15311538
"gift_card_pending": "Pending Delivery, Please Wait...",
15321539
"gift_card_pending_toast": "Your gift card is being delivered. Please wait for a few minutes for it to arrive.",
15331540
"gift_card_quote_id_label": "Quote ID",

src/types/routerTypes.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import type { FioSentRequestDetailsParams } from '../components/scenes/Fio/FioSe
3535
import type { FioStakingChangeParams } from '../components/scenes/Fio/FioStakingChangeScene'
3636
import type { FioStakingOverviewParams } from '../components/scenes/Fio/FioStakingOverviewScene'
3737
import type { GettingStartedParams } from '../components/scenes/GettingStartedScene'
38+
import type { GiftCardAccountInfoParams } from '../components/scenes/GiftCardAccountInfoScene'
3839
import type { GiftCardPurchaseParams } from '../components/scenes/GiftCardPurchaseScene'
3940
import type { GuiPluginListParams } from '../components/scenes/GuiPluginListScene'
4041
import type { PluginViewParams } from '../components/scenes/GuiPluginViewScene'
@@ -206,6 +207,7 @@ export type EdgeAppStackParamList = {} & {
206207
fioSentRequestDetails: FioSentRequestDetailsParams
207208
fioStakingChange: FioStakingChangeParams
208209
fioStakingOverview: FioStakingOverviewParams
210+
giftCardAccountInfo: GiftCardAccountInfoParams
209211
giftCardList: undefined
210212
giftCardMarket: undefined
211213
giftCardPurchase: GiftCardPurchaseParams

0 commit comments

Comments
 (0)