@adyen/kyc-components
Version:
`adyen-kyc-components` provides the required pieces to build an onboarding flow based on a legal entity. To onboard and verify users, you need to create a user interface (UI) to collect user data. To speed up building your integration, Adyen offers onboar
504 lines (503 loc) • 20.9 kB
JavaScript
;
{
try {
let e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "c9e9f2dd-daee-494f-94d2-a8615ac78c60", e._sentryDebugIdIdentifier = "sentry-dbid-c9e9f2dd-daee-494f-94d2-a8615ac78c60");
} catch (e) {
}
}
;
import { jsx, jsxs, Fragment } from "preact/jsx-runtime";
import { aj as useApiContext, an as useQuery, ao as httpGet, H as Typography, u as useI18nContext, ap as useFormContext, a6 as Alert, J as Field, aq as RadioGroup, ar as getFormProps, h as Icon, as as isEmpty, U as Svg, at as sofStyles, B as Button, au as TaskStatusIndicator, av as normalizedTaskStatusStore, aw as Card, ax as StructuredList, ay as IconButton, az as isEmpty$1, ab as useQueryClient, n as useAnalyticsContext, p as useLegalEntity, Z as useUpdateLegalEntity, ah as useMultiForm, aA as getRequiredForms, aB as addValidityToForms, aC as useFormComposer, g as createLogger, q as Loader, aD as FormContextProvider, aE as FormWrapper } from "./core-B_WrZP-J.js";
import { useState, useRef, useEffect, useMemo, useCallback } from "preact/hooks";
import { signal } from "@preact/signals";
const getTaxClassification = async (legalEntityId, url) => {
return httpGet({
loadingContext: url,
errorLevel: "warn",
errorMessage: `Failed to fetch Business lines`,
path: `legalEntities/${legalEntityId}/taxclassification`,
authentication: "jwt",
headers: {
"Content-Type": "application/json"
}
});
};
const useTaxClassification = (options) => {
const { legalEntityId, baseUrl } = useApiContext();
return useQuery({
queryKey: ["taxClassification", legalEntityId.value, baseUrl.value],
queryFn: () => getTaxClassification(legalEntityId.value, baseUrl.value),
...options
});
};
const taxClassificationErrorMessage = signal(void 0);
const setTaxClassificationErrorMessage = (message) => {
taxClassificationErrorMessage.value = message;
};
const clearTaxClassificationErrorMessage = () => {
taxClassificationErrorMessage.value = void 0;
};
const taxReportingDropin = "adyen-kyc-tax-reporting-dropin";
const textCenter = "adyen-kyc-text-center";
const radioCaption = "adyen-kyc-radio-caption";
const taxReportingDropinGettingStarted = "adyen-kyc-tax-reporting-dropin-getting-started";
const taxReportingDropinFormContainer = "adyen-kyc-tax-reporting-dropin-form-container";
const subtitle = "adyen-kyc-subtitle";
const summary = "adyen-kyc-summary";
const summaryTaxStatusCard = "adyen-kyc-summary-tax-status-card";
const summaryTaxStatusCardHeader = "adyen-kyc-summary-tax-status-card--header";
const summaryTaxStatusCardBody = "adyen-kyc-summary-tax-status-card--body";
const styles = {
taxReportingDropin,
textCenter,
radioCaption,
taxReportingDropinGettingStarted,
taxReportingDropinFormContainer,
subtitle,
summary,
summaryTaxStatusCard,
summaryTaxStatusCardHeader,
summaryTaxStatusCardBody
};
const taxReportingForms = {
taxClassification: {
formId: "taxClassification",
formName: "chooseATaxReportingClassificationOption",
fields: ["type"]
}
};
const taxReportingRequiredFields = {
taxClassification: ["type"]
};
const taxReportingOptions = {
nonFinancialActive: "yourBusinessReceivesTheMajorityOfItsIncomeThroughActiveIncome",
nonFinancialPassive: "yourBusinessGeneratesMoreThanHalfOfItsRevenueAsPassiveIncome",
nonFinancialNonReportable: "yourBusinessIsAPublicListedEntity",
financialNonReportable: "yourBusinessIsAFinancialInstitution"
};
const getTaxStatusSummary = (i18n, taxReportingClassification) => {
var _a;
const taxStatusDescription = ((_a = taxReportingClassification == null ? void 0 : taxReportingClassification.taxClassification) == null ? void 0 : _a.type) ? taxReportingClassification.taxClassification.type : void 0;
return taxStatusDescription ? [
{
term: i18n.get("status"),
details: i18n.get(taxStatusDescription)
},
{
term: i18n.get("description"),
details: i18n.get(taxReportingOptions[taxStatusDescription])
}
] : [];
};
const getTaxOptionsRadioItems = (i18n, taxRecommendationData, taxReportingClassification) => {
const taxOptionsWithoutRecommendation = Object.fromEntries(
Object.entries(taxReportingOptions).filter(([key]) => key !== (taxRecommendationData == null ? void 0 : taxRecommendationData.type))
);
const taxReportingOptionsToShow = (taxRecommendationData == null ? void 0 : taxRecommendationData.type) && !(taxReportingClassification == null ? void 0 : taxReportingClassification.type) ? taxOptionsWithoutRecommendation : taxReportingOptions;
return Object.entries(taxReportingOptionsToShow).map(([key, value]) => ({
id: key,
name: key,
content: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", className: styles.radioCaption, children: i18n.get(value) })
}));
};
const getRecommendedTaxOptionsRadioItems = (i18n, showRecommendation, taxRecommendationData) => {
const taxRecommendationType = (taxRecommendationData == null ? void 0 : taxRecommendationData.type) ? taxRecommendationData.type : void 0;
return showRecommendation && taxRecommendationType ? [
{
id: taxRecommendationType,
name: taxRecommendationType,
content: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", className: styles.radioCaption, children: i18n.get(taxReportingOptions[taxRecommendationType]) })
}
] : [];
};
function TaxReportingClassificationForm({
data,
taxReportingClassification,
taxRecommendationData,
errors
}) {
var _a, _b;
const { i18n } = useI18nContext();
const { form } = useFormContext();
const { handleChangeFor } = form;
const showRecommendation = (taxRecommendationData == null ? void 0 : taxRecommendationData.type) && !(taxReportingClassification == null ? void 0 : taxReportingClassification.type);
const taxOptionsRadioItems = getTaxOptionsRadioItems(
i18n,
taxRecommendationData,
taxReportingClassification
);
const recommendedTaxOptionRadioItems = getRecommendedTaxOptionsRadioItems(
i18n,
showRecommendation,
taxRecommendationData
);
const handleFieldChange = (fieldName, mode) => handleChangeFor(fieldName, "taxClassification", mode);
return /* @__PURE__ */ jsxs("form", { className: "tax-reporting", children: [
/* @__PURE__ */ jsx(Typography, { variant: "title-l", el: "h2", className: styles.textCenter, children: i18n.get("taxStatusSelfCertification") }),
/* @__PURE__ */ jsx(Typography, { variant: "body", el: "div", className: styles.subtitle, children: /* @__PURE__ */ jsx(
"div",
{
dangerouslySetInnerHTML: {
__html: i18n.get("chooseTheTaxStatusWhichBestRepresentsYourBusiness")
}
}
) }),
((_a = errors == null ? void 0 : errors.type) == null ? void 0 : _a.errorMessage) && /* @__PURE__ */ jsx(Alert, { variant: "error", title: i18n.get(errors.type.errorMessage) }),
showRecommendation ? /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Typography, { variant: "body-stronger", children: i18n.get("recommendedForYourBusiness") }),
/* @__PURE__ */ jsx(Field, { name: "type", errorMessage: (_b = errors == null ? void 0 : errors.type) == null ? void 0 : _b.errorMessage, children: (childProps) => /* @__PURE__ */ jsx(
RadioGroup,
{
...childProps,
name: "type",
items: recommendedTaxOptionRadioItems,
value: data == null ? void 0 : data.type,
onChange: handleFieldChange("type", "input")
}
) }),
/* @__PURE__ */ jsx(Typography, { variant: "body-stronger", children: i18n.get("otherOptions") })
] }) : null,
/* @__PURE__ */ jsx(Field, { name: "type", children: (childProps) => /* @__PURE__ */ jsx(
RadioGroup,
{
...childProps,
name: "type",
items: taxOptionsRadioItems,
value: data == null ? void 0 : data.type,
onChange: handleFieldChange("type", "input")
}
) })
] });
}
const taxClassificationFormID = taxReportingForms.taxClassification.formId;
function TaxReporting(props) {
const { form } = useFormContext();
const { errors, valid, fieldProblems: fieldValidationErrors } = form;
const { activeForm: propActiveForm, taxReportingClassification, taxRecommendationData } = props;
const classificationFormProps = getFormProps(props, taxClassificationFormID);
const renderActiveForm = (activeForm) => /* @__PURE__ */ jsx(Fragment, { children: (activeForm == null ? void 0 : activeForm.formId) === taxClassificationFormID && /* @__PURE__ */ jsx("div", { className: styles.taxReportingDropinFormContainer, children: /* @__PURE__ */ jsx(
TaxReportingClassificationForm,
{
...classificationFormProps,
taxReportingClassification,
taxRecommendationData,
errors: errors == null ? void 0 : errors.taxClassification,
valid: valid == null ? void 0 : valid.taxClassification,
fieldValidationErrors: fieldValidationErrors == null ? void 0 : fieldValidationErrors.taxClassification
}
) }) });
return /* @__PURE__ */ jsxs("div", { className: "tax-reporting", children: [
taxClassificationErrorMessage.value && /* @__PURE__ */ jsxs(
Typography,
{
variant: "caption",
color: "critical",
"aria-live": "polite",
className: "adyen-kyc-u-justify-content-center adyen-kyc-u-display-flex",
children: [
/* @__PURE__ */ jsx(Icon, { name: "field-error" }),
" ",
/* @__PURE__ */ jsx("div", { children: taxClassificationErrorMessage.value })
]
}
),
renderActiveForm(propActiveForm)
] });
}
const TaxReportingGettingStarted = ({
handleToggleFormVisible,
handleCancelClick,
taxReportingClassification
}) => {
var _a, _b, _c, _d;
const { i18n } = useI18nContext();
const hasTaxReportingClassification = !isEmpty(
(_a = taxReportingClassification == null ? void 0 : taxReportingClassification.taxClassification) == null ? void 0 : _a.type
);
const taxStatusSummary = getTaxStatusSummary(i18n, taxReportingClassification);
return /* @__PURE__ */ jsxs("div", { className: styles.taxReportingDropinGettingStarted, children: [
!hasTaxReportingClassification && /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(
Svg,
{
type: "image",
testId: "source-of-funds-getting-started-icon",
name: "tax-reporting-graph",
className: sofStyles.sourceOfFundsGettingStartedIcon
}
),
/* @__PURE__ */ jsx(
Typography,
{
className: sofStyles.sourceOfFundsGettingStartedHeading,
el: "h2",
variant: "title-l",
children: i18n.get("taxStatusSelfCertification")
}
),
/* @__PURE__ */ jsx(
Typography,
{
className: sofStyles.sourceOfFundsGettingStartedHeading,
el: "div",
variant: "body",
children: i18n.get("toUnderstandIfYourBankAccountDetailsAreReportable")
}
),
/* @__PURE__ */ jsxs("div", { className: sofStyles.sourceOfFundsGettingStartedActions, children: [
/* @__PURE__ */ jsx(
Button,
{
fullWidth: true,
testId: "source-of-funds-getting-primary-button",
onClick: handleToggleFormVisible,
children: i18n.get("gettingStarted")
}
),
handleCancelClick && /* @__PURE__ */ jsx(
Button,
{
variant: "tertiary",
fullWidth: true,
testId: "source-of-funds-getting-cancel-button",
onClick: handleCancelClick,
children: i18n.get("backToTaskList")
}
)
] })
] }),
hasTaxReportingClassification && /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx(
TaskStatusIndicator,
{
taskStatus: (_d = (_c = (_b = normalizedTaskStatusStore) == null ? void 0 : _b.value) == null ? void 0 : _c.TAX_REPORTING) == null ? void 0 : _d.status
}
),
/* @__PURE__ */ jsx(Typography, { className: styles.textCenter, el: "h2", variant: "title-l", children: i18n.get("selfCertifiedTaxStatus") }),
/* @__PURE__ */ jsx(Typography, { className: styles.subtitle, el: "div", variant: "body", children: i18n.get("noFurtherActionOrRecertificationIsNeeded") }),
/* @__PURE__ */ jsx("div", { className: styles.summary, children: /* @__PURE__ */ jsx(
Card,
{
className: styles.summaryTaxStatusCard,
headerClassName: styles.summaryTaxStatusCardHeader,
bodyClassName: styles.summaryTaxStatusCardBody,
title: i18n.get("taxStatus"),
headerButton: /* @__PURE__ */ jsx(
IconButton,
{
ariaLabel: "edit",
icon: "edit",
onClick: handleToggleFormVisible,
variant: "tertiary"
}
),
children: /* @__PURE__ */ jsx(
StructuredList,
{
className: styles.summaryTaxStatusCardDescription,
items: taxStatusSummary
}
)
}
) })
] }),
handleCancelClick && /* @__PURE__ */ jsx(
Button,
{
variant: "secondary",
testId: "source-of-funds-getting-return-button",
onClick: handleCancelClick,
children: i18n.get("backToTaskList")
}
)
] })
] });
};
const taxReportingTypeValidations = {
type: {
modes: ["blur"],
validate: (type) => !isEmpty$1(type),
errorMessage: "chooseATaxStatusOptionToContinue"
}
};
const logger = createLogger();
function TaxReportingDropin({ problems, handleHomeClick }) {
var _a, _b, _c, _d, _e;
const [loadingStatus, setLoadingStatus] = useState("success");
const [formVisible, setFormVisible] = useState(false);
useRef(null);
const queryClient = useQueryClient();
const { i18n } = useI18nContext();
const { data: taxRecommendationData, isLoading: isLoadingTaxRecommendationData } = useTaxClassification();
const userEvents = useAnalyticsContext();
const { data: legalEntityData, isLoading } = useLegalEntity();
const { mutateAsync: updateLegalEntityMutation } = useUpdateLegalEntity();
useEffect(() => {
clearTaxClassificationErrorMessage();
}, []);
useEffect(() => {
userEvents.addTaskEvent("Landed on page", {
actionType: "start"
});
}, [userEvents]);
const taxReportingClassification = useMemo(
() => {
var _a2, _b2;
return {
taxClassification: {
type: (_b2 = (_a2 = legalEntityData == null ? void 0 : legalEntityData.organization) == null ? void 0 : _a2.taxReportingClassification) == null ? void 0 : _b2.type
}
};
},
[(_b = (_a = legalEntityData == null ? void 0 : legalEntityData.organization) == null ? void 0 : _a.taxReportingClassification) == null ? void 0 : _b.type]
);
const defaultData = useMemo(
() => ({
...taxReportingClassification
}),
[taxReportingClassification]
);
const form = useMultiForm({
requiredFields: taxReportingRequiredFields,
rules: {
taxClassification: taxReportingTypeValidations
},
defaultData
});
const { data = taxReportingClassification, setData, triggerValidation } = form;
const canSubmitForm = useMemo(
() => {
var _a2;
return !isEmpty$1((_a2 = data == null ? void 0 : data.taxClassification) == null ? void 0 : _a2.type);
},
[(_c = data == null ? void 0 : data.taxClassification) == null ? void 0 : _c.type]
);
useEffect(() => {
var _a2, _b2, _c2;
if (!((_a2 = data == null ? void 0 : data.taxClassification) == null ? void 0 : _a2.type) && (((_b2 = taxReportingClassification == null ? void 0 : taxReportingClassification.taxClassification) == null ? void 0 : _b2.type) || (taxRecommendationData == null ? void 0 : taxRecommendationData.type))) {
setData(
"type",
((_c2 = taxReportingClassification == null ? void 0 : taxReportingClassification.taxClassification) == null ? void 0 : _c2.type) ?? (taxRecommendationData == null ? void 0 : taxRecommendationData.type),
"taxClassification"
);
(async () => {
await triggerValidation("taxClassification");
})().catch(() => console.error("Error triggering validation"));
}
}, [
(_d = data == null ? void 0 : data.taxClassification) == null ? void 0 : _d.type,
taxRecommendationData == null ? void 0 : taxRecommendationData.type,
(_e = taxReportingClassification == null ? void 0 : taxReportingClassification.taxClassification) == null ? void 0 : _e.type,
setData,
triggerValidation
]);
const forms = useMemo(() => {
const requiredForms = getRequiredForms(
taxReportingForms,
taxReportingRequiredFields,
void 0
);
const requiredFormsWithoutSummary = requiredForms.filter((form2) => form2.formId !== "summary");
return addValidityToForms(requiredFormsWithoutSummary, form.isValid, problems);
}, [form.isValid, problems]);
const handleSubmit = useCallback(async () => {
var _a2;
if (!legalEntityData) {
return;
}
setLoadingStatus("loading");
const taxReportingPayload = {
businessType: taxRecommendationData == null ? void 0 : taxRecommendationData.businessType,
financialInstitutionNumber: taxRecommendationData == null ? void 0 : taxRecommendationData.financialInstitutionNumber,
mainSourceOfIncome: taxRecommendationData == null ? void 0 : taxRecommendationData.mainSourceOfIncome,
type: (_a2 = data == null ? void 0 : data.taxClassification) == null ? void 0 : _a2.type
};
const legalEntityPayload = {
id: legalEntityData.id,
...(legalEntityData == null ? void 0 : legalEntityData.organization) && {
organization: {
...legalEntityData.organization,
taxReportingClassification: taxReportingPayload
}
}
};
try {
await updateLegalEntityMutation(legalEntityPayload);
await queryClient.invalidateQueries({
queryKey: ["taxClassification"]
});
await queryClient.invalidateQueries({
queryKey: ["taskStatus"]
});
handleHomeClick == null ? void 0 : handleHomeClick();
setFormVisible(false);
gotoFormByFormIndex(0);
setTaxClassificationErrorMessage("");
setLoadingStatus("success");
} catch (e) {
setTaxClassificationErrorMessage((e == null ? void 0 : e.message) || i18n.get("errorUpdatingTaxClassification"));
logger.log("Error updating source of funds", e);
setLoadingStatus("success");
}
}, [data, taxRecommendationData, legalEntityData, updateLegalEntityMutation]);
const handleToggleFormVisible = () => {
setFormVisible(!formVisible);
};
const {
handleNextClick,
activeForm,
setShouldValidate,
gotoFormByFormIndex,
steps
} = useFormComposer({
problems,
forms,
onSubmit: handleSubmit,
triggerValidation: form.triggerValidation
});
return /* @__PURE__ */ jsx("div", { className: styles.taxReportingDropin, children: isLoading || isLoadingTaxRecommendationData ? /* @__PURE__ */ jsx(Loader, { size: "medium" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
!formVisible && /* @__PURE__ */ jsx(
TaxReportingGettingStarted,
{
handleCancelClick: handleHomeClick,
handleToggleFormVisible,
taxReportingClassification,
problems: legalEntityData == null ? void 0 : legalEntityData.problems
}
),
formVisible && /* @__PURE__ */ jsx(FormContextProvider, { form, children: /* @__PURE__ */ jsx(
FormWrapper,
{
taskName: "taxReportingClassification",
gotoFormByFormIndex,
hideSidebar: true,
loadingStatus,
forms,
activeForm,
validateForm: () => setShouldValidate(true),
onSubmit: handleSubmit,
problems,
canSubmit: canSubmitForm,
handleNextClick,
showBackButton: true,
handleBackClick: handleToggleFormVisible,
handleHomeClick,
steps,
children: /* @__PURE__ */ jsx(
TaxReporting,
{
taxReportingClassification: taxReportingClassification == null ? void 0 : taxReportingClassification.taxClassification,
taxRecommendationData,
activeForm,
data
}
)
}
) })
] }) });
}
export {
TaxReportingDropin
};