Skip to content

Commit

Permalink
feat(PhoneNumber): add filter for showing e.g. only Scandinavia count…
Browse files Browse the repository at this point in the history
…ries (#2959)

```tsx
<Field.PhoneNumber
  label="Label text"
  countries="Scandinavia"
/>
```
  • Loading branch information
tujoworker authored Dec 4, 2023
1 parent a85b5f7 commit 995c43d
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,15 @@ export const ValidationRequired = () => {
</ComponentBox>
)
}

export const WithFilter = () => {
return (
<ComponentBox>
<Field.PhoneNumber
label="Label text"
onChange={(...args) => console.log('onChange', ...args)}
countries="Scandinavia"
/>
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import * as Examples from './Examples'

<Examples.LabelAndValue />

### Show only Scandinavian countries

<Examples.WithFilter />

### With help

<Examples.WithHelp />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import DataValueReadwriteProperties from '../../data-value-readwrite-properties.

| Property | Type | Description |
| --------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------- |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `contents` |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `contents`. |
| `countries` | `string` | _(optional)_ List only a certain set of countries: `Scandinavia`, `NorthernNordic` or `Europe` |
| `countryCodeFieldClassName` | `string` | _(optional)_ Class name for the country code component. |
| `numberFieldClassName` | `string` | _(optional)_ Class name for the number component. |
| `countryCodePlaceholder` | `string` | _(optional)_ Placeholder for the country code field. |
| `countryCodeLabel` | `string` | _(optional)_ Label to show above / before the country code field |
| `countryCodeLabel` | `string` | _(optional)_ Label to show above / before the country code field. |
| `numberMask` | Various | _(optional)_ See property `mask` of the [InputMasked](/uilib/components/input-masked/properties) component. |
| `width` | `string` or `false` | _(optional)_ `large` for predefined standard width, `stretch` for fill available width. |
| [Space](/uilib/layout/space/properties) | Various | _(optional)_ Spacing properties like `top` or `bottom` are supported. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useMemo, useContext, useCallback, useEffect } from 'react'
import { Autocomplete, Flex } from '../../../../components'
import { InputMaskedProps } from '../../../../components/InputMasked'
import classnames from 'classnames'
import countries from '../../constants/countries'
import countries, { CountryType } from '../../constants/countries'
import StringComponent from '../String'
import { useDataValue } from '../../hooks'
import FieldBlock from '../../FieldBlock'
Expand All @@ -20,7 +20,16 @@ export type Props = FieldHelpProps &
width?: 'large' | 'stretch'
onCountryCodeChange?: (value: string | undefined) => void
onNumberChange?: (value: string | undefined) => void
} & {
countries?: 'Scandinavia' | 'NorthernNordic' | 'Europe'

/**
* For internal use only.
*
* @param country
* @returns boolean
*/
filterCountries?: (country: CountryType) => boolean

/**
* For internal testing purposes
*/
Expand Down Expand Up @@ -75,6 +84,7 @@ function PhoneNumber(props: Props) {
countryCodeLabel,
label = sharedContext?.translation.Forms.phoneNumberLabel,
numberMask,
countries: ccFilter,
emptyValue,
info,
warning,
Expand All @@ -92,6 +102,17 @@ function PhoneNumber(props: Props) {
updateValue,
onCountryCodeChange,
onNumberChange,
filterCountries = ccFilter
? (country) => {
switch (ccFilter) {
case 'Scandinavia':
case 'NorthernNordic':
return country.regions?.includes(ccFilter)
default:
return country.continent.includes(ccFilter)
}
}
: undefined,
} = useDataValue(preparedProps)

const countryCodeRef = React.useRef(null)
Expand Down Expand Up @@ -127,9 +148,10 @@ function PhoneNumber(props: Props) {
langRef.current = lang
dataRef.current = getCountryData({
lang,
filter: filterCountries,
})
}
}, [props.value, lang])
}, [props.value, lang, filterCountries])

