@swan-io/shared-business 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/HISTORY.md +3 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1 -0
  4. package/package.json +46 -0
  5. package/src/components/CountryPicker.d.ts +20 -0
  6. package/src/components/CountryPicker.js +26 -0
  7. package/src/components/SkipToContent.d.ts +3 -0
  8. package/src/components/SkipToContent.js +35 -0
  9. package/src/components/SupportChat.d.ts +26 -0
  10. package/src/components/SupportChat.js +87 -0
  11. package/src/components/SupportingDocument.d.ts +33 -0
  12. package/src/components/SupportingDocument.js +166 -0
  13. package/src/components/UploadArea.d.ts +26 -0
  14. package/src/components/UploadArea.js +161 -0
  15. package/src/constants/business.d.ts +12 -0
  16. package/src/constants/business.js +36 -0
  17. package/src/constants/countries.d.ts +2002 -0
  18. package/src/constants/countries.js +2363 -0
  19. package/src/constants/legal.d.ts +3 -0
  20. package/src/constants/legal.js +9 -0
  21. package/src/constants/registrationNumbers.d.ts +14 -0
  22. package/src/constants/registrationNumbers.js +117 -0
  23. package/src/constants/termsAndConditions.d.ts +7 -0
  24. package/src/constants/termsAndConditions.js +28 -0
  25. package/src/constants/ubos.d.ts +6 -0
  26. package/src/constants/ubos.js +47 -0
  27. package/src/constants/uploads.d.ts +1 -0
  28. package/src/constants/uploads.js +2 -0
  29. package/src/third-party/Pappers.d.ts +8 -0
  30. package/src/third-party/Pappers.js +36 -0
  31. package/src/utils/date.d.ts +3 -0
  32. package/src/utils/date.js +13 -0
  33. package/src/utils/i18n.d.ts +21 -0
  34. package/src/utils/i18n.js +115 -0
  35. package/src/utils/languages.d.ts +6 -0
  36. package/src/utils/languages.js +44 -0
  37. package/src/utils/validation.d.ts +7 -0
  38. package/src/utils/validation.js +65 -0
