Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(PhoneNumber): add filter for showing e.g. only Scandinavia countries #2959

Merged
merged 3 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading