1+ import Clipboard from '@react-native-clipboard/clipboard'
12import type { EdgeTxActionGiftCard } from 'edge-core-js'
23import * as React from 'react'
3- import { Linking } from 'react-native'
4+ import { Linking , View } from 'react-native'
45
56import { useHandler } from '../../hooks/useHandler'
67import { lstrings } from '../../locales/strings'
8+ import { triggerHaptic } from '../../util/haptic'
79import { removeIsoPrefix } from '../../util/utils'
810import { CircularBrandIcon } from '../common/CircularBrandIcon'
11+ import { DividerLineUi4 } from '../common/DividerLineUi4'
12+ import { EdgeTouchableOpacity } from '../common/EdgeTouchableOpacity'
13+ import { CopyIcon } from '../icons/ThemedIcons'
914import { EdgeRow } from '../rows/EdgeRow'
15+ import { showToast } from '../services/AirshipInstance'
16+ import { cacheStyles , type Theme , useTheme } from '../services/ThemeContext'
1017import { EdgeText } from '../themed/EdgeText'
1118import { EdgeCard } from './EdgeCard'
1219
@@ -15,11 +22,21 @@ interface Props {
1522}
1623
1724/**
18- * Displays gift card details including brand, amount, and redemption code
19- * in TransactionDetailsScene for gift card purchases.
25+ * Displays gift card details including brand, amount, quote ID, and redemption
26+ * code in TransactionDetailsScene for gift card purchases.
27+ *
28+ * Layout: A left column of data rows with dividers and a single card-level copy
29+ * button on the right. Dividers stop short of the copy button area.
2030 */
2131export const GiftCardDetailsCard : React . FC < Props > = ( { action } ) => {
2232 const { card, redemption } = action
33+ const theme = useTheme ( )
34+ const styles = getStyles ( theme )
35+
36+ // Backward compat: Prior versions stored the quoteId in the `orderId` field
37+ // of EdgeTxActionGiftCard. Once edge-core-js adds an explicit `quoteId`
38+ // field, prefer that and fall back to `orderId` for older transactions.
39+ const quoteId = action . orderId
2340
2441 const handleRedeemPress = useHandler ( ( ) => {
2542 if ( redemption ?. url != null ) {
@@ -43,30 +60,86 @@ export const GiftCardDetailsCard: React.FC<Props> = ({ action }) => {
4360 const fiatCurrency = removeIsoPrefix ( card . fiatCurrencyCode )
4461 const amountDisplay = `${ card . fiatAmount } ${ fiatCurrency } `
4562
63+ // Build formatted string for card-level copy
64+ const copyText = React . useMemo ( ( ) => {
65+ const lines = [
66+ `${ lstrings . gift_card_label } : ${ card . name } ` ,
67+ `${ lstrings . string_amount } : ${ amountDisplay } ` ,
68+ `${ lstrings . gift_card_quote_id_label } : ${ quoteId } `
69+ ]
70+ if ( redemption ?. code != null ) {
71+ lines . push ( `${ lstrings . gift_card_security_code } : ${ redemption . code } ` )
72+ }
73+ return lines . join ( '\n' )
74+ } , [ card . name , amountDisplay , quoteId , redemption ?. code ] )
75+
76+ const handleCopyAll = useHandler ( ( ) => {
77+ triggerHaptic ( 'impactLight' )
78+ Clipboard . setString ( copyText )
79+ showToast ( lstrings . fragment_copied )
80+ } )
81+
4682 return (
47- < EdgeCard sections >
48- < EdgeRow icon = { brandIcon } title = { lstrings . gift_card_label } >
49- < EdgeText > { card . name } </ EdgeText >
50- </ EdgeRow >
51-
52- < EdgeRow title = { lstrings . string_amount } body = { amountDisplay } />
53-
54- { redemption ?. code != null ? (
55- < EdgeRow
56- title = { lstrings . gift_card_security_code }
57- body = { redemption . code }
58- rightButtonType = "copy"
59- />
60- ) : null }
83+ < EdgeCard >
84+ < View style = { styles . cardLayout } >
85+ { /* Left column: data rows with dividers */ }
86+ < View style = { styles . dataColumn } >
87+ < EdgeRow icon = { brandIcon } title = { lstrings . gift_card_label } >
88+ < EdgeText > { card . name } </ EdgeText >
89+ </ EdgeRow >
90+
91+ < DividerLineUi4 />
6192
93+ < EdgeRow title = { lstrings . string_amount } body = { amountDisplay } />
94+
95+ < DividerLineUi4 />
96+
97+ < EdgeRow title = { lstrings . gift_card_quote_id_label } body = { quoteId } />
98+
99+ { redemption ?. code != null ? (
100+ < >
101+ < DividerLineUi4 />
102+ < EdgeRow
103+ title = { lstrings . gift_card_security_code }
104+ body = { redemption . code }
105+ />
106+ </ >
107+ ) : null }
108+ </ View >
109+
110+ { /* Right column: card-level copy button */ }
111+ < EdgeTouchableOpacity style = { styles . copyColumn } onPress = { handleCopyAll } >
112+ < CopyIcon size = { theme . rem ( 1 ) } color = { theme . iconTappable } />
113+ </ EdgeTouchableOpacity >
114+ </ View >
115+
116+ { /* Redeem row outside the copy layout - has its own chevron */ }
62117 { redemption ?. url != null ? (
63- < EdgeRow
64- title = { lstrings . gift_card_redeem }
65- body = { lstrings . gift_card_redeem_visit }
66- rightButtonType = "touchable"
67- onPress = { handleRedeemPress }
68- />
118+ < >
119+ < DividerLineUi4 />
120+ < EdgeRow
121+ title = { lstrings . gift_card_redeem }
122+ body = { lstrings . gift_card_redeem_visit }
123+ rightButtonType = "touchable"
124+ onPress = { handleRedeemPress }
125+ />
126+ </ >
69127 ) : null }
70128 </ EdgeCard >
71129 )
72130}
131+
132+ const getStyles = cacheStyles ( ( theme : Theme ) => ( {
133+ cardLayout : {
134+ flexDirection : 'row' as const
135+ } ,
136+ dataColumn : {
137+ flex : 1 ,
138+ flexDirection : 'column' as const
139+ } ,
140+ copyColumn : {
141+ justifyContent : 'center' as const ,
142+ alignItems : 'center' as const ,
143+ paddingHorizontal : theme . rem ( 0.75 )
144+ }
145+ } ) )
0 commit comments