@@ -0,0 +1,3 @@
1
+ import { CountryCCA3 } from "./countries";
2
+ export declare const companyTypesPerCountry: Partial<Record<CountryCCA3, string>>;
3
+ export declare const countriesWithHomeOwnerAssociation: CountryCCA3[];
@@ -0,0 +1,9 @@
1
+ export const companyTypesPerCountry = {
2
+ BEL: "Entreprise (SA, SPRL, SCRL, SCRIS, SNC, SCS, GIE)",
3
+ DEU: "Firma (GmbH, EI, Gbr, KG)",
4
+ FRA: "Entreprise (SA, SARL, SAS, SCI, EI, EIRL, Micro-entreprise…)",
5
+ ITA: "Società (SS, SRL, SPA, SNC, SAS…)",
6
+ LUX: "Entreprise (SA, SCS, SARLI, SNC, SCA, SC)",
7
+ NLD: "Bedrijf (BV, NV, VOF…)",
8
+ };
9
+ export const countriesWithHomeOwnerAssociation = ["FRA", "BEL"];
@@ -0,0 +1,14 @@
1
+ import { CountryCCA3 } from "./countries";
2
+ export type RegistrationNumberConfig = {
3
+ showRegistrationQuestion: false;
4
+ } | {
5
+ showRegistrationQuestion: true;
6
+ organismName: string;
7
+ registrationNumberLabel: string;
8
+ };
9
+ type CompanyType = "Association" | "Company" | "HomeOwnerAssociation" | "SelfEmployed" | "Other";
10
+ export declare const getRegistrationNumbersConfig: ({ country, companyType, }: {
11
+ country: CountryCCA3;
12
+ companyType: CompanyType;
13
+ }) => RegistrationNumberConfig;
14
+ export {};
@@ -0,0 +1,117 @@
1
+ import { t } from "../utils/i18n";
2
+ const registrationNumbersConfigByCountry = {
3
+ FRA: {
4
+ Company: {
5
+ showRegistrationQuestion: true,
6
+ organismName: t("registrationPage.withOrganismLabel", {
7
+ organismName: "RCS",
8
+ }),
9
+ registrationNumberLabel: "SIREN",
10
+ },
11
+ Association: {
12
+ showRegistrationQuestion: true,
13
+ organismName: t("registrationPage.withOrganismLabel", {
14
+ organismName: "RCS",
15
+ }),
16
+ registrationNumberLabel: "RNA",
17
+ },
18
+ HomeOwnerAssociation: {
19
+ showRegistrationQuestion: false,
20
+ },
21
+ Other: {
22
+ showRegistrationQuestion: true,
23
+ organismName: t("registrationPage.withOrganismLabel", {
24
+ organismName: "RCS",
25
+ }),
26
+ registrationNumberLabel: "SIREN",
27
+ },
28
+ },
29
+ BEL: {
30
+ Company: {
31
+ showRegistrationQuestion: true,
32
+ organismName: t("registrationPage.withOrganismLabel", {
33
+ organismName: "Code des sociétés",
34
+ }),
35
+ registrationNumberLabel: "Numéro d'entreprise (BCE)",
36
+ },
37
+ Association: {
38
+ showRegistrationQuestion: true,
39
+ organismName: t("registrationPage.withOrganismLabel", {
40
+ organismName: "Code des sociétés",
41
+ }),
42
+ registrationNumberLabel: "Numéro d'entreprise (BCE)",
43
+ },
44
+ },
45
+ ITA: {
46
+ Company: {
47
+ showRegistrationQuestion: true,
48
+ organismName: t("registrationPage.withOrganismLabel", {
49
+ organismName: "REGISTRO IMPRESE",
50
+ }),
51
+ registrationNumberLabel: "Numero di registrazione",
52
+ },
53
+ Association: {
54
+ showRegistrationQuestion: true,
55
+ organismName: t("registrationPage.withOrganismLabel", {
56
+ organismName: "REGISTRO IMPRESE",
57
+ }),
58
+ registrationNumberLabel: "Numero di registrazione",
59
+ },
60
+ },
61
+ DEU: {
62
+ Company: {
63
+ showRegistrationQuestion: true,
64
+ organismName: t("registrationPage.withOrganismLabel", {
65
+ organismName: "Handelsregister",
66
+ }),
67
+ registrationNumberLabel: "Registernummer (HRB, HRA, GnR, PR, VR)",
68
+ },
69
+ Association: {
70
+ showRegistrationQuestion: true,
71
+ organismName: t("registrationPage.withOrganismLabel", {
72
+ organismName: "Handelsregister",
73
+ }),
74
+ registrationNumberLabel: "Registration number (VR)",
75
+ },
76
+ },
77
+ LUX: {
78
+ Company: {
79
+ showRegistrationQuestion: true,
80
+ organismName: t("registrationPage.withOrganismLabel", {
81
+ organismName: "RCS",
82
+ }),
83
+ registrationNumberLabel: "Numéro RCS",
84
+ },
85
+ Association: {
86
+ showRegistrationQuestion: true,
87
+ organismName: t("registrationPage.withOrganismLabel", {
88
+ organismName: "RCS",
89
+ }),
90
+ registrationNumberLabel: "Numéro RCS",
91
+ },
92
+ },
93
+ NLD: {
94
+ Company: {
95
+ showRegistrationQuestion: true,
96
+ organismName: t("registrationPage.withOrganismLabel", {
97
+ organismName: "Handelsregister",
98
+ }),
99
+ registrationNumberLabel: "KVK number",
100
+ },
101
+ Association: {
102
+ showRegistrationQuestion: true,
103
+ organismName: t("registrationPage.withOrganismLabel", {
104
+ organismName: "Handelsregister",
105
+ }),
106
+ registrationNumberLabel: "KVK number",
107
+ },
108
+ },
109
+ };
110
+ const defaultRegistrationNumbersConfig = {
111
+ showRegistrationQuestion: true,
112
+ organismName: t("registrationPage.withoutOrganismNameLabel"),
113
+ registrationNumberLabel: t("registrationPage.defaultNumberLabel"),
114
+ };
115
+ export const getRegistrationNumbersConfig = ({ country, companyType, }) => {
116
+ return (registrationNumbersConfigByCountry[country]?.[companyType] ?? defaultRegistrationNumbersConfig);
117
+ };
@@ -0,0 +1,7 @@
1
+ type Locale = "de" | "en" | "es" | "fr" | "it" | "nl" | "pt";
2
+ export declare const getTermsAndConditionsPathByAccountCountryAndLocale: ({ rootUrl, accountCountry, locale, }: {
3
+ rootUrl: string;
4
+ accountCountry?: string | undefined;
5
+ locale: Locale;
6
+ }) => string;
7
+ export {};
@@ -0,0 +1,28 @@
1
+ const termsAndConditions = {
2
+ DEU: {
3
+ de: "deu/de.pdf",
4
+ en: "deu/en.pdf",
5
+ es: "deu/en.pdf",
6
+ fr: "deu/en.pdf",
7
+ it: "deu/en.pdf",
8
+ nl: "deu/en.pdf",
9
+ pt: "deu/en.pdf",
10
+ },
11
+ FRA: {
12
+ de: "en.pdf",
13
+ en: "en.pdf",
14
+ es: "en.pdf",
15
+ fr: "fr.pdf",
16
+ it: "en.pdf",
17
+ nl: "en.pdf",
18
+ pt: "en.pdf",
19
+ },
20
+ };
21
+ const defaultTerms = termsAndConditions.FRA;
22
+ export const getTermsAndConditionsPathByAccountCountryAndLocale = ({ rootUrl, accountCountry, locale, }) => {
23
+ if (accountCountry == null) {
24
+ return new URL(defaultTerms[locale], rootUrl).toString();
25
+ }
26
+ const termsByLocale = termsAndConditions[accountCountry] ?? defaultTerms;
27
+ return new URL(termsByLocale[locale], rootUrl).toString();
28
+ };
@@ -0,0 +1,6 @@
1
+ import { CountryCCA3 } from "./countries";
2
+ export declare const getCountryUbo: (country: CountryCCA3) => {
3
+ singular: string;
4
+ plural: string;
5
+ title: string;
6
+ };
@@ -0,0 +1,47 @@
1
+ import { isCompanyWithUboCountryCCA3 } from "./countries";
2
+ const countryUboDenominations = {
3
+ BEL: {
4
+ singular: "Bénéficiaire effectif",
5
+ plural: "Bénéficiaires effectifs",
6
+ title: "Bénéficiaires",
7
+ },
8
+ DEU: {
9
+ singular: "Wirtschaftlich Berechtigter",
10
+ plural: "Wirtschaftlich Berechtigten",
11
+ title: "Wirtschaftlich Berechtigte",
12
+ },
13
+ FRA: {
14
+ singular: "Bénéficiaire effectif",
15
+ plural: "Bénéficiaires effectifs",
16
+ title: "Bénéficiaires",
17
+ },
18
+ ITA: {
19
+ singular: "Titolare effettivo",
20
+ plural: "Titolari effettivi",
21
+ title: "Titolari effettivi",
22
+ },
23
+ LTU: {
24
+ singular: "Ultimate Beneficial Owner",
25
+ plural: "Ultimate Beneficial Owners",
26
+ title: "Beneficial Owners",
27
+ },
28
+ LUX: {
29
+ singular: "Bénéficiaire effectif",
30
+ plural: "Bénéficiaires effectifs",
31
+ title: "Bénéficiaires",
32
+ },
33
+ NLD: {
34
+ singular: "Ultimate Beneficial Owner",
35
+ plural: "Ultimate Beneficial Owners",
36
+ title: "Beneficial Owners",
37
+ },
38
+ };
39
+ export const getCountryUbo = (country) => {
40
+ return isCompanyWithUboCountryCCA3(country)
41
+ ? countryUboDenominations[country]
42
+ : {
43
+ singular: "Beneficiary",
44
+ plural: "Beneficiaries",
45
+ title: "Beneficiaries",
46
+ };
47
+ };
@@ -0,0 +1 @@
1
+ export declare const MAX_SUPPORTING_DOCUMENT_UPLOAD_SIZE: number;
@@ -0,0 +1,2 @@
1
+ // just below 20MB (* 1000 instead of * 1024) in bytes to account for the rest of the payload
2
+ export const MAX_SUPPORTING_DOCUMENT_UPLOAD_SIZE = 20 * 1000 * 1000;
@@ -0,0 +1,8 @@
1
+ import { Future, Result } from "@swan-io/boxed";
2
+ export type CompanySuggestion = {
3
+ city: string;
4
+ name: string;
5
+ siren: string;
6
+ value: string;
7
+ };
8
+ export declare const queryCompanies: (_query: string) => Future<Result<Array<CompanySuggestion>, Error>>;
@@ -0,0 +1,36 @@
1
+ import { Future, Result } from "@swan-io/boxed";
2
+ import { isNotNullish } from "@swan-io/lake/src/utils/nullish";
3
+ export const queryCompanies = (_query) => Future.make(resolve => {
4
+ const xhr = new XMLHttpRequest();
5
+ xhr.responseType = "json";
6
+ // const params = new URLSearchParams({
7
+ // cibles: "nom_entreprise,denomination,siren",
8
+ // q: query,
9
+ // });
10
+ // xhr.open("GET", `${__SWAN_ENV_PAPPERS_API_URL__}?${params.toString()}`, true);
11
+ xhr.addEventListener("load", () => {
12
+ resolve((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304
13
+ ? Result.Ok(xhr.response)
14
+ : Result.Error(new Error(xhr.statusText)));
15
+ });
16
+ xhr.addEventListener("error", () => {
17
+ resolve(Result.Error(new Error("Failed to fetch companies")));
18
+ });
19
+ const timeoutId = setTimeout(() => xhr.send(), 250);
20
+ return () => {
21
+ xhr.abort();
22
+ clearTimeout(timeoutId);
23
+ };
24
+ }).mapOk(({ resultats_siren = [], resultats_nom_entreprise = [], resultats_denomination = [] }) => {
25
+ return [...resultats_siren, ...resultats_nom_entreprise, ...resultats_denomination]
26
+ .filter(isNotNullish)
27
+ .reduce((acc, result) => {
28
+ const { denomination, nom_entreprise, siege, siren = "" } = result;
29
+ const name = nom_entreprise ?? denomination ?? "";
30
+ const city = [siege?.code_postal, siege?.ville].filter(isNotNullish).join(" ");
31
+ // we don't display result without name, without siren or already displayed
32
+ return name === "" || siren === "" || acc.some(suggestion => suggestion.siren === siren)
33
+ ? acc
34
+ : [...acc, { value: siren, siren, name, city }];
35
+ }, []);
36
+ }, true);
@@ -0,0 +1,3 @@
1
+ export declare const decodeBirthDate: (value: string) => string;
2
+ export declare const isValidBirthDate: (value: string) => boolean;
3
+ export declare const encodeBirthDate: (value: string) => string;
@@ -0,0 +1,13 @@
1
+ import dayjs from "dayjs";
2
+ export const decodeBirthDate = (value) => {
3
+ const date = dayjs.utc(value, "YYYY-MM-DD");
4
+ return date.isValid() ? date.format("DD/MM/YYYY") : "";
5
+ };
6
+ export const isValidBirthDate = (value) => {
7
+ const date = dayjs.utc(value, "DD/MM/YYYY");
8
+ return date.isValid() && date.isBefore(dayjs.utc());
9
+ };
10
+ export const encodeBirthDate = (value) => {
11
+ const date = dayjs.utc(value, "DD/MM/YYYY");
12
+ return date.isValid() ? date.format("YYYY-MM-DD") : "";
13
+ };
@@ -0,0 +1,21 @@
1
+ import { Props } from "@swan-io/lake/src/utils/rifm";
2
+ import { ReactElement, ReactNode } from "react";
3
+ import translationEN from "../locales/en.json";
4
+ declare const supportedLanguages: readonly ["en", "es", "de", "fr", "it", "nl", "pt"];
5
+ type SupportedLanguage = (typeof supportedLanguages)[number];
6
+ type TranslationParams = Record<string, string | number>;
7
+ export type TranslationKey = keyof typeof translationEN;
8
+ type Locale = {
9
+ language: SupportedLanguage;
10
+ translations: Record<string, string>;
11
+ dayjsLocale: ILocale;
12
+ dateFormat: string;
13
+ datePlaceholder: string;
14
+ timeFormat: string;
15
+ timePlaceholder: string;
16
+ };
17
+ export declare const locale: Locale;
18
+ export declare const t: (key: TranslationKey, params?: TranslationParams) => string;
19
+ export declare const formatNestedMessage: (key: TranslationKey, params: Record<string, string | number | ReactElement<any, string | import("react").JSXElementConstructor<any>> | ((children: ReactNode) => ReactNode)>) => (string | ReactElement<unknown, string | import("react").JSXElementConstructor<any>>)[];
20
+ export declare const rifmDateProps: Props;
21
+ export {};
@@ -0,0 +1,115 @@
1
+ import { createIntl, createIntlCache } from "@formatjs/intl";
2
+ import { getRifmProps } from "@swan-io/lake/src/utils/rifm";
3
+ import dayjs from "dayjs";
4
+ import dayjsLocaleDE from "dayjs/locale/de";
5
+ import dayjsLocaleEN from "dayjs/locale/en";
6
+ import dayjsLocaleES from "dayjs/locale/es";
7
+ import dayjsLocaleFR from "dayjs/locale/fr";
8
+ import dayjsLocaleIT from "dayjs/locale/it";
9
+ import dayjsLocaleNL from "dayjs/locale/nl";
10
+ import dayjsLocalePT from "dayjs/locale/pt";
11
+ import customParseFormat from "dayjs/plugin/customParseFormat";
12
+ import localizedFormat from "dayjs/plugin/localizedFormat";
13
+ import relativeTime from "dayjs/plugin/relativeTime";
14
+ import utc from "dayjs/plugin/utc";
15
+ import { cloneElement, isValidElement } from "react";
16
+ import translationDE from "../locales/de.json";
17
+ import translationEN from "../locales/en.json";
18
+ import translationES from "../locales/es.json";
19
+ import translationFR from "../locales/fr.json";
20
+ import translationIT from "../locales/it.json";
21
+ import translationNL from "../locales/nl.json";
22
+ import translationPT from "../locales/pt.json";
23
+ import { getLanguagesHelpers, LANGUAGE_FALLBACK } from "./languages";
24
+ // https://day.js.org/docs/en/plugin/plugin
25
+ dayjs.extend(utc);
26
+ dayjs.extend(customParseFormat);
27
+ dayjs.extend(relativeTime);
28
+ dayjs.extend(localizedFormat);
29
+ const supportedLanguages = ["en", "es", "de", "fr", "it", "nl", "pt"];
30
+ const locales = {
31
+ en: () => ({
32
+ language: "en",
33
+ translations: translationEN,
34
+ dayjsLocale: dayjsLocaleEN,
35
+ dateFormat: "DD/MM/YYYY",
36
+ datePlaceholder: "DD/MM/YYYY",
37
+ timeFormat: "HH:mm:ss",
38
+ timePlaceholder: "HH:mm:ss",
39
+ }),
40
+ de: () => ({
41
+ language: "de",
42
+ translations: translationDE,
43
+ dayjsLocale: dayjsLocaleDE,
44
+ dateFormat: "DD/MM/YYYY",
45
+ datePlaceholder: "DD/MM/YYYY",
46
+ timeFormat: "HH:mm:ss",
47
+ timePlaceholder: "HH:mm:ss",
48
+ }),
49
+ fr: () => ({
50
+ language: "fr",
51
+ translations: translationFR,
52
+ dayjsLocale: dayjsLocaleFR,
53
+ dateFormat: "DD/MM/YYYY",
54
+ datePlaceholder: "JJ/MM/AAAA",
55
+ timeFormat: "HH:mm:ss",
56
+ timePlaceholder: "HH:mm:ss",
57
+ }),
58
+ it: () => ({
59
+ language: "it",
60
+ translations: translationIT,
61
+ dayjsLocale: dayjsLocaleIT,
62
+ dateFormat: "DD/MM/YYYY",
63
+ datePlaceholder: "DD/MM/YYYY",
64
+ timeFormat: "HH:mm:ss",
65
+ timePlaceholder: "HH:mm:ss",
66
+ }),
67
+ nl: () => ({
68
+ language: "nl",
69
+ translations: translationNL,
70
+ dayjsLocale: dayjsLocaleNL,
71
+ dateFormat: "DD/MM/YYYY",
72
+ datePlaceholder: "DD/MM/YYYY",
73
+ timeFormat: "HH:mm:ss",
74
+ timePlaceholder: "HH:mm:ss",
75
+ }),
76
+ es: () => ({
77
+ language: "es",
78
+ translations: translationES,
79
+ dayjsLocale: dayjsLocaleES,
80
+ dateFormat: "DD/MM/YYYY",
81
+ datePlaceholder: "DD/MM/YYYY",
82
+ timeFormat: "HH:mm:ss",
83
+ timePlaceholder: "HH:mm:ss",
84
+ }),
85
+ pt: () => ({
86
+ language: "pt",
87
+ translations: translationPT,
88
+ dayjsLocale: dayjsLocalePT,
89
+ dateFormat: "DD/MM/YYYY",
90
+ datePlaceholder: "DD/MM/YYYY",
91
+ timeFormat: "HH:mm:ss",
92
+ timePlaceholder: "HH:mm:ss",
93
+ }),
94
+ };
95
+ const { getBestLocale } = getLanguagesHelpers(supportedLanguages);
96
+ export const locale = getBestLocale(locales);
97
+ const intl = createIntl({
98
+ defaultLocale: LANGUAGE_FALLBACK,
99
+ fallbackOnEmptyString: false,
100
+ locale: locale.language,
101
+ messages: locale.translations,
102
+ }, createIntlCache());
103
+ export const t = (key, params) => intl.formatMessage({ id: key, defaultMessage: translationEN[key] }, params).toString();
104
+ export const formatNestedMessage = (key, params) => {
105
+ const result = intl.formatMessage({ id: key, defaultMessage: translationEN[key] },
106
+ // @ts-expect-error
107
+ params);
108
+ const resultArray = typeof result === "string" ? [result] : result;
109
+ return resultArray.map((item, index) => isValidElement(item) ? cloneElement(item, { key: `t-${key}-${index}` }) : item);
110
+ };
111
+ export const rifmDateProps = getRifmProps({
112
+ accept: "numeric",
113
+ charMap: { 2: "/", 4: "/" },
114
+ maxLength: 8,
115
+ });
@@ -0,0 +1,6 @@
1
+ export declare const LANGUAGE_FALLBACK = "en";
2
+ export declare const getLanguagesHelpers: <SupportedLanguages extends readonly string[]>(languages: SupportedLanguages) => {
3
+ getFirstSupportedLanguage: (languages: string[]) => SupportedLanguages[number];
4
+ setPreferredLanguage: (language: SupportedLanguages[number]) => void;
5
+ getBestLocale: <Locale>(locales: Record<SupportedLanguages[number], () => Locale>) => Locale;
6
+ };
@@ -0,0 +1,44 @@
1
+ import { isNotNullish, isNullish } from "@swan-io/lake/src/utils/nullish";
2
+ export const LANGUAGE_FALLBACK = "en";
3
+ const PREFERRED_LANGUAGE_KEY = "swan__PreferredLanguage";
4
+ let supportedLanguages = undefined;
5
+ export const getLanguagesHelpers = (languages) => {
6
+ // Restrict shared-business supported languages to the current project ones
7
+ if (isNullish(supportedLanguages)) {
8
+ supportedLanguages = languages;
9
+ }
10
+ const isSupportedLanguage = (language) => (supportedLanguages ?? []).includes(language);
11
+ const getFirstSupportedLanguage = (languages) => languages.find(isSupportedLanguage) ?? LANGUAGE_FALLBACK;
12
+ const getPreferredLanguage = () => {
13
+ try {
14
+ return localStorage.getItem(PREFERRED_LANGUAGE_KEY) ?? undefined;
15
+ }
16
+ catch {
17
+ return;
18
+ }
19
+ };
20
+ return {
21
+ getFirstSupportedLanguage,
22
+ setPreferredLanguage: (language) => {
23
+ try {
24
+ localStorage.setItem(PREFERRED_LANGUAGE_KEY, language);
25
+ window.location.reload();
26
+ }
27
+ catch {
28
+ return;
29
+ }
30
+ },
31
+ getBestLocale: (locales) => {
32
+ const searchParams = new URLSearchParams(document.location.search);
33
+ const langParam = searchParams.get("lang")?.split("-")[0];
34
+ if (isNotNullish(langParam) && isSupportedLanguage(langParam)) {
35
+ return locales[langParam]();
36
+ }
37
+ const preferredLanguage = getPreferredLanguage();
38
+ const language = getFirstSupportedLanguage([...(isNotNullish(preferredLanguage) ? [preferredLanguage] : []), ...navigator.languages]
39
+ .map(language => language.split("-")[0])
40
+ .filter(isNotNullish));
41
+ return locales[language]();
42
+ },
43
+ };
44
+ };
@@ -0,0 +1,7 @@
1
+ import { Validator } from "react-ux-form";
2
+ export declare const isValidVatNumber: (maybeVat: string) => boolean;
3
+ export declare const validateNullableRequired: Validator<string | undefined>;
4
+ export declare const validateRequired: Validator<string>;
5
+ export declare const validateBooleanRequired: Validator<boolean | undefined>;
6
+ export declare const validateIndividualTaxNumber: Validator<string | undefined>;
7
+ export declare const validateCompanyTaxNumber: Validator<string | undefined>;
@@ -0,0 +1,65 @@
1
+ import { t } from "./i18n";
2
+ const VAT_NUMBER_REGEX = /^((AT)?U[0-9]{8}|(BE)?0[0-9]{9}|(BG)?[0-9]{9,10}|(CY)?[0-9]{8}L|(CZ)?[0-9]{8,10}|(DE)?[0-9]{9}|(DK)?[0-9]{8}|(EE)?[0-9]{9}|(EL|GR)?[0-9]{9}|(ES)?[0-9A-Z][0-9]{7}[0-9A-Z]|(FI)?[0-9]{8}|(FR)?[0-9A-Z]{2}[0-9]{9}|(GB)?([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3})|(HU)?[0-9]{8}|(IE)?[0-9]S[0-9]{5}L|(IT)?[0-9]{11}|(LT)?([0-9]{9}|[0-9]{12})|(LU)?[0-9]{8}|(LV)?[0-9]{11}|(MT)?[0-9]{8}|(NL)?[0-9]{9}B[0-9]{2}|(PL)?[0-9]{10}|(PT)?[0-9]{9}|(RO)?[0-9]{2,10}|(SE)?[0-9]{12}|(SI)?[0-9]{8}|(SK)?[0-9]{10})$/;
3
+ // (AT)?U[0-9]{8} | # Austria
4
+ // (BE)?0[0-9]{9} | # Belgium
5
+ // (BG)?[0-9]{9,10} | # Bulgaria
6
+ // (CY)?[0-9]{8}L | # Cyprus
7
+ // (CZ)?[0-9]{8,10} | # Czech Republic
8
+ // (DE)?[0-9]{9} | # Germany
9
+ // (DK)?[0-9]{8} | # Denmark
10
+ // (EE)?[0-9]{9} | # Estonia
11
+ // (EL|GR)?[0-9]{9} | # Greece
12
+ // (ES)?[0-9A-Z][0-9]{7}[0-9A-Z] | # Spain
13
+ // (FI)?[0-9]{8} | # Finland
14
+ // (FR)?[0-9A-Z]{2}[0-9]{9} | # France
15
+ // (GB)?([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3}) | # United Kingdom
16
+ // (HU)?[0-9]{8} | # Hungary
17
+ // (IE)?[0-9]S[0-9]{5}L | # Ireland
18
+ // (IT)?[0-9]{11} | # Italy
19
+ // (LT)?([0-9]{9}|[0-9]{12}) | # Lithuania
20
+ // (LU)?[0-9]{8} | # Luxembourg
21
+ // (LV)?[0-9]{11} | # Latvia
22
+ // (MT)?[0-9]{8} | # Malta
23
+ // (NL)?[0-9]{9}B[0-9]{2} | # Netherlands
24
+ // (PL)?[0-9]{10} | # Poland
25
+ // (PT)?[0-9]{9} | # Portugal
26
+ // (RO)?[0-9]{2,10} | # Romania
27
+ // (SE)?[0-9]{12} | # Sweden
28
+ // (SI)?[0-9]{8} | # Slovenia
29
+ // (SK)?[0-9]{10} # Slovakia
30
+ export const isValidVatNumber = (maybeVat) => {
31
+ return VAT_NUMBER_REGEX.test(maybeVat);
32
+ };
33
+ export const validateNullableRequired = value => {
34
+ if (value == null || !value) {
35
+ return t("error.requiredField");
36
+ }
37
+ };
38
+ export const validateRequired = value => {
39
+ if (!value) {
40
+ return t("error.requiredField");
41
+ }
42
+ };
43
+ export const validateBooleanRequired = value => {
44
+ if (value == null || !value) {
45
+ return t("error.requiredField");
46
+ }
47
+ };
48
+ export const validateIndividualTaxNumber = value => {
49
+ if (value == null || !value) {
50
+ return;
51
+ }
52
+ // accept 11 digits
53
+ if (!/^\d{11}$/.test(value)) {
54
+ return t("common.form.invalidTaxIdentificationNumber");
55
+ }
56
+ };
57
+ export const validateCompanyTaxNumber = value => {
58
+ if (value == null || !value) {
59
+ return;
60
+ }
61
+ // accept 10 or 11 digits
62
+ if (!/^\d{10,11}$/.test(value)) {
63
+ return t("common.form.invalidTaxIdentificationNumber");
64
+ }
65
+ };