@adyen/kyc-components
Version:
This guide assumes that you have already an account with Adyen. A legalEntity needs to be created, and you need to have a `legalEntityId` to instatiate a Component.
858 lines (857 loc) • 43.8 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] = "dc8933c1-42c1-4c85-921a-3eb0ba6022be", e._sentryDebugIdIdentifier = "sentry-dbid-dc8933c1-42c1-4c85-921a-3eb0ba6022be");
} catch (e) {}
import { n as addResourceBundles, r as useTranslation, t as Trans } from "./translation-BFxyJ1c5.js";
import { r as Loader, t as Button } from "./Button-oj6H8OrC.js";
import { s as useApiContext } from "./http-D1NDkBxF.js";
import { r as useLegalEntity, t as ROOT_LE } from "./useLegalEntity-yxi9XhLi.js";
import { t as getLegalEntityCountry } from "./getLegalEntityCountry-C6bSV6sB.js";
import { t as useSettingsContext } from "./useSettingsContext-DzwVt0W0.js";
import { r as cloneObject, t as useAnalyticsContext } from "./useAnalyticsContext-BVFDMrVE.js";
import { t as useToggleContext } from "./useToggleContext-DaQUBF8O.js";
import { d as extractFieldName, m as hasEmptyFields, u as concatenateFieldNames, v as isAccountIdentifierObscured } from "./validatorUtils-DRapRJ6z.js";
import { t as _rolldown_dynamic_import_helper_default } from "./_rolldown_dynamic_import_helper-rq_tsyLP.js";
import { n as datasetUtilities } from "./datasetUtil-Zd4TCTDn.js";
import { C as EntityTypes } from "./processCapabilities-DlZY9-Jc.js";
import { p as TaskTypes } from "./entityAssociationUtil-BEzUdPbm.js";
import { t as SettingNames } from "./types-CNZsK2dZ.js";
import { t as useToastContext } from "./useToastContext-CYgfHjSb.js";
import { n as useCapabilityProblems, t as getProblemsForEntity } from "./getProblemsForEntity-BLcIg3x_.js";
import { t as LoaderWrapper } from "./LoaderWrapper-Dq8TNJCi.js";
import { t as Confirm } from "./Confirm-B6TWSuab.js";
import { n as FeatureNames, t as ExperimentNames } from "./types-8S6KTD2W.js";
import { t as Image } from "./Image-BEzOZ1tt.js";
import { n as getLegalEntityNameBasedOnType, r as getPayoutAccountHolderName } from "./getName-Bdwp_hkV.js";
import { t as useNavigate } from "./useNavigate-lR8Lcsrq.js";
import { n as FormFlow, r as FormContextProvider, t as useFormContext } from "./useFormContext-Cx9-3iXR.js";
import { r as getPropsFromConfigurations } from "./process-field-configurations-C7MuEj5q.js";
import { i as useFormComposer, n as getRequiredForms, t as addValidityToForms } from "./dropinUtils-IdasFZCU.js";
import { t as trackNavigation } from "./trackNavigation-LvCP5Vyc.js";
import { n as summaryStep } from "./Summary-B5IkOGJV.js";
import { t as useMultiForm } from "./useMultiForm-B3e1ImN3.js";
import { a as useScenarioConfiguration, o as useUnifyLoadingStatus } from "./mapExistingFile-wp3Nf1-m.js";
import { t as useTaskLandedEvent } from "./useTaskLandedEvent-DInxWeqN.js";
import { a as mapCreateOrUpdateTransferInstrumentErrorMessageToTranslatable, i as isValidationError, o as processValidationErrors, r as isIdDocumentUploadError, s as isMaintenanceModeError, t as isBankStatementUploadError } from "./validationError-BzQCrJPn.js";
import { n as fileValidationRules, s as documentApiUtils, t as defaultFileValidationOptions, u as getFileExtention } from "./validate-DDKy88ac.js";
import { t as omitObscuredFieldsIfUnchanged } from "./omitObscuredFieldsIfUnchanged-Cx1OCZuB.js";
import { t as resolveFieldMetadata } from "./fieldConfigurations-m7oWP1DZ.js";
import { t as LandingLayout } from "./LandingLayout-z8j2xiqg.js";
import { A as MemoizedBankDocumentClassification, B as useCreateTrustedTransferInstrument, C as defaultFieldMetadata$3, D as InstantVerificationErrorContext, E as BankVerification, F as mapPayoutAccountSchemaToApiBankAccount, H as useBankVerificationProviders, I as useAsyncAccountDetailsValidationRules, L as getAccountFormatsForCountry, M as resetPayoutSignals, N as showInstantVerificationPayoutModal, O as useInstantVerificationErrorNotification, P as getAccountIdentificationFromPayoutAccountSchema, R as useUpdateTrustedTransferInstrument, S as defaultFieldConfig$3, T as defaultFieldMetadata$1, U as useCheck, V as createTransferInstrument, _ as swiftCodeFieldMetadata, a as getAppropriatePayoutDetailsSteps, b as defaultFieldConfig, c as mapPayoutDetailsToTransferInstrument, d as payoutSteps, f as PayoutVerificationMethod, g as PayoutAccount, h as PayoutRequirementsModal, i as getPayoutVerificationMethod, j as bankDocumentValidationRules, k as bankVerificationValidationRules, l as mapApiDocumentToPayoutDocuments, m as getDefaultCurrencyForCountry, n as formatAccountVerificationSummary, o as parseConfiguration, p as PayoutCountryDetails, r as getInvalidFieldsErrorMessage, s as mapPayoutDocumentsToApiDocuments, t as PayoutDetailsDropin, u as rules, v as defaultFieldConfig$2, w as defaultFieldConfig$1, x as defaultFieldMetadata, y as defaultFieldMetadata$2, z as useUpdateTransferInstrument } from "./PayoutDetailsDropin-kU0l62aD.js";
import { n as useTransferInstrument, t as mapTransferInstrumentToPayoutAccount } from "./mapTransferInstrumentToPayoutAccount--CQmg2ha.js";
import { t as currencyByCountry } from "./types-qnPNJzLh.js";
import { lazy } from "preact/compat";
import { useCallback as useCallback$1, useEffect as useEffect$1, useMemo as useMemo$1, useState as useState$1 } from "preact/hooks";
import { Fragment as Fragment$1, jsx, jsxs } from "preact/jsx-runtime";
import { skipToken } from "@tanstack/preact-query";
import { useParams } from "wouter-preact";
import { Show } from "@preact/signals/utils";
//#region src/components/BankAccount/forms/PayoutDetails/PayoutDetailsMultiform.tsx
var PayoutCountryDetailsFormID = payoutSteps.payoutCountryDetails.formId;
var PayoutVerificationMethodFormID = payoutSteps.payoutVerificationMethod.formId;
var PayoutAccountDetailsFormID = payoutSteps.payoutAccountDetails.formId;
var PayoutAccountDocumentsFormID = payoutSteps.payoutAccountDocuments.formId;
var PayoutAccountVerificationFormID = payoutSteps.payoutAccountVerification.formId;
function PayoutDetailsMultiform({ activeForm, shouldValidate, problems = {}, country, accountHolder, legalEntityResponse, provider, bankVendorsLoadingStatus, instantVerificationAvailable, setHideSidebar, createTrustedTransferInstrument, accountDetailsFromInput, onBack, setHasAsyncValidationError, showInstantVerificationCTA }) {
const { t } = useTranslation("banking");
const { t: commonT } = useTranslation("common");
const { form } = useFormContext();
const { isFeatureEnabled } = useToggleContext();
const { isSettingEnabled } = useSettingsContext();
const isCrossBorderPayoutsEnabled = isFeatureEnabled(FeatureNames.EnableCrossBorderPayouts) && isSettingEnabled(SettingNames.AllowCrossBorderPayout);
const [instantVerificationError, setInstantVerificationError] = useInstantVerificationErrorNotification(1e4);
const bankCountry = (isCrossBorderPayoutsEnabled ? form.data?.payoutCountryDetails?.bankCountry : form.data?.payoutVerificationMethod?.bankCountry) ?? country;
const [bankInfoValidated, setBankInfoValidated] = useState$1(false);
const [arePayoutAccountDetailsInvalid, setArePayoutAccountDetailsInvalid] = useState$1(false);
const [invalidFieldNames, setInvalidFieldNames] = useState$1("");
const payload = useMemo$1(() => bankCountry && accountDetailsFromInput ? getAccountIdentificationFromPayoutAccountSchema(accountDetailsFromInput, bankCountry, isCrossBorderPayoutsEnabled) : {}, [
accountDetailsFromInput,
bankCountry,
isCrossBorderPayoutsEnabled
]);
const validateAccountDetails = useAsyncAccountDetailsValidationRules(payload, hasEmptyFields(payload), isAccountIdentifierObscured(payload));
const resetInvalidFieldState = () => {
setInvalidFieldNames("");
setArePayoutAccountDetailsInvalid(false);
};
useEffect$1(() => {
if (validateAccountDetails?.invalidFields && validateAccountDetails.invalidFields.length > 0) {
setHasAsyncValidationError?.(true);
setInvalidFieldNames(concatenateFieldNames(validateAccountDetails.invalidFields.map((field) => extractFieldName(field.name)).map((key) => commonT(($) => $[key]))));
setArePayoutAccountDetailsInvalid(true);
} else {
setHasAsyncValidationError?.(false);
resetInvalidFieldState();
}
}, [
commonT,
validateAccountDetails,
setHasAsyncValidationError
]);
const renderActiveForm = (activeForm) => {
switch (activeForm.formId) {
case PayoutCountryDetailsFormID: return /* @__PURE__ */ jsx(PayoutCountryDetails, {
id: activeForm.formId,
legalEntityResponse,
provider,
shouldValidate,
fieldValidationErrors: problems.validationErrors?.[activeForm.formId] ?? {},
formVerificationErrors: problems.verificationErrors?.[activeForm.formId] ?? {},
data: form.data.payoutCountryDetails,
errors: form.errors.payoutCountryDetails,
valid: form.valid.payoutCountryDetails,
allFields: form.allFields?.payoutCountryDetails,
requiredFields: form.requiredFields?.payoutCountryDetails,
optionalFields: form.optionalFields?.payoutCountryDetails,
trustedFields: form.trustedFields?.payoutCountryDetails,
handleFieldChange: (fieldName, mode) => form.handleChangeFor(fieldName, "payoutCountryDetails", mode)
});
case PayoutVerificationMethodFormID: return /* @__PURE__ */ jsx(InstantVerificationErrorContext.Provider, {
value: instantVerificationError,
children: /* @__PURE__ */ jsx(PayoutVerificationMethod, {
id: activeForm.formId,
heading: t(($) => $["addABankAccountForPayouts"]),
country,
accountHolder,
legalEntityResponse,
provider,
bankVendorsLoadingStatus,
bankInfoValidated,
instantVerificationAvailable,
shouldValidate,
fieldValidationErrors: problems.validationErrors?.[activeForm.formId] ?? {},
formVerificationErrors: problems.verificationErrors?.[activeForm.formId] ?? {},
data: form.data.payoutVerificationMethod,
errors: form.errors.payoutVerificationMethod,
valid: form.valid.payoutVerificationMethod,
allFields: form.allFields?.payoutVerificationMethod,
requiredFields: form.requiredFields?.payoutVerificationMethod,
optionalFields: form.optionalFields?.payoutVerificationMethod,
trustedFields: form.trustedFields?.payoutVerificationMethod,
handleFieldChange: (fieldName, mode) => form.handleChangeFor(fieldName, "payoutVerificationMethod", mode)
})
});
case PayoutAccountDetailsFormID: return /* @__PURE__ */ jsx(InstantVerificationErrorContext.Provider, {
value: instantVerificationError,
children: /* @__PURE__ */ jsx(PayoutAccount, {
id: activeForm.formId,
heading: t(($) => $["addABankAccountForPayouts"]),
country: bankCountry,
legalEntityResponse,
arePayoutAccountDetailsInvalid,
invalidFieldNames,
preferredCurrencyCode: form.data?.payoutCountryDetails?.preferredCurrency,
shouldValidate,
fieldValidationErrors: problems.validationErrors?.[activeForm.formId] ?? {},
formVerificationErrors: problems.verificationErrors?.[activeForm.formId] ?? {},
data: form.data.payoutAccountDetails,
errors: form.errors.payoutAccountDetails,
valid: form.valid.payoutAccountDetails,
allFields: form.allFields?.payoutAccountDetails,
requiredFields: form.requiredFields?.payoutAccountDetails,
optionalFields: form.optionalFields?.payoutAccountDetails,
trustedFields: form.trustedFields?.payoutAccountDetails,
obscuredFields: form.obscuredFields?.payoutAccountDetails,
handleFieldChange: (fieldName, mode) => form.handleChangeFor(fieldName, "payoutAccountDetails", mode),
showInstantVerificationCTA,
provider
})
});
case PayoutAccountDocumentsFormID: return /* @__PURE__ */ jsx(MemoizedBankDocumentClassification, {
id: activeForm.formId,
legalEntity: legalEntityResponse,
country: bankCountry,
shouldValidate,
fieldValidationErrors: problems.validationErrors?.[activeForm.formId] ?? {},
formVerificationErrors: problems.verificationErrors?.[activeForm.formId] ?? {},
data: form.data.payoutAccountDocuments,
errors: form.errors.payoutAccountDocuments,
valid: form.valid.payoutAccountDocuments,
allFields: form.allFields?.payoutAccountDocuments,
requiredFields: form.requiredFields?.payoutAccountDocuments,
optionalFields: form.optionalFields?.payoutAccountDocuments,
trustedFields: form.trustedFields?.payoutAccountDocuments,
handleFieldChange: (fieldName, mode) => form.handleChangeFor(fieldName, "payoutAccountDocuments", mode)
});
default: return null;
}
};
return /* @__PURE__ */ jsxs("div", {
className: "adyen-kyc-payout",
children: [/* @__PURE__ */ jsx("div", {
className: "adyen-kyc-form-wrapper",
children: renderActiveForm(activeForm)
}), /* @__PURE__ */ jsx(Show, {
when: showInstantVerificationPayoutModal,
children: /* @__PURE__ */ jsx(BankVerification, {
id: PayoutAccountVerificationFormID,
heading: t(($) => $["bankAccountVerification"]),
provider,
country: bankCountry,
onBack,
hideSidebar: setHideSidebar,
setBankVerificationError: setInstantVerificationError,
bankInfoValidated,
setBankInfoValidated,
formIsActive: activeForm.formId === PayoutVerificationMethodFormID,
createTrustedTransferInstrument,
shouldValidate,
fieldValidationErrors: problems.validationErrors?.[PayoutAccountVerificationFormID] ?? {},
formVerificationErrors: problems.verificationErrors?.[PayoutAccountVerificationFormID] ?? {},
data: form.data.payoutAccountVerification,
errors: form.errors.payoutAccountVerification,
valid: form.valid.payoutAccountVerification,
allFields: form.allFields?.payoutAccountVerification,
requiredFields: form.requiredFields?.payoutAccountVerification,
optionalFields: form.optionalFields?.payoutAccountVerification,
trustedFields: form.trustedFields?.payoutAccountVerification,
handleFieldChange: (fieldName, mode) => form.handleChangeFor(fieldName, "payoutAccountVerification", mode)
})
})]
});
}
var PayoutDetailsGettingStarted_module_default = {
"payout-details-getting-started": "adyen-kyc-payout-details-getting-started",
payoutDetailsGettingStarted: "adyen-kyc-payout-details-getting-started"
};
//#endregion
//#region src/components/BankAccount/tasks/PayoutDetailsGettingStarted/PayoutDetailsGettingStarted.tsx
var payoutBankAccountsImage = lazy(() => import("./payout-bank-accounts-CF8erfdR.js"));
var PayoutDetailsGettingStarted = ({ onGetStarted, onFinishLater, provider }) => {
const [isRequirementsModalOpen, setIsRequirementsModalOpen] = useState$1(false);
const { t } = useTranslation("banking");
const { t: commonT } = useTranslation("common");
return /* @__PURE__ */ jsxs("div", {
className: PayoutDetailsGettingStarted_module_default.payoutDetailsGettingStarted,
"data-testid": "payout-details-getting-started",
children: [/* @__PURE__ */ jsx(LandingLayout, {
title: commonT(($) => $["payoutBankAccounts"]),
description: /* @__PURE__ */ jsx(Trans, {
t,
ns: "banking",
i18nKey: ($) => $["linkAndVerifyNewBankAccountForPayouts"],
components: { requirementsLink: /* @__PURE__ */ jsx(Button, {
variant: "link",
onClick: () => setIsRequirementsModalOpen(true),
children: t(($) => $["bankAccountRequirements"])
}) }
}),
media: /* @__PURE__ */ jsx(Image, { lazyLoadedImage: payoutBankAccountsImage }),
actions: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button, {
fullWidth: true,
onClick: onGetStarted,
children: commonT(($) => $["getStarted"])
}), /* @__PURE__ */ jsx(Button, {
fullWidth: true,
variant: "tertiary",
onClick: onFinishLater,
children: commonT(($) => $["finishLater"])
})] })
}), /* @__PURE__ */ jsx(PayoutRequirementsModal, {
isOpen: isRequirementsModalOpen,
onClose: () => setIsRequirementsModalOpen(false),
provider
})]
});
};
//#endregion
//#region src/components/BankAccount/tasks/PayoutDetailsDropin/validate.ts
function payoutCountryDetailsValidators() {
return {};
}
function payoutVerificationMethodValidators() {
return { payoutVerificationMethod: {
modes: ["blur"],
validate: (payoutVerificationMethod) => !!payoutVerificationMethod
} };
}
function payoutAccountDetailsValidators({ country }) {
const branchCodeMetadata = resolveFieldMetadata(defaultFieldConfig[country], {}, defaultFieldMetadata);
const bankAccountNumberMetadata = resolveFieldMetadata(defaultFieldConfig$1[country], {}, defaultFieldMetadata$1);
const ibanMetadata = resolveFieldMetadata(defaultFieldConfig$2[country], {}, defaultFieldMetadata$2);
const bankCodeMetadata = resolveFieldMetadata(defaultFieldConfig$3[country], {}, defaultFieldMetadata$3);
return {
branchCode: branchCodeMetadata.validators,
bankAccountNumber: bankAccountNumberMetadata.validators,
iban: ibanMetadata.validators,
swiftCode: swiftCodeFieldMetadata.validators,
bankCode: bankCodeMetadata.validators
};
}
function payoutAccountDocumentsValidators() {
return {
...bankDocumentValidationRules,
bankStatementDocument: fileValidationRules(defaultFileValidationOptions)
};
}
function payoutAccountVerificationValidators() {
return bankVerificationValidationRules;
}
//#endregion
//#region src/components/BankAccount/tasks/PayoutDetailsDropin/PayoutDetailsDropinMultiForm.tsx
function PayoutDetailsDropinMultiForm({ legalEntityResponse, problems: propProblems, onSubmit: externalOnSubmit, asModal = false, handleCloseClick, taskType: propTaskType, handleHomeClick, currentTransferInstrumentId, navigateBackToTaskList, handleBackClick: externalBackClick, openBankingPartnerConfigId }) {
const { baseUrl, rootLegalEntityId } = useApiContext();
const { data: transferInstrument, refetch: refetchTransferInstrument, isLoading: isTransferInstrumentLoading } = useTransferInstrument(currentTransferInstrumentId ?? skipToken);
const { mutateAsync: handleUpdateTransferInstrument } = useUpdateTransferInstrument();
const { mutateAsync: handleUpdateTrustedTransferInstrument } = useUpdateTrustedTransferInstrument();
const { mutateAsync: handleCreateTrustedTransferInstrument, status: createTrustedTransferInstrumentStatus } = useCreateTrustedTransferInstrument();
const [previousTrustedInstrumentStatus, setPreviousTrustedInstrumentStatus] = useState$1(createTrustedTransferInstrumentStatus);
const { t, i18n: i18next } = useTranslation("banking");
const { t: commonT } = useTranslation("common");
const userEvents = useAnalyticsContext();
const { showToast, clearToasts } = useToastContext();
const { isFeatureEnabled } = useToggleContext();
const { isSettingEnabled } = useSettingsContext();
const { isExperimentEnabled } = useToggleContext();
const enabledCrossBorderPayouts = isFeatureEnabled(FeatureNames.EnableCrossBorderPayouts) && isSettingEnabled(SettingNames.AllowCrossBorderPayout);
const isForcedManualPayoutFlowEnabled = isExperimentEnabled(ExperimentNames.BankingPayoutFlow_ForcedManualVerification) && !isSettingEnabled(SettingNames.AllowIntraRegionCrossBorderPayout);
const defaultPayoutCountry = getLegalEntityCountry(legalEntityResponse);
const existingPayoutDetails = useMemo$1(() => transferInstrument ? mapTransferInstrumentToPayoutAccount(transferInstrument, enabledCrossBorderPayouts) : void 0, [transferInstrument, enabledCrossBorderPayouts]);
const [documents, setDocuments] = useState$1();
const [isCaasCalled, setIsCaasCalled] = useState$1(false);
const accountHolder = getPayoutAccountHolderName(legalEntityResponse, t);
const fallbackCurrency = currencyByCountry[defaultPayoutCountry]?.[0];
const accountHolderName = accountHolder || getLegalEntityNameBasedOnType(legalEntityResponse);
const instantVerificationEnabled = Boolean(!isTransferInstrumentLoading && !transferInstrument && isSettingEnabled("instantBankVerification"));
const taskType = propTaskType ?? TaskTypes.PAYOUT;
const [trustedTransferInstrumentId, setTrustedTransferInstrumentId] = useState$1();
const prefilledData = useMemo$1(() => ({
payoutCountryDetails: {
bankCountry: existingPayoutDetails?.payoutCountryDetails?.bankCountry ?? defaultPayoutCountry,
preferredCurrency: existingPayoutDetails?.payoutCountryDetails?.preferredCurrency ?? getDefaultCurrencyForCountry(defaultPayoutCountry)
},
payoutAccountDetails: {
accountHolder: accountHolderName,
currency: fallbackCurrency,
...existingPayoutDetails?.payoutAccountDetails
},
payoutVerificationMethod: {
payoutVerificationMethod: getPayoutVerificationMethod(transferInstrument, instantVerificationEnabled),
bankCountry: defaultPayoutCountry,
...existingPayoutDetails?.payoutVerificationMethod
},
payoutAccountVerification: {
verifiedAccountHolder: accountHolderName,
verifiedBankCountry: defaultPayoutCountry,
...existingPayoutDetails?.payoutAccountVerification
}
}), [
existingPayoutDetails,
defaultPayoutCountry,
accountHolderName,
fallbackCurrency,
instantVerificationEnabled,
transferInstrument
]);
const documentUtils = documentApiUtils({
baseUrl: baseUrl.value,
rootLegalEntityId: rootLegalEntityId.value
});
const [hasStarted, setHasStarted] = useState$1(false);
const [skipSubmit, setSkipSubmit] = useState$1(false);
const [loadingStatus, setLoadingStatus] = useState$1("loading");
const [isSubmitting, setIsSubmitting] = useState$1(false);
const [configurationLoadingStatus, setConfigurationLoadingStatus] = useState$1("loading");
const [accountDetailsFromInput, setAccountDetailsFromInput] = useState$1(prefilledData.payoutAccountDetails);
const [derivedProps, setDerivedProps] = useState$1();
const [initialBankAccountCountry] = useState$1(defaultPayoutCountry);
const [problems, setProblems] = useState$1(propProblems);
const [hasAsyncValidationError, setHasAsyncValidationError] = useState$1(false);
const buildFieldValidations = useCallback$1((data) => {
const country = (enabledCrossBorderPayouts ? data?.payoutCountryDetails?.bankCountry : data?.payoutVerificationMethod?.bankCountry) ?? defaultPayoutCountry;
return {
payoutCountryDetails: payoutCountryDetailsValidators(),
payoutVerificationMethod: payoutVerificationMethodValidators(),
payoutAccountDetails: payoutAccountDetailsValidators({ country }),
payoutAccountDocuments: payoutAccountDocumentsValidators(),
payoutAccountVerification: payoutAccountVerificationValidators()
};
}, [enabledCrossBorderPayouts, defaultPayoutCountry]);
const multiForm = useMultiForm({
defaultData: useMemo$1(() => {
return {
...prefilledData,
payoutAccountDocuments: documents
};
}, [prefilledData, documents]),
allFields: derivedProps?.allFields,
requiredFields: derivedProps?.requiredFields,
optionalFields: derivedProps?.optionalFields,
obscuredFields: derivedProps?.obscuredFields,
trustedFields: derivedProps?.trustedFields,
rules: buildFieldValidations
});
const bankAccountCountry = (enabledCrossBorderPayouts ? multiForm.data?.payoutCountryDetails?.bankCountry : multiForm.data?.payoutVerificationMethod?.bankCountry) ?? initialBankAccountCountry;
const isMaskedBankAccountNumber = multiForm.data.payoutAccountDetails?.bankAccountNumber?.includes("*") || multiForm.data.payoutAccountDetails?.iban?.includes("*");
const existingBankAccountFormat = transferInstrument ? transferInstrument?.bankAccount?.accountIdentification?.type === "numberAndBic" ? "numberAndBic" : existingPayoutDetails?.payoutAccountDetails?.iban ? "iban" : "local" : void 0;
/**
* Analytics
*/
useTaskLandedEvent(taskType);
useEffect$1(() => {
resetPayoutSignals();
}, []);
const { data: providers, refetch: refetchBankVerificationProviders, status: bankVendorsLoadingStatus } = useBankVerificationProviders({
country: bankAccountCountry,
configId: openBankingPartnerConfigId,
locale: i18next.language
}, { enabled: instantVerificationEnabled });
/**
* instantVerificationEnabled = conditions are met to show the option for instant verification
* instantVerificationAvailable = instantVerificationEnabled AND there is a provider returned for the bank account country
*/
const instantVerificationAvailable = useMemo$1(() => Boolean(instantVerificationEnabled && providers?.[0]?.redirectUrl), [instantVerificationEnabled, providers]);
const getPayoutAccountFormatData = useCallback$1(async () => getAccountFormatsForCountry(bankAccountCountry), [bankAccountCountry]);
/**
* Fetch Configurations
*/
const { fieldConfigurations, requiredFields } = useScenarioConfiguration({
parseConfiguration,
legalEntityType: legalEntityResponse.type,
getPayoutAccountFormatData,
instantVerificationAvailable,
setLoadingStatus: setConfigurationLoadingStatus,
country: bankAccountCountry,
existingBankAccountFormat
});
/**
* parse configuration and create component props
*/
const fieldsFromCustomRules = useMemo$1(() => rules({
data: multiForm.data,
country: bankAccountCountry,
taskType,
isFeatureEnabled,
isSettingEnabled,
isExperimentEnabled
}), [
multiForm.data,
bankAccountCountry,
taskType,
requiredFields,
isFeatureEnabled,
isSettingEnabled
]);
const { data: checkAsAServiceData, refetch: refetchCheckAsAService, isLoading: isCheckAsAServiceLoading, isError: isCheckAsAServiceError } = useCheck(useMemo$1(() => {
return mapPayoutAccountSchemaToApiBankAccount(multiForm.data.payoutAccountDetails ?? { bankAccountNumber: "" }, bankAccountCountry);
}, [multiForm.data, bankAccountCountry]).accountIdentification, { enabled: false });
const checkAsAServiceResultStatus = checkAsAServiceData?.status;
const checkAsAServiceResultErrors = checkAsAServiceData?.errors;
const provider = providers?.[0];
const isInstantVerificationFlow = multiForm.data.payoutVerificationMethod?.payoutVerificationMethod === "instantVerification";
const [isModalOpen, setIsModalOpen] = useState$1(false);
const showInstantVerificationCTA = !currentTransferInstrumentId && instantVerificationAvailable && isExperimentEnabled(ExperimentNames.BankingPayoutFlow_ForcedManualVerification) && !!provider && (bankAccountCountry !== "GB" || !isSettingEnabled(SettingNames.AllowIntraRegionCrossBorderPayout));
const payoutDetailsSteps = useMemo$1(() => {
const appropriatePayoutDetailsSteps = getAppropriatePayoutDetailsSteps(Boolean(prefilledData?.payoutAccountDetails?.transferInstrumentId), instantVerificationAvailable, isSettingEnabled(SettingNames.AllowIntraRegionCrossBorderPayout), enabledCrossBorderPayouts, isForcedManualPayoutFlowEnabled);
if (!isCheckAsAServiceError && checkAsAServiceResultStatus === "VALID" && !isMaskedBankAccountNumber) delete appropriatePayoutDetailsSteps[payoutSteps.payoutAccountDocuments.formId];
return appropriatePayoutDetailsSteps;
}, [
providers,
checkAsAServiceResultStatus,
isCheckAsAServiceError,
isMaskedBankAccountNumber
]);
useEffect$1(() => {
setDerivedProps(getPropsFromConfigurations({
scenarioConfiguration: fieldConfigurations,
forms: payoutDetailsSteps,
remediationActions: problems?.remediationActions ? Object.values(problems?.remediationActions) : [],
dataMissingErrors: problems?.missingData ?? [],
fieldsWithExistingData: [],
customRules: fieldsFromCustomRules,
legalEntityType: legalEntityResponse.type
}));
}, [
fieldConfigurations,
payoutDetailsSteps,
problems?.remediationActions,
problems?.missingData,
fieldsFromCustomRules,
legalEntityResponse.type
]);
useUnifyLoadingStatus(setLoadingStatus, configurationLoadingStatus, instantVerificationEnabled ? bankVendorsLoadingStatus : "success", isSubmitting ? "loading" : "success");
/**
* Configure forms based on obtained props
*/
const forms = useMemo$1(() => {
return addValidityToForms(getRequiredForms(payoutDetailsSteps, derivedProps?.requiredFields, derivedProps?.optionalFields), hasAsyncValidationError ? {
...multiForm.isValid,
payoutAccountDetails: false
} : multiForm.isValid, problems);
}, [
derivedProps,
hasAsyncValidationError,
multiForm.isValid,
problems,
payoutDetailsSteps
]);
useEffect$1(() => {
if (!transferInstrument?.documentDetails?.length) return;
if (transferInstrument.id) documentUtils.fetchDocuments(transferInstrument.documentDetails, transferInstrument.id).then(() => {
const documents = mapApiDocumentToPayoutDocuments(transferInstrument.id);
setDocuments(documents);
multiForm.handleChangeFor("bankStatementDocument", "payoutAccountDocuments")(documents.bankStatementDocument);
multiForm.handleChangeFor("description", "payoutAccountDocuments")(documents.description);
}).catch(() => {
showToast({
label: commonT(($) => $["failedToFetchRelevantDocuments"]),
variant: "error"
});
});
}, [transferInstrument?.documentDetails]);
const submitDocuments = async ({ forms, transferInstrument, dataSubmitted }) => {
if (forms.some((form) => form.formId === payoutSteps.payoutAccountDocuments.formId)) {
const documentToUpload = await mapPayoutDocumentsToApiDocuments(dataSubmitted, transferInstrument.id);
if (documentToUpload) try {
(await documentUtils.uploadDocuments([documentToUpload], transferInstrument.id)).forEach((document) => {
userEvents.addTaskEvent("Success", {
actionType: "upload",
documentType: dataSubmitted.payoutAccountDocuments?.documentType ?? document.type,
fileExtention: document.attachments?.map((item) => getFileExtention(item.pageName ?? "")).filter((item) => item !== void 0) ?? void 0
});
});
} catch {
setProblems({
...problems,
validationErrors: { payoutAccountDocuments: { bankStatementDocument: true } }
});
throw new Error(commonT(($) => $["remediationMessage_1_704"]));
} finally {
if (currentTransferInstrumentId) await refetchTransferInstrument?.();
}
}
};
useEffect$1(() => {
const payoutAccountData = cloneObject(multiForm.data)?.payoutAccountDetails;
if (payoutAccountData) setAccountDetailsFromInput(payoutAccountData);
}, [multiForm.data]);
const onSubmit = async () => {
setIsSubmitting(true);
const dataSubmitted = cloneObject({
...prefilledData,
...multiForm.data
});
const { payoutAccountDetails, payoutVerificationMethod } = dataSubmitted;
const baseTracking = {
actionType: "submit",
documentType: "bankStatement",
bankCountry: payoutVerificationMethod?.bankCountry ?? defaultPayoutCountry,
bankCurrency: payoutAccountDetails?.currency ?? null
};
let transferInstrumentFromInput = mapPayoutDetailsToTransferInstrument({
data: dataSubmitted,
legalEntity: legalEntityResponse,
enabledCrossBorderPayouts
});
transferInstrumentFromInput = omitObscuredFieldsIfUnchanged(["bankAccount.accountIdentification.accountNumber", "bankAccount.accountIdentification.iban"], transferInstrumentFromInput, transferInstrument);
try {
if (!transferInstrumentFromInput) return;
const response = await (transferInstrument ? handleUpdateTransferInstrument({
transferInstrument: transferInstrumentFromInput,
transferInstrumentId: transferInstrument.id
}) : createTransferInstrument(rootLegalEntityId.value, baseUrl.value, transferInstrumentFromInput));
userEvents.addTaskEvent("Success", { ...baseTracking });
try {
await submitDocuments({
forms,
transferInstrument: response,
dataSubmitted
});
clearToasts();
externalOnSubmit?.({
...dataSubmitted,
id: response?.id
});
} catch (e) {
showToast({
label: e.message,
variant: "error"
});
userEvents.addTaskEvent("Encountered error", {
...baseTracking,
returnType: e?.errorCode || "backend",
returnValue: e?.title || e?.message
});
} finally {
setIsSubmitting(false);
}
} catch (e) {
if (isValidationError(e)) {
const validationErrors = processValidationErrors(e, taskType);
setProblems({
...problems,
validationErrors
});
} else if (isIdDocumentUploadError(e)) showToast({
label: t(($) => $["idDocumentAlreadyUploaded"]),
variant: "error"
});
else if (isBankStatementUploadError(e)) showToast({
label: t(($) => $["bankStatementAlreadyUploaded"]),
variant: "error"
});
else if (isMaintenanceModeError(e)) showToast({
label: commonT(($) => $["maintenanceModeMessage"]),
variant: "error",
duration: "indefinite"
});
else {
const errorTranslatable = mapCreateOrUpdateTransferInstrumentErrorMessageToTranslatable(e);
showToast({
label: commonT(($) => $[errorTranslatable]),
variant: "error"
});
}
setIsSubmitting(false);
userEvents.addTaskEvent("Encountered error", {
...baseTracking,
returnType: e?.errorCode || "backend",
returnValue: e?.title || e?.message
});
}
};
const formatFileSummaryData = (bankDocuments) => {
const bankStatementDocument = bankDocuments?.bankStatementDocument?.[0];
return {
documentType: bankDocuments?.documentType && commonT(($) => $[bankDocuments?.documentType]),
fileName: bankStatementDocument?.name,
description: bankDocuments?.description
};
};
const datasetUtils = datasetUtilities(i18next.language);
const formatDataForSummary = () => {
const summaryData = cloneObject(multiForm.data);
if (summaryData.payoutAccountDetails) summaryData.payoutAccountDetails.accountHolder = accountHolderName;
if (summaryData.payoutVerificationMethod?.bankCountry && summaryData.payoutAccountDetails) summaryData.payoutAccountDetails.bankCountry = datasetUtils.getCountryName(summaryData.payoutVerificationMethod.bankCountry);
if (summaryData.payoutAccountDocuments) summaryData.payoutAccountDocuments = formatFileSummaryData(multiForm.data?.payoutAccountDocuments);
summaryData.payoutAccountVerification = formatAccountVerificationSummary(multiForm.data.payoutAccountVerification);
return summaryData;
};
const createTrustedTransferInstrumentHandler = async (code, state) => {
try {
const trustedTransferInstrument = await handleCreateTrustedTransferInstrument({
code,
state
});
if (trustedTransferInstrument) {
setTrustedTransferInstrumentId(trustedTransferInstrument.verificationReference);
multiForm.setFormData("payoutAccountDetails", prefilledData.payoutAccountDetails);
return trustedTransferInstrument;
}
} catch (e) {
refetchBankVerificationProviders();
const errorTranslatable = mapCreateOrUpdateTransferInstrumentErrorMessageToTranslatable(e);
if (errorTranslatable === "transferInstrumentLimitHasAlreadyBeenMet") showToast({
label: commonT(($) => $[errorTranslatable]),
variant: "error"
});
throw e;
}
};
const { handleNextClick, handleBackClick, activeForm, shouldValidate, gotoFormByFormIndex, gotoFormByFormId, steps } = useFormComposer({
problems,
forms,
externalBackClick,
triggerValidation: async (formName) => {
if (!multiForm.requiredFields?.[formName]) return true;
return multiForm.triggerValidation(formName);
},
onSubmit: skipSubmit ? async () => {
if (enabledCrossBorderPayouts && trustedTransferInstrumentId && multiForm.data.payoutCountryDetails?.preferredCurrency) try {
await handleUpdateTrustedTransferInstrument({
transferInstrumentId: trustedTransferInstrumentId,
preferredCurrencyCode: multiForm.data.payoutCountryDetails?.preferredCurrency
});
} catch {
showToast({
label: commonT(($) => $["failedToUpdateDetails"]),
variant: "error"
});
}
if (trustedTransferInstrumentId) externalOnSubmit?.({
...multiForm.data,
id: trustedTransferInstrumentId
});
userEvents.addTaskEvent("Success", { actionType: "submit" });
navigateBackToTaskList?.();
} : onSubmit
});
useEffect$1(() => {
if (activeForm?.formId === summaryStep.formId && isInstantVerificationFlow && trustedTransferInstrumentId) setSkipSubmit?.(true);
}, [
activeForm?.formId,
trustedTransferInstrumentId,
isInstantVerificationFlow,
setSkipSubmit
]);
useEffect$1(() => {
if (!isCaasCalled || !forms) return;
setIsCaasCalled(false);
if (checkAsAServiceResultStatus !== "VALID" && checkAsAServiceResultStatus !== "INCOMPLETE_INPUT") {
const formIndex = forms.findIndex((f) => f.formId === "payoutAccountDocuments");
if (formIndex > -1) gotoFormByFormIndex(formIndex);
}
if (checkAsAServiceResultStatus === "VALID") handleNextClick();
}, [
forms,
checkAsAServiceResultStatus,
isCaasCalled
]);
const handleFormNextClick = async () => {
if (activeForm.formId === "payoutVerificationMethod") if (isInstantVerificationFlow) {
trackNavigation({
userEvents,
actionType: "next",
label: "instantVerification",
toForm: "instantVerification"
});
showInstantVerificationPayoutModal.value = true;
return;
} else {
handleNextClick();
return;
}
if (activeForm.formId === "payoutAccountDetails" && activeForm.isValid && multiForm.data.payoutAccountDetails && !isMaskedBankAccountNumber) try {
const { data: response } = await refetchCheckAsAService();
setIsCaasCalled(true);
if (response?.status === "INCOMPLETE_INPUT") setIsModalOpen(true);
} catch {
handleNextClick();
}
else handleNextClick();
};
if (previousTrustedInstrumentStatus !== createTrustedTransferInstrumentStatus) {
if (activeForm.formId === "payoutAccountVerification" && activeForm.isValid && createTrustedTransferInstrumentStatus === "success" && multiForm.data.payoutAccountVerification?.verifiedBankAccountNumber) {
handleNextClick();
setPreviousTrustedInstrumentStatus(createTrustedTransferInstrumentStatus);
}
if ((activeForm.formId === "payoutVerificationMethod" || isForcedManualPayoutFlowEnabled && activeForm.formId === "payoutAccountDetails") && createTrustedTransferInstrumentStatus === "success") {
gotoFormByFormIndex(forms.length - 1);
setPreviousTrustedInstrumentStatus(createTrustedTransferInstrumentStatus);
}
}
const omittedForms = multiForm.data?.payoutVerificationMethod?.payoutVerificationMethod === "instantVerification" ? [] : [payoutSteps.payoutVerificationMethod.formId];
const { header: invalidFieldHeader, content: invalidFieldContent } = getInvalidFieldsErrorMessage(checkAsAServiceResultErrors ?? []);
if (isFeatureEnabled(FeatureNames.EnableBankAccountDetailsLandingPage) && !hasStarted && !legalEntityResponse.transferInstruments?.length) return /* @__PURE__ */ jsx(PayoutDetailsGettingStarted, {
onGetStarted: () => setHasStarted(true),
onFinishLater: () => navigateBackToTaskList?.(),
provider
});
return /* @__PURE__ */ jsxs(LoaderWrapper, {
showSpinner: true,
status: isCheckAsAServiceLoading || isModalOpen || createTrustedTransferInstrumentStatus === "pending" ? "loading" : "success",
formOpacityWhenLoading: .3,
children: [isModalOpen && /* @__PURE__ */ jsx(Confirm, {
title: t(($) => $[invalidFieldHeader]),
description: t(($) => $[invalidFieldContent]),
cancelText: commonT(($) => $["editDetails"]),
confirmText: t(($) => $["continueAnyway"]),
onConfirm: () => {
handleNextClick();
setIsModalOpen(false);
},
onCancel: () => {
gotoFormByFormIndex(0);
setIsModalOpen(false);
}
}), /* @__PURE__ */ jsx(FormContextProvider, {
form: multiForm,
children: /* @__PURE__ */ jsx(FormFlow, {
summary: {
data: formatDataForSummary(),
omitted: {
keys: ["transferInstrumentId", "payoutVerificationMethod"],
forms: omittedForms,
summaryEditButton: ["payoutVerificationMethod", "payoutAccountVerification"]
},
problems
},
asModal,
currentStep: steps.current,
totalSteps: steps.total,
forms,
activeForm,
gotoFormByFormIndex,
gotoFormByFormId,
handleNextClick: handleFormNextClick,
handleBackClick: activeForm.formId !== "summary" ? handleBackClick : void 0,
handleCancelClick: handleCloseClick || handleHomeClick,
loadingStatus: isTransferInstrumentLoading ? "loading" : loadingStatus,
children: (!isTransferInstrumentLoading || isSubmitting) && /* @__PURE__ */ jsx(PayoutDetailsMultiform, {
activeForm,
shouldValidate,
problems,
country: defaultPayoutCountry,
accountHolder: accountHolder ?? getLegalEntityNameBasedOnType(legalEntityResponse),
legalEntityResponse,
provider,
bankVendorsLoadingStatus,
instantVerificationAvailable,
createTrustedTransferInstrument: createTrustedTransferInstrumentHandler,
accountDetailsFromInput,
trustedTransferInstrumentId,
onBack: handleBackClick,
setHasAsyncValidationError,
showInstantVerificationCTA
})
})
})]
});
}
//#endregion
//#region src/components/BankAccount/pages/PayoutDetailsPage.tsx
function PayoutDetailsPage({ transferInstrumentId: transferInstrumentIdProp, setTransferInstrumentId: setTransferInstrumentIdProp, taskType, openBankingPartnerConfigId, onSubmit, handleHomeClick }) {
const routeParams = useParams();
const navigate = useNavigate();
const transferInstrumentId = transferInstrumentIdProp ?? routeParams.transferInstrumentId;
const setTransferInstrumentId = setTransferInstrumentIdProp ?? ((id) => navigate.replace(taskType, { transferInstrumentId: id }));
const { isFeatureEnabled } = useToggleContext();
const { i18n } = useTranslation();
const { data: rootLe } = useLegalEntity(ROOT_LE);
const capabilityProblems = useCapabilityProblems();
addResourceBundles(i18n, [{
ns: "banking",
importFn: (lang) => _rolldown_dynamic_import_helper_default(/* @__PURE__ */ Object.assign({
"../language/bg-BG.json": () => import("./bg-BG-Bayyn2Vj.js"),
"../language/cs-CZ.json": () => import("./cs-CZ-DlGWvcHs.js"),
"../language/da-DK.json": () => import("./da-DK-FIY6i3zy.js"),
"../language/de-DE.json": () => import("./de-DE-DLQs11Hz.js"),
"../language/el-GR.json": () => import("./el-GR-no-mXzHz.js"),
"../language/en-US.json": () => import("./en-US-f2kgWe84.js"),
"../language/es-ES.json": () => import("./es-ES-BUSxmdKa.js"),
"../language/et-EE.json": () => import("./et-EE-9bkSuMa4.js"),
"../language/fi-FI.json": () => import("./fi-FI-whtJ_DRy.js"),
"../language/fr-FR.json": () => import("./fr-FR-SabLrXSF.js"),
"../language/hr-HR.json": () => import("./hr-HR-C7vNP6kG.js"),
"../language/hu-HU.json": () => import("./hu-HU-DBqKyuYs.js"),
"../language/it-IT.json": () => import("./it-IT-jTdy1a4s.js"),
"../language/ja-JP.json": () => import("./ja-JP-qs4tLgRF.js"),
"../language/lt-LT.json": () => import("./lt-LT-BCqnP7r6.js"),
"../language/lv-LV.json": () => import("./lv-LV-BEtE7iP6.js"),
"../language/nl-NL.json": () => import("./nl-NL-HAKt4Uc5.js"),
"../language/no-NO.json": () => import("./no-NO-ChSdsuYY.js"),
"../language/pl-PL.json": () => import("./pl-PL-YNg08-Ol.js"),
"../language/pt-BR.json": () => import("./pt-BR-BnDcVpJT.js"),
"../language/pt-PT.json": () => import("./pt-PT-tt1J0yv6.js"),
"../language/ro-RO.json": () => import("./ro-RO-CRHBNotW.js"),
"../language/sk-SK.json": () => import("./sk-SK-BJxKfous.js"),
"../language/sl-SI.json": () => import("./sl-SI-B9zMw3uZ.js"),
"../language/sv-SE.json": () => import("./sv-SE-BgyicZrq.js")
}), `../language/${lang}.json`, 3)
}]);
if (!rootLe) return /* @__PURE__ */ jsx(Loader, {});
const problems = capabilityProblems && transferInstrumentId ? getProblemsForEntity(capabilityProblems, EntityTypes.BANK_ACCOUNT, transferInstrumentId) : void 0;
return /* @__PURE__ */ jsx(isFeatureEnabled("EnablePayoutDetailsMultiForm") ? PayoutDetailsDropinMultiForm : PayoutDetailsDropin, {
taskType,
currentTransferInstrumentId: transferInstrumentId,
setCurrentTransferInstrumentId: setTransferInstrumentId,
legalEntityResponse: rootLe,
problems,
onSubmit,
handleHomeClick,
navigateBackToTaskList: handleHomeClick,
openBankingPartnerConfigId
});
}
//#endregion
export { PayoutDetailsPage };