Skip to content

Commit

Permalink
fix: remove @ac-dev/countries-service dependency to fetch countries a…
Browse files Browse the repository at this point in the history
…nd states from static assets
  • Loading branch information
gciotola committed Nov 28, 2023
1 parent 2263da7 commit 4179b1b
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 31 deletions.
1 change: 0 additions & 1 deletion packages/app-elements/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"ts:check": "tsc --noEmit"
},
"dependencies": {
"@ac-dev/countries-service": "^1.2.0",
"@commercelayer/sdk": "5.21.1",
"@types/lodash": "^4.14.200",
"@types/react": "^18.2.34",
Expand Down
158 changes: 158 additions & 0 deletions packages/app-elements/src/mocks/data/countries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { rest } from 'msw'

export default [
rest.get(
`https://data.commercelayer.app/assets/lists/countries.json`,
async (req, res, ctx) => {
return await res(
ctx.status(200),
ctx.json([
{
label: 'Angola',
value: 'AO'
},
{
label: 'Hungary',
value: 'HU'
},
{
label: 'Iraq',
value: 'IQ'
},
{
label: 'Ireland',
value: 'IE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Jamaica',
value: 'JM'
},
{
label: 'Japan',
value: 'JP'
},
{
label: 'Philippines',
value: 'PH'
},
{
label: 'Pitcairn Island',
value: 'PN'
},
{
label: 'Poland',
value: 'PL'
},
{
label: 'Portugal',
value: 'PT'
},
{
label: 'United Kingdom',
value: 'GB'
},
{
label: 'United States',
value: 'US'
},
{
label: 'United States Minor Outlying Islands',
value: 'UM'
},
{
label: 'Uruguay',
value: 'UY'
}
])
)
}
),
rest.get(
`https://data.commercelayer.app/assets/lists/states/IT.json`,
async (req, res, ctx) => {
return await res(
ctx.status(200),
ctx.json([
{
label: 'Agrigento',
value: 'AG'
},
{
label: 'Alessandria',
value: 'AL'
},
{
label: 'Como',
value: 'CO'
},
{
label: 'Firenze',
value: 'FI'
},
{
label: 'Genoa',
value: 'GE'
},
{
label: 'Milano',
value: 'MI'
},
{
label: 'Napoli',
value: 'NA'
}
])
)
}
),
rest.get(
`https://data.commercelayer.app/assets/lists/states/US.json`,
async (req, res, ctx) => {
return await res(
ctx.status(200),
ctx.json([
{
label: 'Alabama',
value: 'AL'
},
{
label: 'Alaska',
value: 'AK'
},
{
label: 'Arizona',
value: 'AZ'
},
{
label: 'Arkansas',
value: 'AR'
},
{
label: 'California',
value: 'CA'
},
{
label: 'Colorado',
value: 'CO'
},
{
label: 'Connecticut',
value: 'CT'
},
{
label: 'Delaware',
value: 'DE'
},
{
label: 'District of Columbia',
value: 'DC'
}
])
)
}
)
]
4 changes: 3 additions & 1 deletion packages/app-elements/src/mocks/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { rest } from 'msw'

import countries from './data/countries'
import customers from './data/customers'

export const handlers = [
Expand Down Expand Up @@ -105,7 +106,8 @@ export const handlers = [
)
}),

...customers
...customers,
...countries
]

function returnEmptyList(url: URL): boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { withSkeletonTemplate } from '#ui/atoms/SkeletonTemplate'
import { Countries } from '@ac-dev/countries-service'

