add shipping address state management and country list

Signed-off-by: Loan Laux <loan@outgrow.io>
This commit is contained in:
Loan Laux 2021-08-04 16:10:30 +02:00
parent 0ab3a973a1
commit 45c5b52967
No known key found for this signature in database
GPG Key ID: AF9E9BD6548AD52E
7 changed files with 1191 additions and 32 deletions

View File

@ -11,6 +11,7 @@ import { Button, Text } from '@components/ui'
import { useUI } from '@components/ui/context'
import s from './PaymentMethodView.module.css'
import SidebarLayout from '@components/common/SidebarLayout'
import countries from '@lib/countries'
const PaymentMethodView: FC = () => {
const { paymentMethodDetails, setPaymentMethodDetails, setSidebarView } = useUI()
@ -150,7 +151,14 @@ const PaymentMethodView: FC = () => {
onChange={updateAddressData}
value={address.countryOrRegion}
>
<option>Hong Kong</option>
{countries.map((country) => (
<option
key={country.code}
value={country.code}
>
{country.name}
</option>
))}
</select>
</div>
</div>

View File

@ -1,6 +1,6 @@
import { FC } from 'react'
import s from './PaymentWidget.module.css'
import { ChevronRight, CreditCard, Trash } from '@components/icons'
import { ChevronRight, CreditCard, Pencil } from '@components/icons'
import { useUI } from '@components/ui/context'
interface ComponentProps {
@ -32,7 +32,7 @@ const PaymentWidget: FC<ComponentProps> = ({ onClick }) => {
</div>
<div>
{paymentMethodDetails?.paymentMethod ?
<Trash />
<Pencil />
:
<ChevronRight />
}

View File

@ -1,12 +1,35 @@
import { FC } from 'react'
import { FC, useState } from 'react'
import cn from 'classnames'
import s from './ShippingView.module.css'
import Button from '@components/ui/Button'
import { useUI } from '@components/ui/context'
import SidebarLayout from '@components/common/SidebarLayout'
import countries from '@lib/countries'
const PaymentMethodView: FC = () => {
const { setSidebarView } = useUI()
const { paymentMethodDetails, setShippingAddress, setSidebarView, setUseBillingAddressForShipping, shippingAddress, useBillingAddressForShipping } = useUI()
const handleUseBillingAddressForShipping = (event) => {
setUseBillingAddressForShipping(event.target.value === 'true')
if (event.target.value === 'true') {
setShippingAddress({
firstName: paymentMethodDetails.address?.firstName,
lastName: paymentMethodDetails.address?.lastName,
company: paymentMethodDetails.address?.company,
addressLine1: paymentMethodDetails.address?.addressLine1,
addressLine2: paymentMethodDetails.address?.addressLine2,
postalCode: paymentMethodDetails.address?.postalCode,
city: paymentMethodDetails.address?.city,
countryOrRegion: paymentMethodDetails.address?.countryOrRegion,
})
}
}
const updateAddressData = ({ target }: any) => setShippingAddress({
...shippingAddress,
[target.name]: target.value,
})
return (
<SidebarLayout handleBack={() => setSidebarView('CHECKOUT_VIEW')}>
@ -16,52 +39,124 @@ const PaymentMethodView: FC = () => {
</h2>
<div>
<div className="flex flex-row my-3 items-center">
<input className={s.radio} type="radio" />
<span className="ml-3 text-sm">Same as billing address</span>
<input
className={s.radio}
type="radio"
id="useBillingAddressForShippingTrue"
name="useBillingAddressForShipping"
value="true"
onChange={handleUseBillingAddressForShipping}
checked={useBillingAddressForShipping === true}
/>
<label htmlFor="useBillingAddressForShippingTrue" className="ml-3 text-sm">Same as billing address</label>
</div>
<div className="flex flex-row my-3 items-center">
<input className={s.radio} type="radio" />
<span className="ml-3 text-sm">
<input
className={s.radio}
type="radio"
id="useBillingAddressForShippingFalse"
name="useBillingAddressForShipping"
value="false"
onChange={handleUseBillingAddressForShipping}
checked={useBillingAddressForShipping === false}
/>
<label htmlFor="useBillingAddressForShippingFalse" className="ml-3 text-sm">
Use a different shipping address
</span>
</label>
</div>
<hr className="border-accent-2 my-6" />
<div className="grid gap-3 grid-flow-row grid-cols-12">
<div className={cn(s.fieldset, 'col-span-6')}>
<label className={s.label}>First Name</label>
<input className={s.input} />
<input
className={s.input}
name='firstName'
onChange={updateAddressData}
value={shippingAddress.firstName}
disabled={useBillingAddressForShipping}
/>
</div>
<div className={cn(s.fieldset, 'col-span-6')}>
<label className={s.label}>Last Name</label>
<input className={s.input} />
<input
className={s.input}
name='lastName'
onChange={updateAddressData}
value={shippingAddress.lastName}
disabled={useBillingAddressForShipping}
/>
</div>
</div>
<div className={s.fieldset}>
<label className={s.label}>Company (Optional)</label>
<input className={s.input} />
<input
className={s.input}
name='company'
onChange={updateAddressData}
value={shippingAddress.company}
disabled={useBillingAddressForShipping}
/>
</div>
<div className={s.fieldset}>
<label className={s.label}>Street and House Number</label>
<input className={s.input} />
<input
className={s.input}
name='addressLine1'
onChange={updateAddressData}
value={shippingAddress.addressLine1}
disabled={useBillingAddressForShipping}
/>
</div>
<div className={s.fieldset}>
<label className={s.label}>Apartment, Suite, Etc. (Optional)</label>
<input className={s.input} />
<input
className={s.input}
name='addressLine2'
onChange={updateAddressData}
value={shippingAddress.addressLine2}
disabled={useBillingAddressForShipping}
/>
</div>
<div className="grid gap-3 grid-flow-row grid-cols-12">
<div className={cn(s.fieldset, 'col-span-6')}>
<label className={s.label}>Postal Code</label>
<input className={s.input} />
<input
className={s.input}
name='postalCode'
onChange={updateAddressData}
value={shippingAddress.postalCode}
disabled={useBillingAddressForShipping}
/>
</div>
<div className={cn(s.fieldset, 'col-span-6')}>
<label className={s.label}>City</label>
<input className={s.input} />
<input
className={s.input}
name='city'
onChange={updateAddressData}
value={shippingAddress.city}
disabled={useBillingAddressForShipping}
/>
</div>
</div>
<div className={s.fieldset}>
<label className={s.label}>Country/Region</label>
<select className={s.select}>
<option>Hong Kong</option>
<select
className={s.select}
name="countryOrRegion"
onChange={updateAddressData}
value={shippingAddress.countryOrRegion}
disabled={useBillingAddressForShipping}
>
{countries.map((country) => (
<option
key={country.code}
value={country.code}
>
{country.name}
</option>
))}
</select>
</div>
</div>

View File

@ -1,27 +1,36 @@
import { FC } from 'react'
import s from './ShippingWidget.module.css'
import { ChevronRight, MapPin } from '@components/icons'
import cn from 'classnames'
import { useUI } from '@components/ui/context'
interface ComponentProps {
onClick?: () => any
}
const ShippingWidget: FC<ComponentProps> = ({ onClick }) => {
/* Shipping Address
Only available with checkout set to true -
const { shippingAddress } = useUI()
const isAddressKnown = shippingAddress.addressLine1 !== '' && shippingAddress.city !== '' && shippingAddress.countryOrRegion !== ''
/* Shipping Address
Only available with checkout set to true -
This means that the provider does offer checkout functionality. */
return (
<div onClick={onClick} className={s.root}>
<div className="flex flex-1 items-center">
<MapPin className="w-5 flex" />
<span className="ml-5 text-sm text-center font-medium">
Add Shipping Address
</span>
{/* <span>
1046 Kearny Street.<br/>
San Franssisco, California
</span> */}
<div className="ml-5 text-sm text-left font-medium">
{isAddressKnown ?
<span>
{shippingAddress.addressLine1}<br/>
{shippingAddress.city}, {shippingAddress.countryOrRegion}
</span>
:
<span>
Add Shipping Address
</span>
}
</div>
</div>
<div>
<ChevronRight />

View File

@ -84,8 +84,9 @@ const SidebarView: FC<{ sidebarView: string; closeSidebar(): any }> = ({
}
const SidebarUI: FC = () => {
const { displaySidebar, closeSidebar, sidebarView, paymentMethodDetails } = useUI()
const { displaySidebar, closeSidebar, shippingAddress, sidebarView, paymentMethodDetails } = useUI()
console.log("paymentMethodDetails", paymentMethodDetails)
console.log("shippingAddress", shippingAddress)
return displaySidebar ? (
<SidebarView sidebarView={sidebarView} closeSidebar={closeSidebar} />
) : null

View File

@ -32,6 +32,17 @@ export const initialState = {
},
paymentMethod: null,
},
shippingAddress: {
firstName: '',
lastName: '',
company: '',
addressLine1: '',
addressLine2: '',
postalCode: '',
city: '',
countryOrRegion: '',
},
useBillingAddressForShipping: true,
}
type Action =
@ -69,6 +80,14 @@ type Action =
type: 'SET_PAYMENT_METHOD_DETAILS',
paymentMethodDetails: PAYMENT_METHOD_DETAILS
}
| {
type: 'SET_SHIPPING_ADDRESS',
shippingAddress: SHIPPING_ADDRESS
}
| {
type: 'SET_USE_BILLING_ADDRESS_FOR_SHIPPING',
value: boolean
}
type MODAL_VIEWS =
| 'SIGNUP_VIEW'
@ -84,6 +103,17 @@ type PAYMENT_METHOD_DETAILS = {
paymentMethod: object,
}
type SHIPPING_ADDRESS = {
firstName: string,
lastName: string,
company: string,
addressLine1: string,
addressLine2: string,
postalCode: string,
city: string,
countryOrRegion: string,
}
export const UIContext = React.createContext<State | any>(initialState)
UIContext.displayName = 'UIContext'
@ -148,7 +178,19 @@ function uiReducer(state: State, action: Action) {
case 'SET_PAYMENT_METHOD_DETAILS': {
return {
...state,
paymentMethodDetails: action.paymentMethodDetails
paymentMethodDetails: action.paymentMethodDetails,
}
}
case 'SET_SHIPPING_ADDRESS': {
return {
...state,
shippingAddress: action.shippingAddress,
}
}
case 'SET_USE_BILLING_ADDRESS_FOR_SHIPPING': {
return {
...state,
useBillingAddressForShipping: action.useBillingAddressForShipping
}
}
}
@ -211,7 +253,32 @@ export const UIProvider: FC = (props) => {
)
const setPaymentMethodDetails = useCallback(
(paymentMethodDetails: PAYMENT_METHOD_DETAILS) => dispatch({ type: 'SET_PAYMENT_METHOD_DETAILS', paymentMethodDetails }),
(paymentMethodDetails: PAYMENT_METHOD_DETAILS) => {
dispatch({ type: 'SET_PAYMENT_METHOD_DETAILS', paymentMethodDetails })
if (state.useBillingAddressForShipping) {
setShippingAddress({
firstName: paymentMethodDetails.address?.firstName,
lastName: paymentMethodDetails.address?.lastName,
company: paymentMethodDetails.address?.company,
addressLine1: paymentMethodDetails.address?.addressLine1,
addressLine2: paymentMethodDetails.address?.addressLine2,
postalCode: paymentMethodDetails.address?.postalCode,
city: paymentMethodDetails.address?.city,
countryOrRegion: paymentMethodDetails.address?.countryOrRegion,
})
}
},
[dispatch]
)
const setShippingAddress = useCallback(
(shippingAddress: SHIPPING_ADDRESS) => dispatch({ type: 'SET_SHIPPING_ADDRESS', shippingAddress }),
[dispatch]
)
const setUseBillingAddressForShipping = useCallback(
(useBillingAddressForShipping: boolean) => dispatch({ type: 'SET_USE_BILLING_ADDRESS_FOR_SHIPPING', useBillingAddressForShipping }),
[dispatch]
)
@ -228,7 +295,9 @@ export const UIProvider: FC = (props) => {
closeModal,
setModalView,
setPaymentMethodDetails,
setShippingAddress,
setSidebarView,
setUseBillingAddressForShipping,
setUserAvatar,
}),
[state]

977
lib/countries.ts Normal file
View File

@ -0,0 +1,977 @@
// Source: https://gist.github.com/keeguon/2310008#gistcomment-1174237
// Thanks to @keeguon and @abrkn for this list
export default [
{
'name': 'Afghanistan',
'code': 'AF',
},
{
'name': 'Åland Islands',
'code': 'AX',
},
{
'name': 'Albania',
'code': 'AL',
},
{
'name': 'Algeria',
'code': 'DZ',
},
{
'name': 'American Samoa',
'code': 'AS',
},
{
'name': 'AndorrA',
'code': 'AD',
},
{
'name': 'Angola',
'code': 'AO',
},
{
'name': 'Anguilla',
'code': 'AI',
},
{
'name': 'Antarctica',
'code': 'AQ',
},
{
'name': 'Antigua and Barbuda',
'code': 'AG',
},
{
'name': 'Argentina',
'code': 'AR',
},
{
'name': 'Armenia',
'code': 'AM',
},
{
'name': 'Aruba',
'code': 'AW',
},
{
'name': 'Australia',
'code': 'AU',
},
{
'name': 'Austria',
'code': 'AT',
},
{
'name': 'Azerbaijan',
'code': 'AZ',
},
{
'name': 'Bahamas',
'code': 'BS',
},
{
'name': 'Bahrain',
'code': 'BH',
},
{
'name': 'Bangladesh',
'code': 'BD',
},
{
'name': 'Barbados',
'code': 'BB',
},
{
'name': 'Belarus',
'code': 'BY',
},
{
'name': 'Belgium',
'code': 'BE',
},
{
'name': 'Belize',
'code': 'BZ',
},
{
'name': 'Benin',
'code': 'BJ',
},
{
'name': 'Bermuda',
'code': 'BM',
},
{
'name': 'Bhutan',
'code': 'BT',
},
{
'name': 'Bolivia',
'code': 'BO',
},
{
'name': 'Bosnia and Herzegovina',
'code': 'BA',
},
{
'name': 'Botswana',
'code': 'BW',
},
{
'name': 'Bouvet Island',
'code': 'BV',
},
{
'name': 'Brazil',
'code': 'BR',
},
{
'name': 'British Indian Ocean Territory',
'code': 'IO',
},
{
'name': 'Brunei Darussalam',
'code': 'BN',
},
{
'name': 'Bulgaria',
'code': 'BG',
},
{
'name': 'Burkina Faso',
'code': 'BF',
},
{
'name': 'Burundi',
'code': 'BI',
},
{
'name': 'Cambodia',
'code': 'KH',
},
{
'name': 'Cameroon',
'code': 'CM',
},
{
'name': 'Canada',
'code': 'CA',
},
{
'name': 'Cape Verde',
'code': 'CV',
},
{
'name': 'Cayman Islands',
'code': 'KY',
},
{
'name': 'Central African Republic',
'code': 'CF',
},
{
'name': 'Chad',
'code': 'TD',
},
{
'name': 'Chile',
'code': 'CL',
},
{
'name': 'China',
'code': 'CN',
},
{
'name': 'Christmas Island',
'code': 'CX',
},
{
'name': 'Cocos (Keeling) Islands',
'code': 'CC',
},
{
'name': 'Colombia',
'code': 'CO',
},
{
'name': 'Comoros',
'code': 'KM',
},
{
'name': 'Congo',
'code': 'CG',
},
{
'name': 'Congo, The Democratic Republic of the',
'code': 'CD',
},
{
'name': 'Cook Islands',
'code': 'CK',
},
{
'name': 'Costa Rica',
'code': 'CR',
},
{
'name': 'Cote D\'Ivoire',
'code': 'CI',
},
{
'name': 'Croatia',
'code': 'HR',
},
{
'name': 'Cuba',
'code': 'CU',
},
{
'name': 'Cyprus',
'code': 'CY',
},
{
'name': 'Czech Republic',
'code': 'CZ',
},
{
'name': 'Denmark',
'code': 'DK',
},
{
'name': 'Djibouti',
'code': 'DJ',
},
{
'name': 'Dominica',
'code': 'DM',
},
{
'name': 'Dominican Republic',
'code': 'DO',
},
{
'name': 'Ecuador',
'code': 'EC',
},
{
'name': 'Egypt',
'code': 'EG',
},
{
'name': 'El Salvador',
'code': 'SV',
},
{
'name': 'Equatorial Guinea',
'code': 'GQ',
},
{
'name': 'Eritrea',
'code': 'ER',
},
{
'name': 'Estonia',
'code': 'EE',
},
{
'name': 'Ethiopia',
'code': 'ET',
},
{
'name': 'Falkland Islands (Malvinas)',
'code': 'FK',
},
{
'name': 'Faroe Islands',
'code': 'FO',
},
{
'name': 'Fiji',
'code': 'FJ',
},
{
'name': 'Finland',
'code': 'FI',
},
{
'name': 'France',
'code': 'FR',
},
{
'name': 'French Guiana',
'code': 'GF',
},
{
'name': 'French Polynesia',
'code': 'PF',
},
{
'name': 'French Southern Territories',
'code': 'TF',
},
{
'name': 'Gabon',
'code': 'GA',
},
{
'name': 'Gambia',
'code': 'GM',
},
{
'name': 'Georgia',
'code': 'GE',
},
{
'name': 'Germany',
'code': 'DE',
},
{
'name': 'Ghana',
'code': 'GH',
},
{
'name': 'Gibraltar',
'code': 'GI',
},
{
'name': 'Greece',
'code': 'GR',
},
{
'name': 'Greenland',
'code': 'GL',
},
{
'name': 'Grenada',
'code': 'GD',
},
{
'name': 'Guadeloupe',
'code': 'GP',
},
{
'name': 'Guam',
'code': 'GU',
},
{
'name': 'Guatemala',
'code': 'GT',
},
{
'name': 'Guernsey',
'code': 'GG',
},
{
'name': 'Guinea',
'code': 'GN',
},
{
'name': 'Guinea-Bissau',
'code': 'GW',
},
{
'name': 'Guyana',
'code': 'GY',
},
{
'name': 'Haiti',
'code': 'HT',
},
{
'name': 'Heard Island and Mcdonald Islands',
'code': 'HM',
},
{
'name': 'Holy See (Vatican City State)',
'code': 'VA',
},
{
'name': 'Honduras',
'code': 'HN',
},
{
'name': 'Hong Kong',
'code': 'HK',
},
{
'name': 'Hungary',
'code': 'HU',
},
{
'name': 'Iceland',
'code': 'IS',
},
{
'name': 'India',
'code': 'IN',
},
{
'name': 'Indonesia',
'code': 'ID',
},
{
'name': 'Iran, Islamic Republic Of',
'code': 'IR',
},
{
'name': 'Iraq',
'code': 'IQ',
},
{
'name': 'Ireland',
'code': 'IE',
},
{
'name': 'Isle of Man',
'code': 'IM',
},
{
'name': 'Israel',
'code': 'IL',
},
{
'name': 'Italy',
'code': 'IT',
},
{
'name': 'Jamaica',
'code': 'JM',
},
{
'name': 'Japan',
'code': 'JP',
},
{
'name': 'Jersey',
'code': 'JE',
},
{
'name': 'Jordan',
'code': 'JO',
},
{
'name': 'Kazakhstan',
'code': 'KZ',
},
{
'name': 'Kenya',
'code': 'KE',
},
{
'name': 'Kiribati',
'code': 'KI',
},
{
'name': 'Korea, Democratic People\'S Republic of',
'code': 'KP',
},
{
'name': 'Korea, Republic of',
'code': 'KR',
},
{
'name': 'Kuwait',
'code': 'KW',
},
{
'name': 'Kyrgyzstan',
'code': 'KG',
},
{
'name': 'Lao People\'S Democratic Republic',
'code': 'LA',
},
{
'name': 'Latvia',
'code': 'LV',
},
{
'name': 'Lebanon',
'code': 'LB',
},
{
'name': 'Lesotho',
'code': 'LS',
},
{
'name': 'Liberia',
'code': 'LR',
},
{
'name': 'Libyan Arab Jamahiriya',
'code': 'LY',
},
{
'name': 'Liechtenstein',
'code': 'LI',
},
{
'name': 'Lithuania',
'code': 'LT',
},
{
'name': 'Luxembourg',
'code': 'LU',
},
{
'name': 'Macao',
'code': 'MO',
},
{
'name': 'Macedonia, The Former Yugoslav Republic of',
'code': 'MK',
},
{
'name': 'Madagascar',
'code': 'MG',
},
{
'name': 'Malawi',
'code': 'MW',
},
{
'name': 'Malaysia',
'code': 'MY',
},
{
'name': 'Maldives',
'code': 'MV',
},
{
'name': 'Mali',
'code': 'ML',
},
{
'name': 'Malta',
'code': 'MT',
},
{
'name': 'Marshall Islands',
'code': 'MH',
},
{
'name': 'Martinique',
'code': 'MQ',
},
{
'name': 'Mauritania',
'code': 'MR',
},
{
'name': 'Mauritius',
'code': 'MU',
},
{
'name': 'Mayotte',
'code': 'YT',
},
{
'name': 'Mexico',
'code': 'MX',
},
{
'name': 'Micronesia, Federated States of',
'code': 'FM',
},
{
'name': 'Moldova, Republic of',
'code': 'MD',
},
{
'name': 'Monaco',
'code': 'MC',
},
{
'name': 'Mongolia',
'code': 'MN',
},
{
'name': 'Montserrat',
'code': 'MS',
},
{
'name': 'Morocco',
'code': 'MA',
},
{
'name': 'Mozambique',
'code': 'MZ',
},
{
'name': 'Myanmar',
'code': 'MM',
},
{
'name': 'Namibia',
'code': 'NA',
},
{
'name': 'Nauru',
'code': 'NR',
},
{
'name': 'Nepal',
'code': 'NP',
},
{
'name': 'Netherlands',
'code': 'NL',
},
{
'name': 'Netherlands Antilles',
'code': 'AN',
},
{
'name': 'New Caledonia',
'code': 'NC',
},
{
'name': 'New Zealand',
'code': 'NZ',
},
{
'name': 'Nicaragua',
'code': 'NI',
},
{
'name': 'Niger',
'code': 'NE',
},
{
'name': 'Nigeria',
'code': 'NG',
},
{
'name': 'Niue',
'code': 'NU',
},
{
'name': 'Norfolk Island',
'code': 'NF',
},
{
'name': 'Northern Mariana Islands',
'code': 'MP',
},
{
'name': 'Norway',
'code': 'NO',
},
{
'name': 'Oman',
'code': 'OM',
},
{
'name': 'Pakistan',
'code': 'PK',
},
{
'name': 'Palau',
'code': 'PW',
},
{
'name': 'Palestinian Territory, Occupied',
'code': 'PS',
},
{
'name': 'Panama',
'code': 'PA',
},
{
'name': 'Papua New Guinea',
'code': 'PG',
},
{
'name': 'Paraguay',
'code': 'PY',
},
{
'name': 'Peru',
'code': 'PE',
},
{
'name': 'Philippines',
'code': 'PH',
},
{
'name': 'Pitcairn',
'code': 'PN',
},
{
'name': 'Poland',
'code': 'PL',
},
{
'name': 'Portugal',
'code': 'PT',
},
{
'name': 'Puerto Rico',
'code': 'PR',
},
{
'name': 'Qatar',
'code': 'QA',
},
{
'name': 'Reunion',
'code': 'RE',
},
{
'name': 'Romania',
'code': 'RO',
},
{
'name': 'Russian Federation',
'code': 'RU',
},
{
'name': 'RWANDA',
'code': 'RW',
},
{
'name': 'Saint Helena',
'code': 'SH',
},
{
'name': 'Saint Kitts and Nevis',
'code': 'KN',
},
{
'name': 'Saint Lucia',
'code': 'LC',
},
{
'name': 'Saint Pierre and Miquelon',
'code': 'PM',
},
{
'name': 'Saint Vincent and the Grenadines',
'code': 'VC',
},
{
'name': 'Samoa',
'code': 'WS',
},
{
'name': 'San Marino',
'code': 'SM',
},
{
'name': 'Sao Tome and Principe',
'code': 'ST',
},
{
'name': 'Saudi Arabia',
'code': 'SA',
},
{
'name': 'Senegal',
'code': 'SN',
},
{
'name': 'Serbia and Montenegro',
'code': 'CS',
},
{
'name': 'Seychelles',
'code': 'SC',
},
{
'name': 'Sierra Leone',
'code': 'SL',
},
{
'name': 'Singapore',
'code': 'SG',
},
{
'name': 'Slovakia',
'code': 'SK',
},
{
'name': 'Slovenia',
'code': 'SI',
},
{
'name': 'Solomon Islands',
'code': 'SB',
},
{
'name': 'Somalia',
'code': 'SO',
},
{
'name': 'South Africa',
'code': 'ZA',
},
{
'name': 'South Georgia and the South Sandwich Islands',
'code': 'GS',
},
{
'name': 'Spain',
'code': 'ES',
},
{
'name': 'Sri Lanka',
'code': 'LK',
},
{
'name': 'Sudan',
'code': 'SD',
},
{
'name': 'Suriname',
'code': 'SR',
},
{
'name': 'Svalbard and Jan Mayen',
'code': 'SJ',
},
{
'name': 'Swaziland',
'code': 'SZ',
},
{
'name': 'Sweden',
'code': 'SE',
},
{
'name': 'Switzerland',
'code': 'CH',
},
{
'name': 'Syrian Arab Republic',
'code': 'SY',
},
{
'name': 'Taiwan, Province of China',
'code': 'TW',
},
{
'name': 'Tajikistan',
'code': 'TJ',
},
{
'name': 'Tanzania, United Republic of',
'code': 'TZ',
},
{
'name': 'Thailand',
'code': 'TH',
},
{
'name': 'Timor-Leste',
'code': 'TL',
},
{
'name': 'Togo',
'code': 'TG',
},
{
'name': 'Tokelau',
'code': 'TK',
},
{
'name': 'Tonga',
'code': 'TO',
},
{
'name': 'Trinidad and Tobago',
'code': 'TT',
},
{
'name': 'Tunisia',
'code': 'TN',
},
{
'name': 'Turkey',
'code': 'TR',
},
{
'name': 'Turkmenistan',
'code': 'TM',
},
{
'name': 'Turks and Caicos Islands',
'code': 'TC',
},
{
'name': 'Tuvalu',
'code': 'TV',
},
{
'name': 'Uganda',
'code': 'UG',
},
{
'name': 'Ukraine',
'code': 'UA',
},
{
'name': 'United Arab Emirates',
'code': 'AE',
},
{
'name': 'United Kingdom',
'code': 'GB',
},
{
'name': 'United States',
'code': 'US',
},
{
'name': 'United States Minor Outlying Islands',
'code': 'UM',
},
{
'name': 'Uruguay',
'code': 'UY',
},
{
'name': 'Uzbekistan',
'code': 'UZ',
},
{
'name': 'Vanuatu',
'code': 'VU',
},
{
'name': 'Venezuela',
'code': 'VE',
},
{
'name': 'Viet Nam',
'code': 'VN',
},
{
'name': 'Virgin Islands, British',
'code': 'VG',
},
{
'name': 'Virgin Islands, U.S.',
'code': 'VI',
},
{
'name': 'Wallis and Futuna',
'code': 'WF',
},
{
'name': 'Western Sahara',
'code': 'EH',
},
{
'name': 'Yemen',
'code': 'YE',
},
{
'name': 'Zambia',
'code': 'ZM',
},
{
'name': 'Zimbabwe',
'code': 'ZW',
},
]