@@ -6,7 +6,6 @@ import Icon from "react-eva-icons";
6
6
7
7
import { ExecutionResult } from "@apollo/react-common" ;
8
8
import {
9
- CardElement ,
10
9
Elements ,
11
10
injectStripe ,
12
11
ReactStripeElements
@@ -18,8 +17,10 @@ import {
18
17
MembershipTypes ,
19
18
useGetMembershipMutation
20
19
} from "../generated/graphql" ;
20
+ import { PaymentInformationForm } from "./PaymentInformation" ;
21
+ import { ReviewInformationForm } from "./ReviewInformation" ;
21
22
import { IconContainer } from "./IconContainer" ;
22
- import { PrimaryButton } from "./PrimaryButton " ;
23
+ import { ModalWrapper } from "./ModalWrapper " ;
23
24
24
25
export const GET_MEMBERSHIP : any = gql `
25
26
mutation GetMembership($membershipType: MembershipTypes!) {
@@ -31,176 +32,102 @@ export const GET_MEMBERSHIP: any = gql`
31
32
}
32
33
` ;
33
34
34
- const createOptions = ( fontSize : string , padding ?: string ) => {
35
- return {
36
- style : {
37
- base : {
38
- fontSize,
39
- borderRadius : "20px" ,
40
- width : "100%" ,
41
- color : "#424770" ,
42
- letterSpacing : "0.025em" ,
43
- fontFamily : "Source Code Pro, monospace" ,
44
- "::placeholder" : {
45
- color : "#aab7c4"
46
- } ,
47
- padding
48
- } ,
49
- invalid : {
50
- color : "#9e2146"
51
- }
52
- }
53
- } ;
54
- } ;
55
-
56
- const FormContainer : AnyStyledComponent = styled . div `
57
- display: flex;
58
- flex-direction: column;
59
- align-content: center;
60
- justify-content: center;
61
- align-items: center;
62
-
63
- margin: 3rem 1rem 0 1rem;
64
- ` ;
65
-
66
- const ElementContainer : AnyStyledComponent = styled . div `
67
- width: 100%;
68
- input,
69
- .StripeElement {
70
- display: block;
71
- margin: 10px 0 20px 0;
72
- max-width: 500px;
73
- padding: 8px 12px;
74
- font-size: 1em;
75
- font-family: "Source Code Pro", monospace;
76
- box-shadow: rgba(50, 50, 93, 0.14902) 0px 1px 3px,
77
- rgba(0, 0, 0, 0.0196078) 0px 1px 0px;
78
- border: 0;
79
- outline: 0;
80
- border-radius: 0.5rem;
81
- background: white;
82
- }
83
- ` ;
84
-
85
35
const ErrorContainer : AnyStyledComponent = styled . div `
86
36
display: flex;
87
37
align-items: center;
88
38
align-content: center;
39
+ margin-bottom: .5rem;
89
40
90
41
color: #f56565;
91
42
` ;
92
43
93
44
interface ICheckoutFormProps {
94
- tag : MembershipTypes ;
95
45
onSuccess ?: ( ) => void ;
46
+ removeTag : ( ) => void ;
47
+ tag : MembershipTypes ;
96
48
}
97
49
98
- type CheckoutProps = ReactStripeElements . InjectedStripeProps &
50
+ type CheckoutFormProps = ReactStripeElements . InjectedStripeProps &
99
51
ICheckoutFormProps ;
100
52
101
53
type setString = React . Dispatch < React . SetStateAction < string > > ;
102
- type setBoolean = React . Dispatch < React . SetStateAction < boolean > > ;
54
+ type setNumber = React . Dispatch < React . SetStateAction < number > > ;
55
+ type setPaymentMethod = React . Dispatch < React . SetStateAction < stripe . paymentMethod . PaymentMethod | undefined > > ;
56
+ type voidFunction = ( ) => void ;
57
+ type asyncVoidFunction = ( ) => Promise < void > ;
103
58
104
- const CheckoutFormBase : React . FC < CheckoutProps > = (
105
- props : CheckoutProps
59
+ const CheckoutFormBase : React . FC < CheckoutFormProps > = (
60
+ props : CheckoutFormProps
106
61
) : JSX . Element => {
107
- const [ cardElement , setCardElement ] = useState < any > ( undefined ) ;
108
- const [ intent , setIntent ] : [ string , setString ] = useState < string > ( "" ) ;
109
- const [ clientSecret , setClientSecret ] : [ string , setString ] = useState < string > (
110
- ""
111
- ) ;
62
+ // const [intent, setIntent]: [string, setString] = useState<string>("");
63
+ const [ paymentMethod , setPaymentMethod ] : [ stripe . paymentMethod . PaymentMethod | undefined , setPaymentMethod ] = useState < stripe . paymentMethod . PaymentMethod | undefined > ( undefined ) ;
64
+ const [ clientSecret , setClientSecret ] : [ string , setString ] = useState < string > ( "" ) ;
112
65
const [ error , setError ] : [ string , setString ] = useState < string > ( "" ) ;
113
- const [ success , setSuccess ] : [ boolean , setBoolean ] = useState < boolean > ( false ) ;
114
- const [ loading , setLoading ] : [ boolean , setBoolean ] = useState < boolean > ( false ) ;
66
+ const [ index , setIndex ] : [ number , setNumber ] = useState < number > ( 0 ) ;
115
67
116
68
const [ getMembership ] = useGetMembershipMutation ( ) ;
117
69
118
70
const handleError : ( message : string ) => void = ( message : string ) : void => {
119
- setLoading ( false ) ;
71
+ setPaymentMethod ( undefined ) ;
120
72
setError ( message ) ;
73
+ setIndex ( 0 ) ;
121
74
} ;
122
75
123
- const handleSubmit : ( ev : React . FormEvent ) => void = async (
124
- ev : React . FormEvent
125
- ) : Promise < void > => {
126
- // We don't want to let default form submission happen here, which would refresh the page.
127
- ev . preventDefault ( ) ;
128
- setLoading ( true ) ;
129
- if ( ! props . stripe ) {
130
- handleError ( "Stripe.js hasn't loaded yet." ) ;
131
- return ;
132
- }
133
- let secret : string = clientSecret ;
134
-
135
- if ( ! secret ) {
136
- let result : ExecutionResult < GetMembershipMutation > ;
137
- try {
138
- result = await getMembership ( {
139
- variables : { membershipType : props . tag }
140
- } ) ;
141
- } catch ( e ) {
142
- handleError ( e . message ) ;
143
- return ;
144
- }
145
-
146
- const data = result . data ;
147
-
148
- if ( ! data ) {
149
- if ( result . errors ) {
150
- handleError ( result . errors [ 0 ] . message || "Unknown Error occurred." ) ;
151
- }
152
-
153
- return ;
154
- }
155
- secret = data . startMembershipTransaction . clientSecret ;
156
- setClientSecret ( secret ) ;
157
- }
76
+ const resetForm : asyncVoidFunction = async ( ) : Promise < void > => {
77
+ props . removeTag ( ) ;
78
+ setPaymentMethod ( undefined ) ;
79
+ setClientSecret ( "" ) ;
80
+ setTimeout ( ( ) => {
81
+ setIndex ( 0 ) ;
82
+ setError ( "" ) ;
83
+ } , 400 ) ;
84
+ }
158
85
159
- const response : stripe . PaymentIntentResponse = await props . stripe . handleCardPayment (
160
- secret ,
161
- cardElement
162
- ) ;
86
+ const nextModal : voidFunction = ( ) : void => {
87
+ setIndex ( index + 1 ) ;
88
+ }
163
89
164
- if ( response . error ) {
165
- handleError ( response . error . message || "Unknown error occurred" ) ;
90
+ const prevModal : voidFunction = ( ) : void => {
91
+ setIndex ( index - 1 ) ;
92
+ }
166
93
167
- return ;
94
+ const getClientSecret : ( ) => Promise < string > = async ( ) : Promise < string > => {
95
+ let result : ExecutionResult < GetMembershipMutation > ;
96
+ try {
97
+ result = await getMembership ( {
98
+ variables : { membershipType : props . tag }
99
+ } ) ;
100
+ } catch ( e ) {
101
+ handleError ( e . message ) ;
102
+ return "" ;
168
103
}
104
+ const data = result . data ;
169
105
170
- if ( ! response . paymentIntent ) {
171
- handleError ( "Unknown error occurred" ) ;
106
+ if ( ! data ) {
107
+ if ( result . errors )
108
+ handleError ( result . errors [ 0 ] . message || "Unknown Error occurred." ) ;
172
109
173
- return ;
110
+ return "" ;
174
111
}
175
-
176
- setIntent ( response . paymentIntent . id ) ;
177
- setLoading ( false ) ;
178
- setSuccess ( true ) ;
112
+ const clientSecret = data . startMembershipTransaction . clientSecret ;
113
+ setClientSecret ( clientSecret ) ;
114
+ return clientSecret ;
179
115
} ;
180
116
181
- if ( success ) {
182
- if ( props . onSuccess ) {
183
- props . onSuccess ( ) ;
184
- }
185
-
186
- return (
187
- < Result
188
- status = "success"
189
- title = "Membership Added!"
190
- subTitle = { `Your membership may take 1-5 minutes to show. ref: ${ intent } ` }
191
- />
192
- ) ;
193
- }
194
-
195
- return (
196
- < form onSubmit = { handleSubmit } >
197
- < FormContainer >
198
- < label style = { { width : "100%" , fontSize : "16px" } } >
199
- Card details
200
- < ElementContainer >
201
- < CardElement { ...createOptions ( "18px" ) } onReady = { setCardElement } />
202
- </ ElementContainer >
203
- </ label >
117
+ const slides = [
118
+ < ModalWrapper
119
+ resetForm = { resetForm }
120
+ tag = { props . tag }
121
+ >
122
+ < PaymentInformationForm
123
+ stripe = { props . stripe }
124
+ setPaymentMethod = { setPaymentMethod }
125
+ getClientSecret = { getClientSecret }
126
+ handleError = { handleError }
127
+ resetForm = { resetForm }
128
+ nextModal = { nextModal }
129
+ clientSecret = { clientSecret }
130
+ >
204
131
{ error !== "" && (
205
132
< ErrorContainer >
206
133
< IconContainer >
@@ -213,19 +140,41 @@ const CheckoutFormBase: React.FC<CheckoutProps> = (
213
140
< span style = { { marginLeft : ".5rem" } } > { error } </ span >
214
141
</ ErrorContainer >
215
142
) }
216
- < PrimaryButton
217
- loading = { loading }
218
- disabled = { loading }
219
- style = { { margin : "2rem auto" } }
220
- >
221
- Purchase
222
- </ PrimaryButton >
223
- </ FormContainer >
224
- </ form >
143
+ </ PaymentInformationForm >
144
+ </ ModalWrapper > ,
145
+ < ModalWrapper
146
+ resetForm = { resetForm }
147
+ tag = { props . tag }
148
+ >
149
+ < ReviewInformationForm
150
+ stripe = { props . stripe }
151
+ handleError = { handleError }
152
+ // setIntent={setIntent}
153
+ nextModal = { nextModal }
154
+ prevModal = { prevModal }
155
+ paymentMethod = { paymentMethod ! }
156
+ clientSecret = { clientSecret }
157
+ tag = { props . tag }
158
+ />
159
+ </ ModalWrapper > ,
160
+ < ModalWrapper
161
+ resetForm = { resetForm }
162
+ tag = { props . tag }
163
+ >
164
+ < Result
165
+ status = "success"
166
+ title = "Membership Added!"
167
+ subTitle = { `Your membership may take 1-5 minutes to show.` }
168
+ />
169
+ </ ModalWrapper >
170
+ ]
171
+
172
+ return (
173
+ slides [ index ]
225
174
) ;
226
175
} ;
227
176
228
- const InjectedCheckoutForm : React . ComponentType < CheckoutProps > = injectStripe (
177
+ const InjectedCheckoutForm : React . ComponentType < ICheckoutFormProps > = injectStripe (
229
178
CheckoutFormBase
230
179
) ;
231
180
0 commit comments