diff --git a/frontend/package-lock.json b/frontend/package-lock.json index bd48e4e07fb4297b189958be2766dcfbf2d3a621..3724ab19a92e6014acb3ec7011148ea558b2587b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -32,6 +32,7 @@ "i18next": "^20.6.0", "i18next-browser-languagedetector": "^6.1.2", "i18next-http-backend": "^1.3.1", + "libphonenumber-js": "^1.9.35", "react": "^17.0.2", "react-datepicker": "^4.2.1", "react-dom": "^17.0.2", @@ -13856,6 +13857,11 @@ "node": ">= 0.8.0" } }, + "node_modules/libphonenumber-js": { + "version": "1.9.35", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.35.tgz", + "integrity": "sha512-6ok1JD4GcU7owpbp07WJZlxoGdlY538OCgN9fmOlWwCzqPNLzra7tvaFz7NJP8Hcmp1lkm97wNZ2hICN9uGylg==" + }, "node_modules/lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -33040,6 +33046,11 @@ "type-check": "~0.4.0" } }, + "libphonenumber-js": { + "version": "1.9.35", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.35.tgz", + "integrity": "sha512-6ok1JD4GcU7owpbp07WJZlxoGdlY538OCgN9fmOlWwCzqPNLzra7tvaFz7NJP8Hcmp1lkm97wNZ2hICN9uGylg==" + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", diff --git a/frontend/package.json b/frontend/package.json index d58a3affc08aa3e8608bd22b8be4b9abd869bde8..8048554994014c225236c156172982cb61f3a8b6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,6 +27,7 @@ "i18next": "^20.6.0", "i18next-browser-languagedetector": "^6.1.2", "i18next-http-backend": "^1.3.1", + "libphonenumber-js": "^1.9.35", "react": "^17.0.2", "react-datepicker": "^4.2.1", "react-dom": "^17.0.2", diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json index c5e5e7350a3ef79c9fed8a541408f78e033c5799..8c7ae1d54760d266622b59170adc54721c5fbfa1 100644 --- a/frontend/public/locales/en/common.json +++ b/frontend/public/locales/en/common.json @@ -50,7 +50,8 @@ "nationalIdNumberRequired": "National ID number required", "roleTypeRequired": "Role type is required", "roleEndRequired": "Role end date is required", - "emailRequired": "E-mail is required" + "emailRequired": "E-mail is required", + "invalidMobilePhoneNumber": "Invalid phone number" }, "button": { "back": "Back", diff --git a/frontend/public/locales/nb/common.json b/frontend/public/locales/nb/common.json index 67239ab90429c20ff6083251b7058dfd8eba4776..9e57b96bbdc37475ed51e98a1362852bb663d503 100644 --- a/frontend/public/locales/nb/common.json +++ b/frontend/public/locales/nb/common.json @@ -50,7 +50,8 @@ "nationalIdNumberRequired": "Fødselsnummer er påkrevd", "roleTypeRequired": "Rolletype er påkrevd", "roleEndRequired": "Sluttdato for rolle er påkrevd", - "emailRequired": "E-post er obligatorisk" + "emailRequired": "E-post er obligatorisk", + "invalidMobilePhoneNumber": "Ugyldig telefonnummer" }, "button": { "back": "Tilbake", diff --git a/frontend/public/locales/nn/common.json b/frontend/public/locales/nn/common.json index 0c80b604abffb7bb7a7861173ebeb058600f16b4..17c7a2426d86f8bf499f2abfac18e768a91832d0 100644 --- a/frontend/public/locales/nn/common.json +++ b/frontend/public/locales/nn/common.json @@ -52,6 +52,7 @@ "roleTypeRequired": "Rolletype er påkrevd", "roleEndRequired": "Sluttdato for rolle er påkrevd", "emailRequired": "E-post er obligatorisk" + "invalidMobilePhoneNumber": "Ugyldig telefonnummer" }, "button": { "back": "Tilbake", diff --git a/frontend/src/utils/index.test.ts b/frontend/src/utils/index.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..766fcd120c90747de174fd7f61f9779ced7a5e5c --- /dev/null +++ b/frontend/src/utils/index.test.ts @@ -0,0 +1,14 @@ +import { isValidMobilePhoneNumber } from './index' + +// Mock i18next module to return a translation that just returns the key +jest.mock('i18next', () => ({ + t: (value: string) => value, +})) + +test('Invalid phone number', async () => { + expect(isValidMobilePhoneNumber('dafasfdsfasdf')).not.toEqual(true) +}) + +test('Valid phone number', async () => { + expect(isValidMobilePhoneNumber('+47 97510000')).toEqual(true) +}) diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts index f269b160aac3b663ad716744d901823f859a7d38..d7a9f1b8fd0983c828dc5d335c631611f6a501cd 100644 --- a/frontend/src/utils/index.ts +++ b/frontend/src/utils/index.ts @@ -1,52 +1,64 @@ import validator from '@navikt/fnrvalidator' import i18n from 'i18next' +import {isValidPhoneNumber} from 'libphonenumber-js' export function getCookie(name: string) { - if (!document.cookie) { - return null - } + if (!document.cookie) { + return null + } - const cookies = document.cookie - .split(';') - .map((c) => c.trim()) - .filter((c) => c.startsWith(`${name}=`)) + const cookies = document.cookie + .split(';') + .map((c) => c.trim()) + .filter((c) => c.startsWith(`${name}=`)) - if (cookies.length === 0) { - return null - } - return decodeURIComponent(cookies[0].split('=')[1]) + if (cookies.length === 0) { + return null + } + return decodeURIComponent(cookies[0].split('=')[1]) } export function maybeCsrfToken() { - const csrfToken = getCookie('csrftoken') - if (!csrfToken) { - return null - } - return { - 'X-CSRFToken': csrfToken, - } + const csrfToken = getCookie('csrftoken') + if (!csrfToken) { + return null + } + return { + 'X-CSRFToken': csrfToken, + } } export function postJsonOpts(data: object): RequestInit { - return { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...maybeCsrfToken(), - }, - body: JSON.stringify(data), - credentials: 'same-origin', - } + return { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...maybeCsrfToken(), + }, + body: JSON.stringify(data), + credentials: 'same-origin', + } } export function isValidFnr(data: string | undefined): boolean | string { - if (data === null) { + if (data === null) { + return i18n.t('common:validation.invalidIdNumber').toString() + } + const valid = validator.idnr(data as string).status === 'valid' + if (valid) { + return true + } + // TypeScript complains if toString is not used on the function result return i18n.t('common:validation.invalidIdNumber').toString() - } - const valid = validator.idnr(data as string).status === 'valid' - if (valid) { - return true - } - // TypeScript complains if toString is not used on the function result - return i18n.t('common:validation.invalidIdNumber').toString() } + +export function isValidMobilePhoneNumber(data: string | undefined): boolean | string { + if (!data) { + return i18n.t<string>('common:validation.invalidMobilePhoneNumber') + } + const valid = isValidPhoneNumber(data) + if (valid) { + return true + } + return i18n.t<string>('common:validation.invalidMobilePhoneNumber') +} \ No newline at end of file