1
- import React , { useState } from 'react'
2
- import AddressForm from '../Address/AddressForm'
3
1
import {
4
2
Elements ,
5
- CardElement ,
6
- IbanElement ,
7
- useStripe ,
3
+ PaymentElement ,
8
4
useElements ,
5
+ useStripe ,
9
6
} from '@stripe/react-stripe-js'
10
7
import { loadStripe } from '@stripe/stripe-js'
11
- import CreditCardForm from '../PaymentCard/CreditCardForm'
12
- import { RadioTileGroup } from 'ui/RadioTileGroup'
13
- import Icon from 'ui/Icon'
8
+ import React , { useState } from 'react'
9
+
10
+ import Button from 'ui/Button'
11
+
12
+ import AddressForm from '../Address/AddressForm'
14
13
15
- // Load your Stripe public key
16
- const stripePromise = loadStripe ( 'your-publishable-key-here' )
14
+ // TODO - fetch from API
15
+ const STRIPE_PUBLISHABLE_KEY = process . env . STRIPE_PUBLISHABLE_KEY || ''
16
+ const MANUALLY_FETCHED_CLIENT_SECRET = process . env . STRIPE_CLIENT_SECRET || ''
17
+
18
+ const stripePromise = loadStripe ( STRIPE_PUBLISHABLE_KEY )
17
19
18
20
interface PaymentFormProps {
19
21
clientSecret : string
20
22
}
21
23
22
- const PaymentForm : React . FC < PaymentFormProps > = ( { clientSecret } ) => {
24
+ const PaymentForm : React . FC < PaymentFormProps > = ( ) => {
23
25
const stripe = useStripe ( )
24
26
const elements = useElements ( )
25
- const [ paymentMethod , setPaymentMethod ] = useState < 'card' | 'bank' > ( 'card' )
26
27
const [ isSubmitting , setIsSubmitting ] = useState ( false )
27
28
const [ errorMessage , setErrorMessage ] = useState < string | null > ( null )
28
29
@@ -37,21 +38,11 @@ const PaymentForm: React.FC<PaymentFormProps> = ({ clientSecret }) => {
37
38
return
38
39
}
39
40
40
- const paymentElement = elements . getElement (
41
- paymentMethod === 'card' ? CardElement : IbanElement
42
- )
43
-
44
- if ( ! paymentElement ) {
45
- setErrorMessage ( 'Payment element is missing.' )
46
- setIsSubmitting ( false )
47
- return
48
- }
49
-
50
- // Confirm payment based on selected method
51
41
const { error } = await stripe . confirmPayment ( {
52
42
elements,
53
43
confirmParams : {
54
- return_url : 'https://your-website.com/order-complete' , // Redirect URL
44
+ // eslint-disable-next-line camelcase
45
+ return_url : 'https://codecov.io' ,
55
46
} ,
56
47
} )
57
48
@@ -64,73 +55,50 @@ const PaymentForm: React.FC<PaymentFormProps> = ({ clientSecret }) => {
64
55
}
65
56
66
57
return (
67
- < form onSubmit = { handleSubmit } className = "space-y-4" >
68
- < h2 className = "text-lg font-bold" > Choose Payment Method</ h2 >
69
-
70
- < RadioTileGroup
71
- value = { paymentMethod }
72
- onValueChange = { ( value : 'card' | 'bank' ) => setPaymentMethod ( value ) }
73
- className = "flex-row"
74
- >
75
- < RadioTileGroup . Item value = "card" data-testid = "card-radio" >
76
- < RadioTileGroup . Label >
77
- < div className = "flex items-center gap-2" >
78
- < Icon name = "checkCircle" > </ Icon >
79
- Card
80
- </ div >
81
- </ RadioTileGroup . Label >
82
- </ RadioTileGroup . Item >
83
- < RadioTileGroup . Item value = "bank" data-testid = "bank-radio" >
84
- < RadioTileGroup . Label >
85
- < div className = "flex items-center gap-2" >
86
- < Icon name = "checkCircle" > </ Icon >
87
- Bank Account
88
- </ div >
89
- </ RadioTileGroup . Label >
90
- </ RadioTileGroup . Item >
91
- </ RadioTileGroup >
92
-
93
- { /* Payment Element */ }
94
- { paymentMethod === 'card' && (
95
- < div >
96
- < h3 className = "font-semibold" > Card Details</ h3 >
97
- < CreditCardForm
98
- closeForm = { function ( ) : void {
99
- throw new Error ( 'Function not implemented.' )
100
- } }
101
- provider = { '' }
102
- owner = { '' }
103
- />
104
- </ div >
105
- ) }
106
-
107
- { paymentMethod === 'bank' && (
108
- < div >
109
- < h3 className = "font-semibold" > Bank Account Details</ h3 >
110
- < IbanElement
111
- className = "border p-2 rounded"
112
- options = { {
113
- supportedCountries : [ 'SEPA' ] , // Specify the supported countries
114
- } }
115
- />
116
- </ div >
117
- ) }
58
+ < div >
59
+ < PaymentElement
60
+ options = { {
61
+ layout : 'tabs' ,
62
+ defaultValues : {
63
+ billingDetails : {
64
+ name : 'John Doe' ,
65
+ } ,
66
+ } ,
67
+ } }
68
+ />
69
+ < div className = "mb-8 mt-4 flex gap-1" >
70
+ < Button
71
+ hook = "submit-address-update"
72
+ type = "submit"
73
+ variant = "primary"
74
+ disabled = { isSubmitting } // TODO - handle
75
+ onClick = { handleSubmit }
76
+ to = { undefined }
77
+ >
78
+ Save
79
+ </ Button >
80
+ < Button
81
+ type = "button"
82
+ hook = "cancel-address-update"
83
+ variant = "plain"
84
+ // disabled={isLoading}
85
+ onClick = { ( ) => console . log ( 'TODO - implement me' ) } // TODO - implement me
86
+ to = { undefined }
87
+ >
88
+ Cancel
89
+ </ Button >
90
+ </ div >
118
91
119
92
{ errorMessage && < div className = "text-red-500" > { errorMessage } </ div > }
120
- </ form >
93
+ </ div >
121
94
)
122
95
}
123
96
124
- // Wrapper Component to provide Stripe Elements
125
97
const PaymentPage : React . FC < { clientSecret : string } > = ( { clientSecret } ) => {
126
- // if (!clientSecret) {
127
- // return <div>Loading...</div>
128
- // }
129
-
130
98
const options = {
131
99
clientSecret,
132
100
appearance : {
133
- theme : 'stripe' ,
101
+ theme : 'stripe' as const ,
134
102
} ,
135
103
}
136
104
@@ -145,20 +113,48 @@ interface EditablePaymentMethodProps {
145
113
clientSecret : string
146
114
}
147
115
148
- const EditPaymentMethod : React . FC < EditablePaymentMethodProps > = ( {
149
- clientSecret,
150
- } ) => {
116
+ const EditPaymentMethod : React . FC < EditablePaymentMethodProps > = ( ) => {
117
+ const clientSecret = MANUALLY_FETCHED_CLIENT_SECRET // TODO - fetch from API
118
+
119
+ const [ activeTab , setActiveTab ] = useState < 'primary' | 'secondary' > ( 'primary' )
120
+
151
121
return (
152
122
< div className = "flex flex-col gap-4 p-4" >
153
123
< h3 className = "font-semibold" > Edit payment method</ h3 >
154
- < PaymentPage clientSecret = { clientSecret } />
155
- < AddressForm
156
- closeForm = { function ( ) : void {
157
- throw new Error ( 'TODO' )
158
- } }
159
- provider = { '' }
160
- owner = { '' }
161
- />
124
+ < div >
125
+ { /* Tabs for Primary and Secondary Payment Methods */ }
126
+ < div className = "ml-2 flex border-b border-ds-gray-tertiary" >
127
+ { [ 'primary' , 'secondary' ] . map ( ( tab ) => (
128
+ < button
129
+ key = { tab }
130
+ className = { `py-2 ${ tab === 'primary' ? 'mr-4' : '' } ${
131
+ activeTab === tab
132
+ ? 'border-b-2 border-ds-gray-octonary font-semibold text-ds-gray-octonary'
133
+ : 'text-ds-gray-quinary hover:border-b-2 hover:border-ds-gray-quinary'
134
+ } `}
135
+ onClick = { ( ) => setActiveTab ( tab as 'primary' | 'secondary' ) }
136
+ >
137
+ { tab === 'primary' ? 'Primary' : 'Secondary' } Payment Method
138
+ </ button >
139
+ ) ) }
140
+ </ div >
141
+
142
+ { /* Payment Details for the selected tab */ }
143
+ < div className = "m-4" >
144
+ { activeTab === 'primary' && (
145
+ < div >
146
+ < PaymentPage clientSecret = { clientSecret } />
147
+ < AddressForm closeForm = { ( ) => { } } provider = { '' } owner = { '' } />
148
+ </ div >
149
+ ) }
150
+ { activeTab === 'secondary' && (
151
+ < div >
152
+ < PaymentPage clientSecret = { clientSecret } />
153
+ < AddressForm closeForm = { ( ) => { } } provider = { '' } owner = { '' } />
154
+ </ div >
155
+ ) }
156
+ </ div >
157
+ </ div >
162
158
</ div >
163
159
)
164
160
}
0 commit comments