UNPKG

@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
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 };