/**
* On external value change, update the internal,
Expand Down Expand Up @@ -192,12 +214,13 @@ function PhoneNumber(props: Props) {
if (dataRef.current.length < 10) {
dataRef.current = getCountryData({
lang,
filter: filterCountries,
})
updateData(dataRef.current)
}
handleFocus()
},
[handleFocus, lang]
[handleFocus, lang, filterCountries]
)

const isNorway = countryCodeRef.current.includes('47')
Expand Down Expand Up @@ -271,14 +294,6 @@ function PhoneNumber(props: Props) {
)
}

type CountryType = {
cdc: string
iso: string
i18n: {
en: string
}
}

function makeObject(country: CountryType, lang: string) {
return {
selectedKey: `+${country.cdc}`,
Expand All @@ -287,9 +302,22 @@ function makeObject(country: CountryType, lang: string) {
}
}

function getCountryData({ lang = 'en', filter = null } = {}) {
type GetCountryData = {
lang?: string
filter?: Props['filterCountries']
}
function getCountryData({
lang = 'en',
filter = null,
}: GetCountryData = {}) {
return countries
.filter(({ cdc }) => !filter || `+${cdc}` === filter)
.filter((country) => {
if (typeof filter === 'function') {
return filter(country)
}

return !filter || `+${country.cdc}` === filter
})
.sort(({ i18n: a }, { i18n: b }) => (a[lang] > b[lang] ? 1 : -1))
.map((country) => makeObject(country, lang))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,4 +455,60 @@ describe('Field.PhoneNumber', () => {
document.querySelector('[role="alert"]')
).not.toBeInTheDocument()
})

it('should filter countries list with given filterCountries', () => {
render(
<PhoneNumber
filterCountries={({ regions }) => regions?.includes('Scandinavia')}
/>
)

const codeElement: HTMLInputElement = document.querySelector(
'.dnb-forms-field-phone-number__country-code input'
)

// open
fireEvent.focus(codeElement)
fireEvent.keyDown(codeElement, {
key: 'Enter',
keyCode: 13,
})

const liElements = document.querySelectorAll('li:not([aria-hidden])')
expect(liElements).toHaveLength(3)
expect(liElements[0].textContent).toBe('+45 Danmark')
expect(liElements[1].textContent).toBe('+47 Norge')
expect(liElements[2].textContent).toBe('+46 Sverige')

expect(
document.querySelector('li.dnb-drawer-list__option--selected')
.textContent
).toBe('+47 Norge')
})

it('should show only Scandinavian countries', () => {
render(<PhoneNumber countries="Scandinavia" />)

const codeElement: HTMLInputElement = document.querySelector(
'.dnb-forms-field-phone-number__country-code input'
)

// open
fireEvent.focus(codeElement)
fireEvent.keyDown(codeElement, {
key: 'Enter',
keyCode: 13,
})

const liElements = document.querySelectorAll('li:not([aria-hidden])')
expect(liElements).toHaveLength(3)
expect(liElements[0].textContent).toBe('+45 Danmark')
expect(liElements[1].textContent).toBe('+47 Norge')
expect(liElements[2].textContent).toBe('+46 Sverige')

expect(
document.querySelector('li.dnb-drawer-list__option--selected')
.textContent
).toBe('+47 Norge')
})
})
30 changes: 29 additions & 1 deletion packages/dnb-eufemia/src/extensions/forms/constants/countries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,26 @@
*
* cdc: Country Dialing Code
*/
export default [

export type CountryType = {
cdc: string
iso: string
i18n: {
en: string
nb: string
}
continent:
| 'Asia'
| 'Europe'
| 'Africa'
| 'Oceania'
| 'Antarctica'
| 'North America'
| 'South America'
regions?: Array<'Scandinavia' | 'NorthernNordic' | 'AutonomousNordic'>
}

const countries: Array<CountryType> = [
{
i18n: {
en: 'Afghanistan',
Expand Down Expand Up @@ -516,6 +535,7 @@ export default [
cdc: '45',
iso: 'DK',
continent: 'Europe',
regions: ['Scandinavia', 'NorthernNordic'],
},
{
i18n: {
Expand Down Expand Up @@ -642,6 +662,7 @@ export default [
cdc: '298',
iso: 'FO',
continent: 'Europe',
regions: ['AutonomousNordic'],
},
{
i18n: {
Expand All @@ -660,6 +681,7 @@ export default [
cdc: '358',
iso: 'FI',
continent: 'Europe',
regions: ['NorthernNordic'],
},
{
i18n: {
Expand Down Expand Up @@ -759,6 +781,7 @@ export default [
cdc: '299',
iso: 'GL',
continent: 'North America',
regions: ['AutonomousNordic'],
},
{
i18n: {
Expand Down Expand Up @@ -876,6 +899,7 @@ export default [
cdc: '354',
iso: 'IS',
continent: 'Europe',
regions: ['NorthernNordic'],
},
{
i18n: {
Expand Down Expand Up @@ -1452,6 +1476,7 @@ export default [
cdc: '47',
iso: 'NO',
continent: 'Europe',
regions: ['Scandinavia', 'NorthernNordic'],
},
{
i18n: {
Expand Down Expand Up @@ -1902,6 +1927,7 @@ export default [
cdc: '46',
iso: 'SE',
continent: 'Europe',
regions: ['Scandinavia', 'NorthernNordic'],
},
{
i18n: {
Expand Down Expand Up @@ -2192,3 +2218,5 @@ export default [
continent: 'Africa',
},
]

export default countries

0 comments on commit 995c43d

Please sign in to comment.