Skip to content

Commit e2cc4f6

Browse files
committed
Feat: State selector US
1 parent 380d743 commit e2cc4f6

File tree

4 files changed

+367
-14
lines changed

4 files changed

+367
-14
lines changed

src/lib/components/billing/paymentModal.svelte

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
import { FakeModal } from '$lib/components';
33
import { InputText, Button } from '$lib/elements/forms';
44
import { createEventDispatcher, onMount } from 'svelte';
5-
import { initializeStripe, submitStripeCard } from '$lib/stores/stripe';
5+
import { initializeStripe, setPaymentMethod, submitStripeCard } from '$lib/stores/stripe';
66
import { invalidate } from '$app/navigation';
77
import { Dependencies } from '$lib/constants';
88
import { addNotification } from '$lib/stores/notifications';
99
import { page } from '$app/state';
1010
import { Spinner } from '@appwrite.io/pink-svelte';
11+
import type { PaymentMethod } from '@stripe/stripe-js';
12+
import StatePicker from './statePicker.svelte';
1113
1214
export let show = false;
1315
@@ -16,10 +18,36 @@
1618
let name: string;
1719
let error: string;
1820
let modal: FakeModal;
21+
let showState: boolean = false;
22+
let state: string = '';
23+
let paymentMethod: PaymentMethod | null = null;
1924
2025
async function handleSubmit() {
2126
try {
27+
if (showState && !state) {
28+
throw Error('Please select a state');
29+
}
30+
31+
if (showState) {
32+
const card = await setPaymentMethod(paymentMethod.id, name, state);
33+
modal.closeModal();
34+
await invalidate(Dependencies.PAYMENT_METHODS);
35+
dispatch('submit', card);
36+
addNotification({
37+
type: 'success',
38+
message: 'A new payment method has been added to your account'
39+
});
40+
return;
41+
}
42+
2243
const card = await submitStripeCard(name, page?.params?.organization ?? null);
44+
if (card && typeof card !== 'string') {
45+
if ((card as PaymentMethod).card.country === 'US') {
46+
paymentMethod = card as PaymentMethod;
47+
showState = true;
48+
return;
49+
}
50+
}
2351
modal.closeModal();
2452
await invalidate(Dependencies.PAYMENT_METHODS);
2553
dispatch('submit', card);
@@ -87,13 +115,19 @@
87115
<Spinner />
88116
</div>
89117
{/if}
90-
91-
<div
92-
style:display={isLoading ? 'none' : 'initial'}
93-
class="stripe-element"
94-
bind:this={element}>
95-
<!-- Stripe will create form elements here -->
96-
</div>
118+
{#if showState}
119+
<div class="state-element">
120+
<!-- input select for state picker -->
121+
<StatePicker card={paymentMethod} bind:state />
122+
</div>
123+
{:else}
124+
<div
125+
style:display={isLoading ? 'none' : 'initial'}
126+
class="stripe-element"
127+
bind:this={element}>
128+
<!-- Stripe will create form elements here -->
129+
</div>
130+
{/if}
97131
</div>
98132
<slot name="end"></slot>
99133
<svelte:fragment slot="footer">
@@ -107,6 +141,14 @@
107141
display: flex;
108142
min-height: 245px;
109143
144+
.state-element {
145+
width: 100%;
146+
display: flex;
147+
flex-direction: column;
148+
align-items: center;
149+
justify-content: center;
150+
}
151+
110152
.stripe-element {
111153
width: 100%;
112154
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<script lang="ts">
2+
import { states } from './states.js';
3+
import { InputSelect } from '$lib/elements/forms';
4+
import type { PaymentMethod } from '@stripe/stripe-js';
5+
import Card from '../card.svelte';
6+
import { Alert, Layout, Typography } from '@appwrite.io/pink-svelte';
7+
import { CreditCardBrandImage } from '../index.js';
8+
9+
export let state: string = '';
10+
export let card: PaymentMethod | null = null;
11+
</script>
12+
13+
{#if card}
14+
<Card>
15+
<Layout.Stack direction="row" alignItems="center" gap="s">
16+
<CreditCardBrandImage brand={card.card?.brand} />
17+
<span>ending in {card.card?.last4}</span>
18+
</Layout.Stack>
19+
<Typography.Text size="s">
20+
{card.card.country}
21+
{card.billing_details.address.postal_code}
22+
</Typography.Text>
23+
</Card>
24+
{/if}
25+
26+
<Alert.Inline status="info" title="State is required for US payment methods">
27+
<Typography.Text size="s">
28+
To complete the billing information, select your state so we can apply the correct taxes and
29+
meet U.S. legal requirements.
30+
</Typography.Text>
31+
</Alert.Inline>
32+
33+
<InputSelect
34+
bind:value={state}
35+
label="State"
36+
placeholder="Select a state"
37+
id="state-picker"
38+
options={states.map((state) => ({
39+
label: state.name,
40+
value: state.abbreviation,
41+
id: state.abbreviation.toLowerCase()
42+
}))} />

src/lib/components/billing/states.js

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
export const states = [
2+
{
3+
"name": "Alabama",
4+
"abbreviation": "AL"
5+
},
6+
{
7+
"name": "Alaska",
8+
"abbreviation": "AK"
9+
},
10+
{
11+
"name": "American Samoa",
12+
"abbreviation": "AS"
13+
},
14+
{
15+
"name": "Arizona",
16+
"abbreviation": "AZ"
17+
},
18+
{
19+
"name": "Arkansas",
20+
"abbreviation": "AR"
21+
},
22+
{
23+
"name": "California",
24+
"abbreviation": "CA"
25+
},
26+
{
27+
"name": "Colorado",
28+
"abbreviation": "CO"
29+
},
30+
{
31+
"name": "Connecticut",
32+
"abbreviation": "CT"
33+
},
34+
{
35+
"name": "Delaware",
36+
"abbreviation": "DE"
37+
},
38+
{
39+
"name": "District Of Columbia",
40+
"abbreviation": "DC"
41+
},
42+
{
43+
"name": "Federated States Of Micronesia",
44+
"abbreviation": "FM"
45+
},
46+
{
47+
"name": "Florida",
48+
"abbreviation": "FL"
49+
},
50+
{
51+
"name": "Georgia",
52+
"abbreviation": "GA"
53+
},
54+
{
55+
"name": "Guam",
56+
"abbreviation": "GU"
57+
},
58+
{
59+
"name": "Hawaii",
60+
"abbreviation": "HI"
61+
},
62+
{
63+
"name": "Idaho",
64+
"abbreviation": "ID"
65+
},
66+
{
67+
"name": "Illinois",
68+
"abbreviation": "IL"
69+
},
70+
{
71+
"name": "Indiana",
72+
"abbreviation": "IN"
73+
},
74+
{
75+
"name": "Iowa",
76+
"abbreviation": "IA"
77+
},
78+
{
79+
"name": "Kansas",
80+
"abbreviation": "KS"
81+
},
82+
{
83+
"name": "Kentucky",
84+
"abbreviation": "KY"
85+
},
86+
{
87+
"name": "Louisiana",
88+
"abbreviation": "LA"
89+
},
90+
{
91+
"name": "Maine",
92+
"abbreviation": "ME"
93+
},
94+
{
95+
"name": "Marshall Islands",
96+
"abbreviation": "MH"
97+
},
98+
{
99+
"name": "Maryland",
100+
"abbreviation": "MD"
101+
},
102+
{
103+
"name": "Massachusetts",
104+
"abbreviation": "MA"
105+
},
106+
{
107+
"name": "Michigan",
108+
"abbreviation": "MI"
109+
},
110+
{
111+
"name": "Minnesota",
112+
"abbreviation": "MN"
113+
},
114+
{
115+
"name": "Mississippi",
116+
"abbreviation": "MS"
117+
},
118+
{
119+
"name": "Missouri",
120+
"abbreviation": "MO"
121+
},
122+
{
123+
"name": "Montana",
124+
"abbreviation": "MT"
125+
},
126+
{
127+
"name": "Nebraska",
128+
"abbreviation": "NE"
129+
},
130+
{
131+
"name": "Nevada",
132+
"abbreviation": "NV"
133+
},
134+
{
135+
"name": "New Hampshire",
136+
"abbreviation": "NH"
137+
},
138+
{
139+
"name": "New Jersey",
140+
"abbreviation": "NJ"
141+
},
142+
{
143+
"name": "New Mexico",
144+
"abbreviation": "NM"
145+
},
146+
{
147+
"name": "New York",
148+
"abbreviation": "NY"
149+
},
150+
{
151+
"name": "North Carolina",
152+
"abbreviation": "NC"
153+
},
154+
{
155+
"name": "North Dakota",
156+
"abbreviation": "ND"
157+
},
158+
{
159+
"name": "Northern Mariana Islands",
160+
"abbreviation": "MP"
161+
},
162+
{
163+
"name": "Ohio",
164+
"abbreviation": "OH"
165+
},
166+
{
167+
"name": "Oklahoma",
168+
"abbreviation": "OK"
169+
},
170+
{
171+
"name": "Oregon",
172+
"abbreviation": "OR"
173+
},
174+
{
175+
"name": "Palau",
176+
"abbreviation": "PW"
177+
},
178+
{
179+
"name": "Pennsylvania",
180+
"abbreviation": "PA"
181+
},
182+
{
183+
"name": "Puerto Rico",
184+
"abbreviation": "PR"
185+
},
186+
{
187+
"name": "Rhode Island",
188+
"abbreviation": "RI"
189+
},
190+
{
191+
"name": "South Carolina",
192+
"abbreviation": "SC"
193+
},
194+
{
195+
"name": "South Dakota",
196+
"abbreviation": "SD"
197+
},
198+
{
199+
"name": "Tennessee",
200+
"abbreviation": "TN"
201+
},
202+
{
203+
"name": "Texas",
204+
"abbreviation": "TX"
205+
},
206+
{
207+
"name": "Utah",
208+
"abbreviation": "UT"
209+
},
210+
{
211+
"name": "Vermont",
212+
"abbreviation": "VT"
213+
},
214+
{
215+
"name": "Virgin Islands",
216+
"abbreviation": "VI"
217+
},
218+
{
219+
"name": "Virginia",
220+
"abbreviation": "VA"
221+
},
222+
{
223+
"name": "Washington",
224+
"abbreviation": "WA"
225+
},
226+
{
227+
"name": "West Virginia",
228+
"abbreviation": "WV"
229+
},
230+
{
231+
"name": "Wisconsin",
232+
"abbreviation": "WI"
233+
},
234+
{
235+
"name": "Wyoming",
236+
"abbreviation": "WY"
237+
}
238+
];

0 commit comments

Comments
 (0)