import { useCoreSdkProvider } from '#providers/CoreSdkProvider'
import { Button } from '#ui/atoms/Button'
import { Grid } from '#ui/atoms/Grid'
import { withSkeletonTemplate } from '#ui/atoms/SkeletonTemplate'
import { Spacer } from '#ui/atoms/Spacer'
import { HookedForm } from '#ui/forms/Form/HookedForm'
import { HookedInput } from '#ui/forms/Input/HookedInput'
import { type InputSelectValue } from '#ui/forms/InputSelect'
import { HookedInputSelect } from '#ui/forms/InputSelect/HookedInputSelect'
import { HookedInputTextArea } from '#ui/forms/InputTextArea'
import { HookedValidationApiError } from '#ui/forms/ReactHookForm/HookedValidationApiError'
import { type Address } from '@commercelayer/sdk'
import { zodResolver } from '@hookform/resolvers/zod'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import React, { useEffect, useState } from 'react'
import { useForm, useFormContext } from 'react-hook-form'
import { z } from 'zod'

const zodString = z
Expand Down Expand Up @@ -61,11 +60,6 @@ export const ResourceAddressForm =

const { sdkClient } = useCoreSdkProvider()

const countries = Countries.getCountries().map((country) => ({
value: country.iso2,
label: country.name
}))

return (
<HookedForm
{...methods}
Expand Down Expand Up @@ -100,21 +94,19 @@ export const ResourceAddressForm =
<HookedInput name='line_2' label='Address line 2' />
</FieldRow>

<FieldRow columns='2'>
<FieldRow columns='1'>
<SelectCountry />
</FieldRow>

<FieldRow columns='1'>
<HookedInput name='city' label='City' />
<Grid columns='2'>
<HookedInput name='zip_code' label='ZIP code' />
<HookedInput name='state_code' label='State code' />
</Grid>
</FieldRow>

<FieldRow columns='1'>
<HookedInputSelect
name='country_code'
label='Country'
initialValues={countries}
pathToValue='value'
/>
<div className='grid grid-cols-[2fr_1fr] gap-4'>
<SelectStates />
<HookedInput name='zip_code' label='ZIP code' />
</div>
</FieldRow>

<FieldRow columns='1'>
Expand Down Expand Up @@ -155,3 +147,89 @@ const FieldRow = ({
</Spacer>
)
}

const SelectCountry: React.FC = () => {
const [countries, setCountries] = useState<InputSelectValue[] | undefined>()
const [forceTextInput, setForceTextInput] = useState(false)

useEffect(() => {
void fetch('https://data.commercelayer.app/assets/lists/countries.json')
.then(async (res) => await res.json())
.then((data) => {
setCountries(data)
})
.catch(() => {
// error fetching states, fallback to text input
setForceTextInput(true)
})
}, [])

if (forceTextInput) {
return <HookedInput name='country_code' label='Country' />
}

return (
<HookedInputSelect
name='country_code'
label='Country'
key={countries?.length}
initialValues={countries ?? []}
pathToValue='value'
isLoading={countries == null}
/>
)
}

const SelectStates: React.FC = () => {
const [states, setStates] = useState<InputSelectValue[] | undefined>()
const { watch, setValue } = useFormContext<ResourceAddressFormValues>()
const [forceTextInput, setForceTextInput] = useState(false)

const countryCode = watch('country_code')
const stateCode = watch('state_code')
const countryWithStates = ['US', 'IT']

useEffect(() => {
if (countryCode != null && countryWithStates.includes(countryCode)) {
void fetch(
`https://data.commercelayer.app/assets/lists/states/${countryCode}.json`
)
.then(async (res) => await res.json())
.then((data) => {
setStates(data)
if (
data.find(
({ value }: { value: string; label: string }) =>
value === stateCode
) == null
) {
// reset state_code if not found in the list
setValue('state_code', '')
}
})
.catch(() => {
// error fetching states, fallback to text input
setForceTextInput(true)
})
}
}, [countryCode])

if (
!countryWithStates.includes(countryCode) ||
states?.length === 0 ||
forceTextInput
) {
return <HookedInput name='state_code' label='State code' />
}

return (
<HookedInputSelect
name='state_code'
label='State'
key={`${countryCode}_${states?.length}`}
initialValues={states ?? []}
pathToValue='value'
isLoading={states == null}
/>
)
}
8 changes: 0 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4179b1b

Please sign in to comment.