tf-checkout-react-native 2.0.0-beta.0 → 2.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -24
- package/dist/index.d.mts +8194 -282
- package/dist/index.d.ts +8194 -282
- package/dist/index.js +32308 -7001
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +32547 -7127
- package/dist/index.mjs.map +1 -1
- package/package.json +23 -11
- package/scripts/build-seat-map.mjs +31 -0
- package/scripts/seat-map-entry.jsx +22 -0
- package/scripts/verify-discussion-support.cjs +131 -0
- package/src/CardInput.tsx +64 -3
- package/src/EmbeddedCheckout.tsx +140 -38
- package/src/auth/AuthModal.tsx +186 -9
- package/src/auth/EmailCodeForm.tsx +91 -0
- package/src/auth/RegisterForm.tsx +91 -5
- package/src/auth/TwoFactorForm.tsx +74 -0
- package/src/auth/index.ts +4 -0
- package/src/configure.ts +19 -14
- package/src/confirmer.ts +112 -20
- package/src/generated/seatMapWidget.ts +3 -0
- package/src/index.tsx +1 -1
- package/src/sections/Accommodation.tsx +57 -0
- package/src/sections/AccountDeletion.tsx +347 -0
- package/src/sections/AccountEmailEnrichment.tsx +122 -0
- package/src/sections/AccountInformation.tsx +139 -0
- package/src/sections/AccountPaymentPlan.tsx +105 -0
- package/src/sections/AccountRewards.tsx +108 -0
- package/src/sections/AddOns.tsx +99 -148
- package/src/sections/BillingInfo.tsx +80 -78
- package/src/sections/Bundles.tsx +467 -0
- package/src/sections/EventDiscussionView.tsx +655 -0
- package/src/sections/NotificationPreferences.tsx +244 -0
- package/src/sections/OrderSummary.tsx +29 -2
- package/src/sections/Passes.tsx +177 -0
- package/src/sections/Payment.tsx +170 -53
- package/src/sections/PhoneAuthentication.tsx +371 -0
- package/src/sections/PostReaction.tsx +122 -0
- package/src/sections/ProfileSettings.tsx +446 -0
- package/src/sections/Rewards.tsx +320 -0
- package/src/sections/SeatMap.tsx +225 -0
- package/src/sections/SeatsIoMap.tsx +110 -0
- package/src/sections/Streaming.tsx +278 -0
- package/src/sections/TicketChange.tsx +379 -0
- package/src/sections/TicketGift.tsx +206 -0
- package/src/sections/TicketRefund.tsx +104 -0
- package/src/sections/Tickets.tsx +289 -208
- package/src/sections/Trips.tsx +87 -0
- package/src/sections/WaiverSigning.tsx +429 -0
- package/src/sections/billing/PhoneIdentity.tsx +169 -0
- package/src/sections/billing/TicketHoldersCard.tsx +4 -0
- package/src/sections/discussion/CommentImages.tsx +366 -0
- package/src/sections/discussion/SwipeReply.tsx +88 -0
- package/src/sections/index.ts +46 -0
- package/src/sections/rewards/RewardsLadder.tsx +167 -0
- package/src/sections/rewards/RewardsTree.tsx +117 -0
- package/src/storage.ts +8 -9
- package/src/ui/CheckoutProvider.tsx +51 -15
- package/src/ui/CustomFields.tsx +48 -12
- package/src/ui/Field.tsx +21 -3
- package/src/ui/Frozen.tsx +22 -0
- package/src/ui/InstallmentPicker.tsx +15 -18
- package/src/ui/PaymentMethods.tsx +6 -3
- package/src/ui/ProviderPages.tsx +214 -0
- package/src/ui/QuantitySelect.tsx +28 -3
- package/src/ui/Select.tsx +4 -1
- package/src/ui/SignaturePad.tsx +218 -0
- package/src/ui/index.ts +3 -0
- package/src/ui/primitives.tsx +13 -2
- package/src/ui/useAccountT.ts +16 -0
- package/src/useCheckout.ts +3 -1
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import React, { type FC } from 'react'
|
|
2
|
+
import { View } from 'react-native'
|
|
3
|
+
import { hooks, type TicketGiftProps } from 'tf-checkout-shared'
|
|
4
|
+
import {
|
|
5
|
+
BodyText,
|
|
6
|
+
Button,
|
|
7
|
+
Card,
|
|
8
|
+
ErrorText,
|
|
9
|
+
Loader,
|
|
10
|
+
SectionHeader,
|
|
11
|
+
} from '../ui/primitives'
|
|
12
|
+
import { Checkbox, Field, Input } from '../ui/Field'
|
|
13
|
+
import { useAccountT } from '../ui/useAccountT'
|
|
14
|
+
|
|
15
|
+
export const TicketGift: FC<TicketGiftProps> = ({
|
|
16
|
+
ticketHash,
|
|
17
|
+
onTicketsChanged,
|
|
18
|
+
onDone,
|
|
19
|
+
locale,
|
|
20
|
+
}) => {
|
|
21
|
+
const t = useAccountT(locale)
|
|
22
|
+
const flow = hooks.useTicketGift(ticketHash, onTicketsChanged)
|
|
23
|
+
const { state, query } = flow
|
|
24
|
+
const command = state.command ?? state.submitted
|
|
25
|
+
if (command)
|
|
26
|
+
return (
|
|
27
|
+
<Card>
|
|
28
|
+
<SectionHeader
|
|
29
|
+
title={t(command.kind === 'send' ? 'Review your gift' : 'Cancel gift')}
|
|
30
|
+
/>
|
|
31
|
+
{command.kind === 'send' ? (
|
|
32
|
+
<>
|
|
33
|
+
<BodyText>
|
|
34
|
+
{command.intent.first_name} {command.intent.last_name}
|
|
35
|
+
</BodyText>
|
|
36
|
+
<BodyText>{command.intent.email}</BodyText>
|
|
37
|
+
{query.data?.add_ons
|
|
38
|
+
.filter(
|
|
39
|
+
(item) =>
|
|
40
|
+
!query.data?.select_add_ons ||
|
|
41
|
+
command.intent.add_on_ids.includes(item.id)
|
|
42
|
+
)
|
|
43
|
+
.map((item) => (
|
|
44
|
+
<BodyText key={item.id}>{item.name}</BodyText>
|
|
45
|
+
))}
|
|
46
|
+
<BodyText>
|
|
47
|
+
{t(
|
|
48
|
+
'Once the gift is accepted, this ticket will belong to the recipient and you will no longer be able to use it.'
|
|
49
|
+
)}
|
|
50
|
+
</BodyText>
|
|
51
|
+
</>
|
|
52
|
+
) : (
|
|
53
|
+
<BodyText>
|
|
54
|
+
{t(
|
|
55
|
+
'Cancel this pending gift so you can keep or send your ticket to someone else?'
|
|
56
|
+
)}
|
|
57
|
+
</BodyText>
|
|
58
|
+
)}
|
|
59
|
+
{state.error && <ErrorText>{t(state.error)}</ErrorText>}
|
|
60
|
+
<Button
|
|
61
|
+
loading={state.busy}
|
|
62
|
+
disabled={state.busy}
|
|
63
|
+
onPress={() => void flow.submit()}
|
|
64
|
+
>
|
|
65
|
+
{t(
|
|
66
|
+
state.submitted
|
|
67
|
+
? 'Check gift status'
|
|
68
|
+
: command.kind === 'send'
|
|
69
|
+
? 'Send gift'
|
|
70
|
+
: 'Cancel gift'
|
|
71
|
+
)}
|
|
72
|
+
</Button>
|
|
73
|
+
{!state.submitted && (
|
|
74
|
+
<Button variant="ghost" onPress={flow.back}>
|
|
75
|
+
{t('Back')}
|
|
76
|
+
</Button>
|
|
77
|
+
)}
|
|
78
|
+
</Card>
|
|
79
|
+
)
|
|
80
|
+
if (query.isLoading) return <Loader />
|
|
81
|
+
if (query.error)
|
|
82
|
+
return (
|
|
83
|
+
<Card>
|
|
84
|
+
<ErrorText>{t(query.error.message)}</ErrorText>
|
|
85
|
+
<Button onPress={() => void query.refetch()}>{t('Try again')}</Button>
|
|
86
|
+
</Card>
|
|
87
|
+
)
|
|
88
|
+
const gift = query.data
|
|
89
|
+
if (!gift) return null
|
|
90
|
+
return (
|
|
91
|
+
<Card>
|
|
92
|
+
<SectionHeader title={t('Gift ticket')} />
|
|
93
|
+
{state.result === 'cancelled' && (
|
|
94
|
+
<BodyText>{t('Your gift was cancelled. Your ticket is still yours.')}</BodyText>
|
|
95
|
+
)}
|
|
96
|
+
{gift.status === 'sent' && (
|
|
97
|
+
<BodyText>
|
|
98
|
+
{t('Your ticket has been given to the recipient. You can no longer use it.')}
|
|
99
|
+
</BodyText>
|
|
100
|
+
)}
|
|
101
|
+
{gift.pending && (
|
|
102
|
+
<>
|
|
103
|
+
<BodyText>
|
|
104
|
+
{t(
|
|
105
|
+
gift.status === 'processing'
|
|
106
|
+
? 'Your gift is being completed.'
|
|
107
|
+
: 'Your gift is waiting for the recipient to accept it.'
|
|
108
|
+
)}
|
|
109
|
+
</BodyText>
|
|
110
|
+
<BodyText>
|
|
111
|
+
{gift.pending.first_name} {gift.pending.last_name}
|
|
112
|
+
</BodyText>
|
|
113
|
+
<BodyText>{gift.pending.email}</BodyText>
|
|
114
|
+
{gift.pending.can_cancel && (
|
|
115
|
+
<Button onPress={flow.confirmCancel}>{t('Cancel gift')}</Button>
|
|
116
|
+
)}
|
|
117
|
+
<Button variant="ghost" onPress={() => void query.refetch()}>
|
|
118
|
+
{t('Check gift status')}
|
|
119
|
+
</Button>
|
|
120
|
+
</>
|
|
121
|
+
)}
|
|
122
|
+
{gift.can_send ? (
|
|
123
|
+
<View style={{ gap: 12 }}>
|
|
124
|
+
<BodyText>
|
|
125
|
+
{t(
|
|
126
|
+
'Give this ticket to someone else. Once they receive it, you will no longer own it or be able to use it.'
|
|
127
|
+
)}
|
|
128
|
+
</BodyText>
|
|
129
|
+
<Field label={t('First name')}>
|
|
130
|
+
<Input
|
|
131
|
+
value={state.draft.first_name}
|
|
132
|
+
accessibilityLabel={t('First name')}
|
|
133
|
+
maxLength={100}
|
|
134
|
+
onChangeText={(value) => flow.edit({ first_name: value })}
|
|
135
|
+
autoCapitalize="words"
|
|
136
|
+
/>
|
|
137
|
+
</Field>
|
|
138
|
+
<Field label={t('Last name')}>
|
|
139
|
+
<Input
|
|
140
|
+
value={state.draft.last_name}
|
|
141
|
+
accessibilityLabel={t('Last name')}
|
|
142
|
+
maxLength={100}
|
|
143
|
+
onChangeText={(value) => flow.edit({ last_name: value })}
|
|
144
|
+
autoCapitalize="words"
|
|
145
|
+
/>
|
|
146
|
+
</Field>
|
|
147
|
+
<Field label={t('Email address')}>
|
|
148
|
+
<Input
|
|
149
|
+
value={state.draft.email}
|
|
150
|
+
accessibilityLabel={t('Email address')}
|
|
151
|
+
maxLength={254}
|
|
152
|
+
onChangeText={(value) => flow.edit({ email: value })}
|
|
153
|
+
keyboardType="email-address"
|
|
154
|
+
autoCapitalize="none"
|
|
155
|
+
/>
|
|
156
|
+
</Field>
|
|
157
|
+
<Field label={t('Confirm email address')}>
|
|
158
|
+
<Input
|
|
159
|
+
value={state.draft.confirm_email}
|
|
160
|
+
accessibilityLabel={t('Confirm email address')}
|
|
161
|
+
maxLength={254}
|
|
162
|
+
onChangeText={(value) => flow.edit({ confirm_email: value })}
|
|
163
|
+
keyboardType="email-address"
|
|
164
|
+
autoCapitalize="none"
|
|
165
|
+
/>
|
|
166
|
+
</Field>
|
|
167
|
+
{gift.add_ons.length > 0 && (
|
|
168
|
+
<BodyText>
|
|
169
|
+
{t(
|
|
170
|
+
gift.select_add_ons
|
|
171
|
+
? 'Choose add-ons to include'
|
|
172
|
+
: 'These add-ons are included with your gift'
|
|
173
|
+
)}
|
|
174
|
+
</BodyText>
|
|
175
|
+
)}
|
|
176
|
+
{gift.add_ons.map((item) =>
|
|
177
|
+
gift.select_add_ons ? (
|
|
178
|
+
<Checkbox
|
|
179
|
+
key={item.id}
|
|
180
|
+
label={item.name}
|
|
181
|
+
checked={state.draft.add_on_ids.includes(item.id)}
|
|
182
|
+
onChange={() => flow.toggleAddOn(item.id)}
|
|
183
|
+
/>
|
|
184
|
+
) : (
|
|
185
|
+
<BodyText key={item.id}>{item.name}</BodyText>
|
|
186
|
+
)
|
|
187
|
+
)}
|
|
188
|
+
<Checkbox
|
|
189
|
+
checked={state.draft.confirm_terms}
|
|
190
|
+
onChange={(value) => flow.edit({ confirm_terms: value })}
|
|
191
|
+
label={t('I understand that this ticket will belong to the recipient.')}
|
|
192
|
+
/>
|
|
193
|
+
{state.error && <ErrorText>{t(state.error)}</ErrorText>}
|
|
194
|
+
<Button onPress={flow.review}>{t('Review gift')}</Button>
|
|
195
|
+
</View>
|
|
196
|
+
) : gift.status === 'unavailable' ? (
|
|
197
|
+
<BodyText>{t('This ticket cannot be gifted now.')}</BodyText>
|
|
198
|
+
) : null}
|
|
199
|
+
{onDone && (
|
|
200
|
+
<Button variant="ghost" onPress={onDone}>
|
|
201
|
+
{t('View my tickets')}
|
|
202
|
+
</Button>
|
|
203
|
+
)}
|
|
204
|
+
</Card>
|
|
205
|
+
)
|
|
206
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import React, { type FC } from 'react'
|
|
2
|
+
import { Pressable, View } from 'react-native'
|
|
3
|
+
import { hooks, ticketRefundConsequences } from 'tf-checkout-shared'
|
|
4
|
+
import {
|
|
5
|
+
BodyText,
|
|
6
|
+
Button,
|
|
7
|
+
Card,
|
|
8
|
+
ErrorText,
|
|
9
|
+
Loader,
|
|
10
|
+
MutedText,
|
|
11
|
+
SectionHeader,
|
|
12
|
+
} from '../ui/primitives'
|
|
13
|
+
import { Checkbox } from '../ui/Field'
|
|
14
|
+
import { FrozenFields } from '../ui/Frozen'
|
|
15
|
+
|
|
16
|
+
export interface TicketRefundProps {
|
|
17
|
+
ticketHash: string
|
|
18
|
+
onSubmitted?: () => void
|
|
19
|
+
onDone?: () => void
|
|
20
|
+
}
|
|
21
|
+
export const TicketRefund: FC<TicketRefundProps> = ({
|
|
22
|
+
ticketHash,
|
|
23
|
+
onSubmitted,
|
|
24
|
+
onDone,
|
|
25
|
+
}) => {
|
|
26
|
+
const refund = hooks.useTicketRefund(ticketHash, onSubmitted)
|
|
27
|
+
if (refund.result)
|
|
28
|
+
return (
|
|
29
|
+
<Card>
|
|
30
|
+
<SectionHeader title="Refund requested" />
|
|
31
|
+
<BodyText>
|
|
32
|
+
Your refund request has been submitted. We’ll email you when it is complete.
|
|
33
|
+
</BodyText>
|
|
34
|
+
{onDone && <Button onPress={onDone}>View my tickets</Button>}
|
|
35
|
+
</Card>
|
|
36
|
+
)
|
|
37
|
+
if (refund.query.isLoading) return <Loader />
|
|
38
|
+
if (refund.query.isError)
|
|
39
|
+
return (
|
|
40
|
+
<Card>
|
|
41
|
+
<ErrorText>{refund.query.error.message}</ErrorText>
|
|
42
|
+
<Button onPress={() => void refund.query.refetch()}>Try again</Button>
|
|
43
|
+
</Card>
|
|
44
|
+
)
|
|
45
|
+
const options = refund.query.data?.options ?? []
|
|
46
|
+
return (
|
|
47
|
+
<Card>
|
|
48
|
+
<SectionHeader title="Refund ticket" />
|
|
49
|
+
{!options.length && (
|
|
50
|
+
<BodyText>
|
|
51
|
+
{refund.query.data?.eligibility_reason ||
|
|
52
|
+
'No refund choices are available for this ticket.'}
|
|
53
|
+
</BodyText>
|
|
54
|
+
)}
|
|
55
|
+
{options.map((option) => (
|
|
56
|
+
<Pressable
|
|
57
|
+
key={option.option_id}
|
|
58
|
+
accessibilityRole="radio"
|
|
59
|
+
accessibilityState={{
|
|
60
|
+
checked: refund.selected?.option_id === option.option_id,
|
|
61
|
+
disabled: refund.busy || refund.commandPending,
|
|
62
|
+
}}
|
|
63
|
+
disabled={refund.busy || refund.commandPending}
|
|
64
|
+
onPress={() => refund.select(option.option_id)}
|
|
65
|
+
>
|
|
66
|
+
<BodyText>
|
|
67
|
+
{refund.selected?.option_id === option.option_id ? '● ' : '○ '}
|
|
68
|
+
{option.currency} {option.amount}
|
|
69
|
+
</BodyText>
|
|
70
|
+
</Pressable>
|
|
71
|
+
))}
|
|
72
|
+
{refund.selected && (
|
|
73
|
+
<View style={{ gap: 8 }}>
|
|
74
|
+
<BodyText>
|
|
75
|
+
You’ll receive {refund.selected.currency} {refund.selected.amount}.
|
|
76
|
+
</BodyText>
|
|
77
|
+
<MutedText>
|
|
78
|
+
Amount retained: {refund.selected.currency} {refund.selected.retained_amount}
|
|
79
|
+
</MutedText>
|
|
80
|
+
{ticketRefundConsequences(refund.selected).map((line) => (
|
|
81
|
+
<BodyText key={line}>{line}</BodyText>
|
|
82
|
+
))}
|
|
83
|
+
<FrozenFields frozen={refund.busy || refund.commandPending}>
|
|
84
|
+
<Checkbox
|
|
85
|
+
label="I have reviewed this refund and its effect on my ticket and add-ons."
|
|
86
|
+
checked={refund.confirmed}
|
|
87
|
+
onChange={refund.confirm}
|
|
88
|
+
/>
|
|
89
|
+
</FrozenFields>
|
|
90
|
+
</View>
|
|
91
|
+
)}
|
|
92
|
+
{refund.error && <ErrorText>{refund.error}</ErrorText>}
|
|
93
|
+
{(refund.selected || refund.commandPending) && (
|
|
94
|
+
<Button
|
|
95
|
+
onPress={() => void refund.submit()}
|
|
96
|
+
loading={refund.busy}
|
|
97
|
+
disabled={refund.busy || (!refund.commandPending && !refund.confirmed)}
|
|
98
|
+
>
|
|
99
|
+
{refund.commandPending ? 'Check refund request' : 'Confirm refund'}
|
|
100
|
+
</Button>
|
|
101
|
+
)}
|
|
102
|
+
</Card>
|
|
103
|
+
)
|
|
104
|
+
}
|