@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.
- package/HISTORY.md +3 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/package.json +46 -0
- package/src/components/CountryPicker.d.ts +20 -0
- package/src/components/CountryPicker.js +26 -0
- package/src/components/SkipToContent.d.ts +3 -0
- package/src/components/SkipToContent.js +35 -0
- package/src/components/SupportChat.d.ts +26 -0
- package/src/components/SupportChat.js +87 -0
- package/src/components/SupportingDocument.d.ts +33 -0
- package/src/components/SupportingDocument.js +166 -0
- package/src/components/UploadArea.d.ts +26 -0
- package/src/components/UploadArea.js +161 -0
- package/src/constants/business.d.ts +12 -0
- package/src/constants/business.js +36 -0
- package/src/constants/countries.d.ts +2002 -0
- package/src/constants/countries.js +2363 -0
- package/src/constants/legal.d.ts +3 -0
- package/src/constants/legal.js +9 -0
- package/src/constants/registrationNumbers.d.ts +14 -0
- package/src/constants/registrationNumbers.js +117 -0
- package/src/constants/termsAndConditions.d.ts +7 -0
- package/src/constants/termsAndConditions.js +28 -0
- package/src/constants/ubos.d.ts +6 -0
- package/src/constants/ubos.js +47 -0
- package/src/constants/uploads.d.ts +1 -0
- package/src/constants/uploads.js +2 -0
- package/src/third-party/Pappers.d.ts +8 -0
- package/src/third-party/Pappers.js +36 -0
- package/src/utils/date.d.ts +3 -0
- package/src/utils/date.js +13 -0
- package/src/utils/i18n.d.ts +21 -0
- package/src/utils/i18n.js +115 -0
- package/src/utils/languages.d.ts +6 -0
- package/src/utils/languages.js +44 -0
- package/src/utils/validation.d.ts +7 -0
- package/src/utils/validation.js +65 -0
|
@@ -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,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,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,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
|
+
};
|