diff --git a/packages/mint-components/package.json b/packages/mint-components/package.json index 4bdfc1be86..b576fb64cd 100644 --- a/packages/mint-components/package.json +++ b/packages/mint-components/package.json @@ -1,7 +1,7 @@ { "name": "@saasquatch/mint-components", "title": "Mint Components", - "version": "2.1.7", + "version": "2.2.0-4", "description": "A minimal design library with components for referral and loyalty experiences. Built with Shoelace components by Saasquatch.", "icon": "https://res.cloudinary.com/saasquatch/image/upload/v1652219900/squatch-assets/For_Mint.svg", "raisins": "docs/raisins.json", diff --git a/packages/mint-components/src/components.d.ts b/packages/mint-components/src/components.d.ts index 0916004dd4..a9d41352ec 100644 --- a/packages/mint-components/src/components.d.ts +++ b/packages/mint-components/src/components.d.ts @@ -34,6 +34,7 @@ import { NavigationMenuViewProps } from "./components/sqm-navigation-menu/sqm-na import { NavigationSidebarViewProps } from "./components/sqm-navigation-sidebar/sqm-navigation-sidebar-view"; import { NavigationSidebarItemViewProps } from "./components/sqm-navigation-sidebar-item/sqm-navigation-sidebar-item-view"; import { UsePagination } from "./components/sqm-pagination/usePagination"; +import { PartnerInfoModalResult } from "./components/sqm-partner-info-modal/usePartnerInfoModal"; import { PasswordFieldViewDemoProps } from "./components/sqm-password-field/usePasswordField"; import { PayoutButtonScrollViewProps } from "./components/sqm-payout-button-scroll/sqm-payout-button-scroll-view"; import { PayoutStatusAlertViewProps } from "./components/tax-and-cash/sqm-payout-status-alert/sqm-payout-status-alert-view"; @@ -64,6 +65,12 @@ export namespace Components { "renderLabel": (idx: any) => Promise; } interface SqmBankingInfoForm { + /** + * Error messages for the agency code field. Supports error codes: empty, alphanumeric, tooShort + * @uiName Agency code error + * @uiWidget textArea + */ + "agencyCodeError": string; /** * @uiName Agency code field label */ @@ -73,18 +80,42 @@ export namespace Components { * @uiName Back button label */ "backButton": string; + /** + * Error messages for the bank account number / IBAN field. Supports error codes: empty, invalidUk, invalid, ibanEmpty, ibanAlphanumeric, ibanInvalid, ibanCountryMismatch + * @uiName Bank account number / IBAN error + * @uiWidget textArea + */ + "bankAccountNumberError": string; /** * @uiName Bank account number field label */ "bankAccountNumberLabel": string; + /** + * Error messages for the bank account type field. Supports error codes: empty + * @uiName Bank account type error + * @uiWidget textArea + */ + "bankAccountTypeError": string; /** * @uiName Bank account type field label */ "bankAccountTypeLabel": string; + /** + * Error messages for the bank address field. Supports error codes: empty + * @uiName Bank address error + * @uiWidget textArea + */ + "bankAddressError": string; /** * @uiName Bank address field label */ "bankAddressLabel": string; + /** + * Error messages for the bank city field. Supports error codes: empty + * @uiName Bank city error + * @uiWidget textArea + */ + "bankCityError": string; /** * @uiName Bank city field label */ @@ -93,14 +124,32 @@ export namespace Components { * @uiName Bank country field label */ "bankLocationLabel": string; + /** + * Error messages for the bank name field. Supports error codes: empty + * @uiName Bank name error + * @uiWidget textArea + */ + "bankNameError": string; /** * @uiName Bank name field label */ "bankNameLabel": string; + /** + * Error messages for the bank postal code field. Supports error codes: empty + * @uiName Bank postal code error + * @uiWidget textArea + */ + "bankPostalCodeError": string; /** * @uiName Bank postal code field label */ "bankPostalCodeLabel": string; + /** + * Error messages for the bank province/state field. Supports error codes: empty + * @uiName Bank province/state error + * @uiWidget textArea + */ + "bankStateError": string; /** * @uiName Bank province/state field label */ @@ -109,14 +158,32 @@ export namespace Components { * @uiName Beneficiary account field description */ "beneficiaryAccountNameDescription": string; + /** + * Error messages for the beneficiary / account holder name field. Supports error codes: empty, invalidCharacters, numeric, tooLong, nonEnglish, businessNameMismatch, nameMismatch, businessPayeeMismatch, payeeMismatch + * @uiName Beneficiary account name error + * @uiWidget textArea + */ + "beneficiaryAccountNameError": string; /** * @uiName Beneficiary account field label */ "beneficiaryAccountNameLabel": string; + /** + * Error messages for the branch code field. Supports error codes: invalid + * @uiName Branch code error + * @uiWidget textArea + */ + "branchCodeError": string; /** * @uiName Branch code field label */ "branchCodeLabel": string; + /** + * Error messages for the branch name field. Supports error codes: empty + * @uiName Branch name error + * @uiWidget textArea + */ + "branchNameError": string; /** * One of three options listed for the classification field * @uiName Business classification option @@ -130,6 +197,12 @@ export namespace Components { * @uiName Classification CPF field label */ "classificationCPFLabel": string; + /** + * Error messages for the classification code field. Supports error codes: empty, invalidKzt + * @uiName Classification code error + * @uiWidget textArea + */ + "classificationCodeError": string; /** * @uiName Classification entity field label */ @@ -237,6 +310,12 @@ export namespace Components { * @uiName Information modal title */ "modalTitle": string; + /** + * Error messages for the patronymic name field. Supports error codes: empty, alphanumeric + * @uiName Patronymic name error + * @uiWidget textArea + */ + "patronymicNameError": string; /** * @uiName Patronymic name field label */ @@ -246,6 +325,12 @@ export namespace Components { * @uiName PayPal email field label */ "payPalInputLabel": string; + /** + * Error messages for the payment day field. Supports error codes: empty, invalid + * @uiName Payment day error + * @uiWidget textArea + */ + "paymentDayError": string; /** * Label text for the payment day select option for the fifteenth of the month * @uiName Fifteenth of month payday option @@ -281,11 +366,29 @@ export namespace Components { * @uiName Fixed day payment schedule option */ "paymentScheduleFixedDay": string; + /** + * Error messages for the payment threshold field. Supports error codes: empty, invalid + * @uiName Payment threshold error + * @uiWidget textArea + */ + "paymentThresholdError": string; /** * Participant use this field to select the balance at which they want to be paid * @uiName Payment threshold field label */ "paymentThresholdSelectLabel": string; + /** + * Error messages for the PayPal email field. Supports error codes: empty, unsupportedCurrency, invalidEmail, verificationIncomplete + * @uiName PayPal email error + * @uiWidget textArea + */ + "paypalEmailError": string; + /** + * Error messages for the routing code / sort code / BSB field. Supports error codes: invalidBsb, invalidSortCode, empty, invalid + * @uiName Routing code error + * @uiWidget textArea + */ + "routingCodeError": string; /** * @uiName Routing code field label */ @@ -303,6 +406,12 @@ export namespace Components { * @uiName Support link text */ "supportLink": string; + /** + * Error messages for the SWIFT / BIC code field. Supports error codes: empty, alphanumeric, invalid + * @uiName SWIFT code error + * @uiWidget textArea + */ + "swiftCodeError": string; /** * @uiName SWIFT code field label */ @@ -316,6 +425,12 @@ export namespace Components { * @uiName Page description */ "taxAndPayoutsDescription": string; + /** + * Error messages for the tax payer ID / classification entity field. Supports error codes: empty, emptyAr, emptyKr, alphanumeric, alphanumericAr, alphanumericKr, invalid, invalidAr, invalidKr, invalidKzt, cnpjTooShort, cpfTooShort + * @uiName Tax payer ID error + * @uiWidget textArea + */ + "taxPayerIdError": string; /** * @uiName Taxpayer ID field label */ @@ -333,6 +448,12 @@ export namespace Components { * @uiName Verify email header */ "verifyEmailHeaderText": string; + /** + * Error messages for the VO code field. Supports error codes: empty, alphanumeric + * @uiName VO code error + * @uiWidget textArea + */ + "voCodeError": string; /** * @uiName VO code field label */ @@ -2190,6 +2311,110 @@ export namespace Components { */ "paginationText": string; } + interface SqmPartnerInfoModal { + /** + * Edit the property called terms and conditions text to change what's displayed for {termsAndConditionsLink}. + * @uiName Terms and conditions checkbox + */ + "allowBankingCollection": string; + /** + * @uiName Confirm button label + */ + "confirmButtonLabel": string; + /** + * @uiName Country label + */ + "countryLabel": string; + /** + * @uiName Currency label + */ + "currencyLabel": string; + /** + * @undocumented + * @uiType object + */ + "demoData"?: DemoData; + /** + * Description for existing partner confirmation + * @uiName Existing partner description + * @uiWidget textArea + */ + "descriptionExistingPartner": string; + /** + * Description for new partner setup + * @uiName New partner description + * @uiWidget textArea + */ + "descriptionNewPartner": string; + /** + * Used to render in another modal. + * @undocumented + */ + "inModal": boolean; + /** + * @uiName Missing fields error text + * @uiWidget textArea + */ + "missingFieldsErrorText": string; + /** + * Header text when user has no existing partner + * @uiName New partner header + * @uiWidget textArea + */ + "modalHeader": string; + /** + * Header text when user has an existing partner + * @uiName Existing partner header + * @uiWidget textArea + */ + "modalHeaderExistingPartner": string; + /** + * @uiName Network error text + * @uiWidget textArea + */ + "networkErrorText": string; + /** + * @uiName Search country placeholder + */ + "searchCountryPlaceholder": string; + /** + * @uiName Search currency placeholder + */ + "searchCurrencyPlaceholder": string; + /** + * @undocumented + * @componentState { "title": "New partner", "props": { "states": { "open": true, "isExistingPartner": false } } } + * @componentState { "title": "Existing partner", "props": { "states": { "open": true, "isExistingPartner": true, "countryCode": "US", "currency": "USD" } } } + * @componentState { "title": "Connected (hidden)", "props": { "states": { "open": false } } } + */ + "stateController": string; + /** + * @uiName Submit button label + */ + "submitButtonLabel": string; + /** + * Support description for existing partner confirmation + * @uiName Existing partner support description + * @uiWidget textArea + */ + "supportDescriptionExistingPartner": string; + /** + * Support description for existing partner confirmation + * @uiName Existing partner support description + */ + "supportLink": string; + /** + * The link text that appears in the terms and conditions checkbox + * @uiName Terms and conditions text + * @uiWidget textArea + */ + "termsAndConditionsLabel": string; + /** + * The link that appears in the terms and conditions checkbox + * @uiName Terms and conditions link + */ + "termsAndConditionsLink": string; + } interface SqmPasswordField { /** * @undocumented @@ -5782,11 +6007,6 @@ export namespace Components { * @uiGroup Step 1 Properties */ "step1_currency": string; - /** - * @uiName Currency field help text - * @uiGroup Step 1 Properties - */ - "step1_currencyHelpText": string; /** * @uiName Email field label * @uiGroup Step 1 Properties @@ -6833,10 +7053,6 @@ export namespace Components { * @uiName Currency field label */ "currency": string; - /** - * @uiName Currency field help text - */ - "currencyHelpText": string; /** * @undocumented * @uiType object @@ -7026,6 +7242,78 @@ export namespace Components { * @uiGroup Code Verification Step */ "codeStep_verifyText": string; + /** + * @uiName Confirm button label + * @uiGroup Partner Creation Step + */ + "createPartnerStep_confirmButtonLabel": string; + /** + * @uiName Country label + * @uiGroup Partner Creation Step + */ + "createPartnerStep_countryLabel": string; + /** + * @uiName Currency label + * @uiGroup Partner Creation Step + */ + "createPartnerStep_currencyLabel": string; + /** + * @uiName Existing partner description + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_descriptionExistingPartner": string; + /** + * @uiName New partner description + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_descriptionNewPartner": string; + /** + * @uiName Missing fields error text + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_missingFieldsErrorText": string; + /** + * @uiName New partner header + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_modalHeader": string; + /** + * @uiName Existing partner header + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_modalHeaderExistingPartner": string; + /** + * @uiName Network error text + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_networkErrorText": string; + /** + * @uiName Search country placeholder + * @uiGroup Partner Creation Step + */ + "createPartnerStep_searchCountryPlaceholder": string; + /** + * @uiName Search currency placeholder + * @uiGroup Partner Creation Step + */ + "createPartnerStep_searchCurrencyPlaceholder": string; + /** + * @uiName Submit button label + * @uiGroup Partner Creation Step + */ + "createPartnerStep_submitButtonLabel": string; + /** + * @uiName Existing partner support description + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_supportDescriptionExistingPartner": string; /** * @uiName Email input label * @uiGroup Email Verification Step @@ -7057,19 +7345,15 @@ export namespace Components { */ "emailStep_verifyEmailHeaderText": string; /** - * @uiName General verify widget description text + * @uiName General widget header text with partner creation * @uiGroup General Text */ - "general_verifyEmailDescription": string; - /** - * @uiName General verify widget header text - * @uiGroup General Text - */ - "general_verifyEmailHeader": string; + "general_widgetHeaderWithPartnerCreation": string; /** * @undocumented * @componentState { "title": "Step 1: Enter email", "props": { "showCode": false }, "dependencies": ["sqm-email-verification"], "uiGroup": "Email Verification Step" } * @componentState { "title": "Step 2: Enter code", "props": { "showCode": true }, "dependencies": ["sqm-code-verification"], "uiGroup": "Code Verification Step" } + * @componentState { "title": "Step 3: Create Partner", "props": { "showPartnerModal": true }, "dependencies": ["sqm-partner-info-modal"], "uiGroup": "Partner Creation Step" } */ "stateController": string; } @@ -7377,6 +7661,12 @@ declare global { prototype: HTMLSqmPaginationElement; new (): HTMLSqmPaginationElement; }; + interface HTMLSqmPartnerInfoModalElement extends Components.SqmPartnerInfoModal, HTMLStencilElement { + } + var HTMLSqmPartnerInfoModalElement: { + prototype: HTMLSqmPartnerInfoModalElement; + new (): HTMLSqmPartnerInfoModalElement; + }; interface HTMLSqmPasswordFieldElement extends Components.SqmPasswordField, HTMLStencilElement { } var HTMLSqmPasswordFieldElement: { @@ -7901,6 +8191,7 @@ declare global { "sqm-navigation-sidebar": HTMLSqmNavigationSidebarElement; "sqm-navigation-sidebar-item": HTMLSqmNavigationSidebarItemElement; "sqm-pagination": HTMLSqmPaginationElement; + "sqm-partner-info-modal": HTMLSqmPartnerInfoModalElement; "sqm-password-field": HTMLSqmPasswordFieldElement; "sqm-payout-button-scroll": HTMLSqmPayoutButtonScrollElement; "sqm-payout-details-card": HTMLSqmPayoutDetailsCardElement; @@ -7986,6 +8277,12 @@ declare namespace LocalJSX { interface RaisinsPlopTarget { } interface SqmBankingInfoForm { + /** + * Error messages for the agency code field. Supports error codes: empty, alphanumeric, tooShort + * @uiName Agency code error + * @uiWidget textArea + */ + "agencyCodeError"?: string; /** * @uiName Agency code field label */ @@ -7995,18 +8292,42 @@ declare namespace LocalJSX { * @uiName Back button label */ "backButton"?: string; + /** + * Error messages for the bank account number / IBAN field. Supports error codes: empty, invalidUk, invalid, ibanEmpty, ibanAlphanumeric, ibanInvalid, ibanCountryMismatch + * @uiName Bank account number / IBAN error + * @uiWidget textArea + */ + "bankAccountNumberError"?: string; /** * @uiName Bank account number field label */ "bankAccountNumberLabel"?: string; + /** + * Error messages for the bank account type field. Supports error codes: empty + * @uiName Bank account type error + * @uiWidget textArea + */ + "bankAccountTypeError"?: string; /** * @uiName Bank account type field label */ "bankAccountTypeLabel"?: string; + /** + * Error messages for the bank address field. Supports error codes: empty + * @uiName Bank address error + * @uiWidget textArea + */ + "bankAddressError"?: string; /** * @uiName Bank address field label */ "bankAddressLabel"?: string; + /** + * Error messages for the bank city field. Supports error codes: empty + * @uiName Bank city error + * @uiWidget textArea + */ + "bankCityError"?: string; /** * @uiName Bank city field label */ @@ -8015,14 +8336,32 @@ declare namespace LocalJSX { * @uiName Bank country field label */ "bankLocationLabel"?: string; + /** + * Error messages for the bank name field. Supports error codes: empty + * @uiName Bank name error + * @uiWidget textArea + */ + "bankNameError"?: string; /** * @uiName Bank name field label */ "bankNameLabel"?: string; + /** + * Error messages for the bank postal code field. Supports error codes: empty + * @uiName Bank postal code error + * @uiWidget textArea + */ + "bankPostalCodeError"?: string; /** * @uiName Bank postal code field label */ "bankPostalCodeLabel"?: string; + /** + * Error messages for the bank province/state field. Supports error codes: empty + * @uiName Bank province/state error + * @uiWidget textArea + */ + "bankStateError"?: string; /** * @uiName Bank province/state field label */ @@ -8031,14 +8370,32 @@ declare namespace LocalJSX { * @uiName Beneficiary account field description */ "beneficiaryAccountNameDescription"?: string; + /** + * Error messages for the beneficiary / account holder name field. Supports error codes: empty, invalidCharacters, numeric, tooLong, nonEnglish, businessNameMismatch, nameMismatch, businessPayeeMismatch, payeeMismatch + * @uiName Beneficiary account name error + * @uiWidget textArea + */ + "beneficiaryAccountNameError"?: string; /** * @uiName Beneficiary account field label */ "beneficiaryAccountNameLabel"?: string; + /** + * Error messages for the branch code field. Supports error codes: invalid + * @uiName Branch code error + * @uiWidget textArea + */ + "branchCodeError"?: string; /** * @uiName Branch code field label */ "branchCodeLabel"?: string; + /** + * Error messages for the branch name field. Supports error codes: empty + * @uiName Branch name error + * @uiWidget textArea + */ + "branchNameError"?: string; /** * One of three options listed for the classification field * @uiName Business classification option @@ -8052,6 +8409,12 @@ declare namespace LocalJSX { * @uiName Classification CPF field label */ "classificationCPFLabel"?: string; + /** + * Error messages for the classification code field. Supports error codes: empty, invalidKzt + * @uiName Classification code error + * @uiWidget textArea + */ + "classificationCodeError"?: string; /** * @uiName Classification entity field label */ @@ -8159,6 +8522,12 @@ declare namespace LocalJSX { * @uiName Information modal title */ "modalTitle"?: string; + /** + * Error messages for the patronymic name field. Supports error codes: empty, alphanumeric + * @uiName Patronymic name error + * @uiWidget textArea + */ + "patronymicNameError"?: string; /** * @uiName Patronymic name field label */ @@ -8168,6 +8537,12 @@ declare namespace LocalJSX { * @uiName PayPal email field label */ "payPalInputLabel"?: string; + /** + * Error messages for the payment day field. Supports error codes: empty, invalid + * @uiName Payment day error + * @uiWidget textArea + */ + "paymentDayError"?: string; /** * Label text for the payment day select option for the fifteenth of the month * @uiName Fifteenth of month payday option @@ -8203,11 +8578,29 @@ declare namespace LocalJSX { * @uiName Fixed day payment schedule option */ "paymentScheduleFixedDay"?: string; + /** + * Error messages for the payment threshold field. Supports error codes: empty, invalid + * @uiName Payment threshold error + * @uiWidget textArea + */ + "paymentThresholdError"?: string; /** * Participant use this field to select the balance at which they want to be paid * @uiName Payment threshold field label */ "paymentThresholdSelectLabel"?: string; + /** + * Error messages for the PayPal email field. Supports error codes: empty, unsupportedCurrency, invalidEmail, verificationIncomplete + * @uiName PayPal email error + * @uiWidget textArea + */ + "paypalEmailError"?: string; + /** + * Error messages for the routing code / sort code / BSB field. Supports error codes: invalidBsb, invalidSortCode, empty, invalid + * @uiName Routing code error + * @uiWidget textArea + */ + "routingCodeError"?: string; /** * @uiName Routing code field label */ @@ -8225,6 +8618,12 @@ declare namespace LocalJSX { * @uiName Support link text */ "supportLink"?: string; + /** + * Error messages for the SWIFT / BIC code field. Supports error codes: empty, alphanumeric, invalid + * @uiName SWIFT code error + * @uiWidget textArea + */ + "swiftCodeError"?: string; /** * @uiName SWIFT code field label */ @@ -8238,6 +8637,12 @@ declare namespace LocalJSX { * @uiName Page description */ "taxAndPayoutsDescription"?: string; + /** + * Error messages for the tax payer ID / classification entity field. Supports error codes: empty, emptyAr, emptyKr, alphanumeric, alphanumericAr, alphanumericKr, invalid, invalidAr, invalidKr, invalidKzt, cnpjTooShort, cpfTooShort + * @uiName Tax payer ID error + * @uiWidget textArea + */ + "taxPayerIdError"?: string; /** * @uiName Taxpayer ID field label */ @@ -8255,6 +8660,12 @@ declare namespace LocalJSX { * @uiName Verify email header */ "verifyEmailHeaderText"?: string; + /** + * Error messages for the VO code field. Supports error codes: empty, alphanumeric + * @uiName VO code error + * @uiWidget textArea + */ + "voCodeError"?: string; /** * @uiName VO code field label */ @@ -10107,6 +10518,110 @@ declare namespace LocalJSX { */ "paginationText"?: string; } + interface SqmPartnerInfoModal { + /** + * Edit the property called terms and conditions text to change what's displayed for {termsAndConditionsLink}. + * @uiName Terms and conditions checkbox + */ + "allowBankingCollection"?: string; + /** + * @uiName Confirm button label + */ + "confirmButtonLabel"?: string; + /** + * @uiName Country label + */ + "countryLabel"?: string; + /** + * @uiName Currency label + */ + "currencyLabel"?: string; + /** + * @undocumented + * @uiType object + */ + "demoData"?: DemoData; + /** + * Description for existing partner confirmation + * @uiName Existing partner description + * @uiWidget textArea + */ + "descriptionExistingPartner"?: string; + /** + * Description for new partner setup + * @uiName New partner description + * @uiWidget textArea + */ + "descriptionNewPartner"?: string; + /** + * Used to render in another modal. + * @undocumented + */ + "inModal"?: boolean; + /** + * @uiName Missing fields error text + * @uiWidget textArea + */ + "missingFieldsErrorText"?: string; + /** + * Header text when user has no existing partner + * @uiName New partner header + * @uiWidget textArea + */ + "modalHeader"?: string; + /** + * Header text when user has an existing partner + * @uiName Existing partner header + * @uiWidget textArea + */ + "modalHeaderExistingPartner"?: string; + /** + * @uiName Network error text + * @uiWidget textArea + */ + "networkErrorText"?: string; + /** + * @uiName Search country placeholder + */ + "searchCountryPlaceholder"?: string; + /** + * @uiName Search currency placeholder + */ + "searchCurrencyPlaceholder"?: string; + /** + * @undocumented + * @componentState { "title": "New partner", "props": { "states": { "open": true, "isExistingPartner": false } } } + * @componentState { "title": "Existing partner", "props": { "states": { "open": true, "isExistingPartner": true, "countryCode": "US", "currency": "USD" } } } + * @componentState { "title": "Connected (hidden)", "props": { "states": { "open": false } } } + */ + "stateController"?: string; + /** + * @uiName Submit button label + */ + "submitButtonLabel"?: string; + /** + * Support description for existing partner confirmation + * @uiName Existing partner support description + * @uiWidget textArea + */ + "supportDescriptionExistingPartner"?: string; + /** + * Support description for existing partner confirmation + * @uiName Existing partner support description + */ + "supportLink"?: string; + /** + * The link text that appears in the terms and conditions checkbox + * @uiName Terms and conditions text + * @uiWidget textArea + */ + "termsAndConditionsLabel"?: string; + /** + * The link that appears in the terms and conditions checkbox + * @uiName Terms and conditions link + */ + "termsAndConditionsLink"?: string; + } interface SqmPasswordField { /** * @undocumented @@ -13675,11 +14190,6 @@ declare namespace LocalJSX { * @uiGroup Step 1 Properties */ "step1_currency"?: string; - /** - * @uiName Currency field help text - * @uiGroup Step 1 Properties - */ - "step1_currencyHelpText"?: string; /** * @uiName Email field label * @uiGroup Step 1 Properties @@ -14725,10 +15235,6 @@ declare namespace LocalJSX { * @uiName Currency field label */ "currency"?: string; - /** - * @uiName Currency field help text - */ - "currencyHelpText"?: string; /** * @undocumented * @uiType object @@ -14918,6 +15424,78 @@ declare namespace LocalJSX { * @uiGroup Code Verification Step */ "codeStep_verifyText"?: string; + /** + * @uiName Confirm button label + * @uiGroup Partner Creation Step + */ + "createPartnerStep_confirmButtonLabel"?: string; + /** + * @uiName Country label + * @uiGroup Partner Creation Step + */ + "createPartnerStep_countryLabel"?: string; + /** + * @uiName Currency label + * @uiGroup Partner Creation Step + */ + "createPartnerStep_currencyLabel"?: string; + /** + * @uiName Existing partner description + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_descriptionExistingPartner"?: string; + /** + * @uiName New partner description + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_descriptionNewPartner"?: string; + /** + * @uiName Missing fields error text + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_missingFieldsErrorText"?: string; + /** + * @uiName New partner header + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_modalHeader"?: string; + /** + * @uiName Existing partner header + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_modalHeaderExistingPartner"?: string; + /** + * @uiName Network error text + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_networkErrorText"?: string; + /** + * @uiName Search country placeholder + * @uiGroup Partner Creation Step + */ + "createPartnerStep_searchCountryPlaceholder"?: string; + /** + * @uiName Search currency placeholder + * @uiGroup Partner Creation Step + */ + "createPartnerStep_searchCurrencyPlaceholder"?: string; + /** + * @uiName Submit button label + * @uiGroup Partner Creation Step + */ + "createPartnerStep_submitButtonLabel"?: string; + /** + * @uiName Existing partner support description + * @uiGroup Partner Creation Step + * @uiWidget textArea + */ + "createPartnerStep_supportDescriptionExistingPartner"?: string; /** * @uiName Email input label * @uiGroup Email Verification Step @@ -14949,19 +15527,15 @@ declare namespace LocalJSX { */ "emailStep_verifyEmailHeaderText"?: string; /** - * @uiName General verify widget description text - * @uiGroup General Text - */ - "general_verifyEmailDescription"?: string; - /** - * @uiName General verify widget header text + * @uiName General widget header text with partner creation * @uiGroup General Text */ - "general_verifyEmailHeader"?: string; + "general_widgetHeaderWithPartnerCreation"?: string; /** * @undocumented * @componentState { "title": "Step 1: Enter email", "props": { "showCode": false }, "dependencies": ["sqm-email-verification"], "uiGroup": "Email Verification Step" } * @componentState { "title": "Step 2: Enter code", "props": { "showCode": true }, "dependencies": ["sqm-code-verification"], "uiGroup": "Code Verification Step" } + * @componentState { "title": "Step 3: Create Partner", "props": { "showPartnerModal": true }, "dependencies": ["sqm-partner-info-modal"], "uiGroup": "Partner Creation Step" } */ "stateController"?: string; } @@ -15023,6 +15597,7 @@ declare namespace LocalJSX { "sqm-navigation-sidebar": SqmNavigationSidebar; "sqm-navigation-sidebar-item": SqmNavigationSidebarItem; "sqm-pagination": SqmPagination; + "sqm-partner-info-modal": SqmPartnerInfoModal; "sqm-password-field": SqmPasswordField; "sqm-payout-button-scroll": SqmPayoutButtonScroll; "sqm-payout-details-card": SqmPayoutDetailsCard; @@ -15157,6 +15732,7 @@ declare module "@stencil/core" { "sqm-navigation-sidebar": LocalJSX.SqmNavigationSidebar & JSXBase.HTMLAttributes; "sqm-navigation-sidebar-item": LocalJSX.SqmNavigationSidebarItem & JSXBase.HTMLAttributes; "sqm-pagination": LocalJSX.SqmPagination & JSXBase.HTMLAttributes; + "sqm-partner-info-modal": LocalJSX.SqmPartnerInfoModal & JSXBase.HTMLAttributes; "sqm-password-field": LocalJSX.SqmPasswordField & JSXBase.HTMLAttributes; "sqm-payout-button-scroll": LocalJSX.SqmPayoutButtonScroll & JSXBase.HTMLAttributes; "sqm-payout-details-card": LocalJSX.SqmPayoutDetailsCard & JSXBase.HTMLAttributes; diff --git a/packages/mint-components/src/components/sqm-form-message/readme.md b/packages/mint-components/src/components/sqm-form-message/readme.md index c49c5aa8ec..22d16daa28 100644 --- a/packages/mint-components/src/components/sqm-form-message/readme.md +++ b/packages/mint-components/src/components/sqm-form-message/readme.md @@ -26,6 +26,7 @@ - [sqm-indirect-tax-form](../tax-and-cash/sqm-indirect-tax-form) - [sqm-instant-access-registration](../sqm-instant-access-registration) - [sqm-lead-form](../sqm-lead-form) + - [sqm-partner-info-modal](../sqm-partner-info-modal) - [sqm-payout-status-alert](../tax-and-cash/sqm-payout-status-alert) - [sqm-portal-change-marketing](../sqm-portal-change-marketing) - [sqm-portal-change-password](../sqm-portal-change-password) @@ -63,6 +64,7 @@ graph TD; sqm-indirect-tax-form --> sqm-form-message sqm-instant-access-registration --> sqm-form-message sqm-lead-form --> sqm-form-message + sqm-partner-info-modal --> sqm-form-message sqm-payout-status-alert --> sqm-form-message sqm-portal-change-marketing --> sqm-form-message sqm-portal-change-password --> sqm-form-message diff --git a/packages/mint-components/src/components/sqm-partner-info-modal/PartnerInfoModal.stories.tsx b/packages/mint-components/src/components/sqm-partner-info-modal/PartnerInfoModal.stories.tsx new file mode 100644 index 0000000000..7d32e8ac2a --- /dev/null +++ b/packages/mint-components/src/components/sqm-partner-info-modal/PartnerInfoModal.stories.tsx @@ -0,0 +1,210 @@ +import { h } from "@stencil/core"; +import { + PartnerInfoModalView, + PartnerInfoModalViewProps, +} from "./sqm-partner-info-modal-view"; + +export default { + title: "Components/Partner Info Modal", +}; + +const demoCountries = [ + { countryCode: "US", displayName: "United States" }, + { countryCode: "CA", displayName: "Canada" }, + { countryCode: "GB", displayName: "United Kingdom" }, + { countryCode: "AU", displayName: "Australia" }, + { countryCode: "DE", displayName: "Germany" }, + { countryCode: "FR", displayName: "France" }, + { countryCode: "JP", displayName: "Japan" }, +]; + +const demoCurrencies = [ + { currencyCode: "USD", displayName: "US Dollar" }, + { currencyCode: "CAD", displayName: "Canadian Dollar" }, + { currencyCode: "GBP", displayName: "British Pound" }, + { currencyCode: "EUR", displayName: "Euro" }, + { currencyCode: "AUD", displayName: "Australian Dollar" }, +]; + +const noopCallbacks = { + onCountryChange: (e: any) => console.log("Country changed:", e), + onCurrencyChange: (e: any) => console.log("Currency changed:", e), + onCheckboxChange: (e: any) => console.log("Checkbox changed:", e), + setCountrySearch: (v: string) => console.log("Country search:", v), + setCurrencySearch: (v: string) => console.log("Currency search:", v), + onSubmit: () => console.log("Submit"), + onClose: () => console.log("Close"), +}; + +const defaultText = { + modalHeader: "Let's get you ready for rewards", + modalHeaderExistingPartner: "We found an existing account", + descriptionNewPartner: + "Confirm your country and currency now to get your future rewards faster.", + descriptionExistingPartner: + "We noticed you are already an Impact.com partner, please confirm your information.", + supportDescriptionExistingPartner: + "If this is a mistake, please contact Support or sign up for this referral program with a different email.", + supportLink: "Support", + countryLabel: "Country", + currencyLabel: "Currency", + submitButtonLabel: "Submit", + confirmButtonLabel: "Confirm", + searchCountryPlaceholder: "Search for a country", + searchCurrencyPlaceholder: "Search for a currency", + bankingCollectionText: "", + allowBankingCollection: + "I have read the {termsAndConditionsLink} and allow impact.com to collect my tax and banking information", + termsAndConditionsLabel: "terms and conditions", + termsAndConditionsLink: + "https://terms.advocate.impact.com/PayoutTermsAndConditions.html", +}; + +const defaultProps: PartnerInfoModalViewProps = { + states: { + open: true, + loading: false, + submitting: false, + isExistingPartner: false, + countryCode: null, + currency: null, + error: "", + success: false, + filteredCountries: demoCountries, + filteredCurrencies: demoCurrencies, + allowBankingCollection: false, + disabled: false, + }, + callbacks: noopCallbacks, + text: defaultText, +}; + +export const NewPartnerEmpty = () => { + return ; +}; + +export const NewPartnerPrefilled = () => { + const props: PartnerInfoModalViewProps = { + ...defaultProps, + states: { + ...defaultProps.states, + countryCode: "US", + currency: "", + }, + }; + return ; +}; + +export const NewPartnerFullySelected = () => { + const props: PartnerInfoModalViewProps = { + ...defaultProps, + states: { + ...defaultProps.states, + countryCode: "US", + currency: "USD", + }, + }; + return ; +}; + +export const ExistingPartnerConfirm = () => { + const props: PartnerInfoModalViewProps = { + ...defaultProps, + states: { + ...defaultProps.states, + isExistingPartner: true, + countryCode: "CA", + currency: "CAD", + }, + }; + return ; +}; + +export const ExistingPartnerEmpty = () => { + const props: PartnerInfoModalViewProps = { + ...defaultProps, + states: { + ...defaultProps.states, + isExistingPartner: true, + countryCode: "", + currency: "", + }, + }; + return ; +}; + +export const Submitting = () => { + const props: PartnerInfoModalViewProps = { + ...defaultProps, + states: { + ...defaultProps.states, + countryCode: "GB", + currency: "GBP", + submitting: true, + }, + }; + return ; +}; + +export const WithError = () => { + const props: PartnerInfoModalViewProps = { + ...defaultProps, + states: { + ...defaultProps.states, + countryCode: "US", + currency: "USD", + error: + "An error occurred while creating your partner account. Please try again.", + }, + }; + return ; +}; + +export const ValidationError = () => { + const props: PartnerInfoModalViewProps = { + ...defaultProps, + states: { + ...defaultProps.states, + countryCode: "", + currency: "", + error: "Please select both a country and currency.", + }, + }; + return ; +}; + +export const Closed = () => { + const props: PartnerInfoModalViewProps = { + ...defaultProps, + states: { + ...defaultProps.states, + open: false, + }, + }; + return ; +}; + +export const SQMComponentExistingPartner = () => { + return ( + + ); +}; + +export const SQMComponentNewPartner = () => { + return ( + + ); +}; diff --git a/packages/mint-components/src/components/sqm-partner-info-modal/readme.md b/packages/mint-components/src/components/sqm-partner-info-modal/readme.md new file mode 100644 index 0000000000..da55359694 --- /dev/null +++ b/packages/mint-components/src/components/sqm-partner-info-modal/readme.md @@ -0,0 +1,57 @@ +# sqm-partner-info-modal + + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| ----------------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `allowBankingCollection` | `allow-banking-collection` | Edit the property called terms and conditions text to change what's displayed for {termsAndConditionsLink}. | `string` | `"I have read the {termsAndConditionsLink} and allow impact.com to collect my tax and banking information"` | +| `confirmButtonLabel` | `confirm-button-label` | | `string` | `"Confirm"` | +| `countryLabel` | `country-label` | | `string` | `"Country"` | +| `currencyLabel` | `currency-label` | | `string` | `"Currency"` | +| `demoData` | -- | | `{ states?: { open: boolean; loading: boolean; submitting: boolean; isExistingPartner: boolean; countryCode: string; currency: string; error: string; success: boolean; filteredCountries: { countryCode: string; displayName: string; }[]; filteredCurrencies: { currencyCode: string; displayName: string; }[]; allowBankingCollection: boolean; disabled: boolean; }; }` | `undefined` | +| `descriptionExistingPartner` | `description-existing-partner` | Description for existing partner confirmation | `string` | `"We found an account with this email on our referral program provider, impact.com. Please confirm your country and currency now to get your future rewards faster."` | +| `descriptionNewPartner` | `description-new-partner` | Description for new partner setup | `string` | `"Confirm your country and currency now to get your future rewards faster."` | +| `inModal` | `in-modal` | Used to render in another modal. | `boolean` | `false` | +| `missingFieldsErrorText` | `missing-fields-error-text` | | `string` | `"Please select both a country and currency."` | +| `modalHeader` | `modal-header` | Header text when user has no existing partner | `string` | `"Let's get you ready for rewards"` | +| `modalHeaderExistingPartner` | `modal-header-existing-partner` | Header text when user has an existing partner | `string` | `"We found an existing account"` | +| `networkErrorText` | `network-error-text` | | `string` | `"An error occurred. Please try again."` | +| `searchCountryPlaceholder` | `search-country-placeholder` | | `string` | `"Search for a country"` | +| `searchCurrencyPlaceholder` | `search-currency-placeholder` | | `string` | `"Search for a currency"` | +| `stateController` | `state-controller` | | `string` | `"{}"` | +| `submitButtonLabel` | `submit-button-label` | | `string` | `"Submit"` | +| `supportDescriptionExistingPartner` | `support-description-existing-partner` | Support description for existing partner confirmation | `string` | `"If this is a mistake, please contact {supportLink} or sign up for this referral program with a different email."` | +| `supportLink` | `support-link` | Support description for existing partner confirmation | `string` | `"Support"` | +| `termsAndConditionsLabel` | `terms-and-conditions-label` | The link text that appears in the terms and conditions checkbox | `string` | `"terms and conditions"` | +| `termsAndConditionsLink` | `terms-and-conditions-link` | The link that appears in the terms and conditions checkbox | `string` | `"https://terms.advocate.impact.com/PayoutTermsAndConditions.html"` | + + +## Dependencies + +### Used by + + - [sqm-stencilbook](../sqm-stencilbook) + - [sqm-widget-verification](../sqm-widget-verification) + +### Depends on + +- [sqm-form-message](../sqm-form-message) + +### Graph +```mermaid +graph TD; + sqm-partner-info-modal --> sqm-form-message + sqm-form-message --> sqm-skeleton + sqm-stencilbook --> sqm-partner-info-modal + sqm-widget-verification --> sqm-partner-info-modal + style sqm-partner-info-modal fill:#f9f,stroke:#333,stroke-width:4px +``` + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/packages/mint-components/src/components/sqm-partner-info-modal/sqm-partner-info-modal-view.tsx b/packages/mint-components/src/components/sqm-partner-info-modal/sqm-partner-info-modal-view.tsx new file mode 100644 index 0000000000..44a8d18943 --- /dev/null +++ b/packages/mint-components/src/components/sqm-partner-info-modal/sqm-partner-info-modal-view.tsx @@ -0,0 +1,297 @@ +import { h } from "@stencil/core"; +import { createStyleSheet } from "../../styling/JSS"; +import { intl } from "../../global/global"; + +export interface PartnerInfoModalViewProps { + states: { + open: boolean; + loading: boolean; + submitting: boolean; + isExistingPartner: boolean; + countryCode: string; + currency: string; + error: string; + success: boolean; + filteredCountries: { countryCode: string; displayName: string }[]; + filteredCurrencies: { currencyCode: string; displayName: string }[]; + allowBankingCollection: boolean; + disabled: boolean; + }; + callbacks: { + onCountryChange: (e: any) => void; + onCurrencyChange: (e: any) => void; + onCheckboxChange: (e: any) => void; + setCurrencySearch: (c: any) => void; + setCountrySearch: (c: any) => void; + onSubmit: () => void; + onClose: () => void; + }; + text: { + modalHeader: string; + descriptionNewPartner: string; + descriptionExistingPartner: string; + countryLabel: string; + currencyLabel: string; + submitButtonLabel: string; + confirmButtonLabel: string; + searchCountryPlaceholder: string; + searchCurrencyPlaceholder: string; + supportDescriptionExistingPartner: string; + supportLink: string; + modalHeaderExistingPartner: string; + allowBankingCollection: string; + termsAndConditionsLabel: string; + termsAndConditionsLink: string; + }; +} + +const style = { + Dialog: { + "&::part(panel)": { + maxWidth: "480px", + }, + "&::part(body)": { + padding: "0 var(--sl-spacing-x-large)", + fontSize: "var(--sl-font-size-small)", + overflow: "visible", + }, + "&::part(overlay)": { + background: "var(--sl-overlay-background-color)", + }, + }, + DialogTitle: { + fontSize: "var(--sl-font-size-x-large)", + fontWeight: "600", + padding: "var(--sl-spacing-large) 0 0 0", + margin: "0", + }, + FormFields: { + display: "flex", + flexDirection: "column", + gap: "var(--sl-spacing-medium)", + marginTop: "var(--sl-spacing-large)", + }, + ErrorMessage: { + marginTop: "var(--sl-spacing-x-small)", + }, + SearchInput: { + "&::part(base)": { + border: "none", + borderBottom: "1px solid var(--sl-color-neutral-300)", + borderRadius: "0", + }, + }, + SelectMenu: { + maxHeight: "300px", + }, + DescriptionContainer: { + display: "flex", + flexDirection: "column", + gap: "var(--sl-spacing-medium)", + margin: "0", + "& > p": { + margin: "0", + }, + }, + CheckboxWrapper: { + display: "flex", + justifyContent: "flex-start", + flexDirection: "column", + }, + Checkbox: { + "&::part(label)": { + fontSize: "var(--sl-font-size-small)", + }, + }, + SubmitButton: { + width: "100%", + marginTop: "var(--sl-spacing-large)", + }, +}; + +export function PartnerInfoModalContentView(props: PartnerInfoModalViewProps) { + const { states, callbacks, text } = props; + const sheet = createStyleSheet(style); + const styleString = sheet.toString(); + + const supportMessage = intl.formatMessage( + { + id: "supportDescriptionExistingPartner", + defaultMessage: text.supportDescriptionExistingPartner, + }, + { + supportLink: ( + + {text.supportLink} + + ), + }, + ); + + const description = states.isExistingPartner ? ( + +

{text.descriptionExistingPartner}

+

{supportMessage}

+
+ ) : ( +

+ {text.descriptionNewPartner} +

+ ); + + const buttonLabel = states.isExistingPartner + ? text.confirmButtonLabel + : text.submitButtonLabel; + + const bankingCollectionText = intl.formatMessage( + { + id: "bankingCollectionText", + defaultMessage: text.allowBankingCollection, + }, + { + termsAndConditionsLink: ( + + {text.termsAndConditionsLabel} + + ), + }, + ); + + return ( +
+ +
+ {description} + + e.stopPropagation()} + onSl-input={(e: any) => { + callbacks.setCountrySearch(e.target?.value); + }} + /> +
+ {states.filteredCountries?.map((c) => ( + {c.displayName} + ))} +
+
+ + + e.stopPropagation()} + onSl-input={(e: any) => + callbacks.setCurrencySearch(e.target?.value) + } + /> +
+ {states.filteredCurrencies?.map((c) => ( + + {c.currencyCode} - {c.displayName} + + ))} +
+
+
+ + {bankingCollectionText} + +
+
+ {states.error && ( +
+ +

{states.error}

+
+
+ )} + + + {buttonLabel} + +
+ ); +} + +export function PartnerInfoModalView(props: PartnerInfoModalViewProps) { + const { states, text, callbacks } = props; + const sheet = createStyleSheet(style); + const styleString = sheet.toString(); + + if (!states.open) return
; + + return ( +
+ + { + e.preventDefault(); + }} + onSl-hide={(e: any) => { + if (e.target?.tagName === "SL-DIALOG") { + e.preventDefault(); + } + }} + > +

+ {states.isExistingPartner + ? text.modalHeaderExistingPartner + : text.modalHeader} +

+ +
+
+ ); +} diff --git a/packages/mint-components/src/components/sqm-partner-info-modal/sqm-partner-info-modal.tsx b/packages/mint-components/src/components/sqm-partner-info-modal/sqm-partner-info-modal.tsx new file mode 100644 index 0000000000..c130e9979f --- /dev/null +++ b/packages/mint-components/src/components/sqm-partner-info-modal/sqm-partner-info-modal.tsx @@ -0,0 +1,268 @@ +import { isDemo } from "@saasquatch/component-boilerplate"; +import { useState, withHooks } from "@saasquatch/stencil-hooks"; +import { Component, Prop, h } from "@stencil/core"; +import deepmerge from "deepmerge"; +import { DemoData } from "../../global/demo"; +import { parseStates } from "../../utils/parseStates"; +import { getProps } from "../../utils/utils"; +import { + PartnerInfoModalContentView, + PartnerInfoModalView, + PartnerInfoModalViewProps, +} from "./sqm-partner-info-modal-view"; +import { + PartnerInfoModalResult, + usePartnerInfoModal, +} from "./usePartnerInfoModal"; + +/** + * @uiName Partner Info Modal + * @exampleGroup Tax and Cash + * @validParents ["sqm-portal-container", "sqm-portal-frame", "div", "sqm-divided-layout", "sqb-program-section", "sqb-conditional-section"] + * @example Partner Info Modal - + */ +@Component({ + tag: "sqm-partner-info-modal", + shadow: true, +}) +export class PartnerInfoModal { + /** + * Header text when user has no existing partner + * + * @uiName New partner header + * @uiWidget textArea + */ + @Prop() + modalHeader: string = "Let's get you ready for rewards"; + + /** + * Header text when user has an existing partner + * + * @uiName Existing partner header + * @uiWidget textArea + */ + @Prop() + modalHeaderExistingPartner: string = "We found an existing account"; + + /** + * Description for new partner setup + * + * @uiName New partner description + * @uiWidget textArea + */ + @Prop() + descriptionNewPartner: string = + "Confirm your country and currency now to get your future rewards faster."; + + /** + * Description for existing partner confirmation + * + * @uiName Existing partner description + * @uiWidget textArea + */ + @Prop() + descriptionExistingPartner: string = + "We found an account with this email on our referral program provider, impact.com. Please confirm your country and currency now to get your future rewards faster."; + + /** + * Support description for existing partner confirmation + * + * @uiName Existing partner support description + * @uiWidget textArea + */ + @Prop() + supportDescriptionExistingPartner: string = + "If this is a mistake, please contact {supportLink} or sign up for this referral program with a different email."; + + /** + * Support description for existing partner confirmation + * + * @uiName Existing partner support description + */ + @Prop() + supportLink: string = "Support"; + + /** + * Edit the property called terms and conditions text to change what's displayed for {termsAndConditionsLink}. + * @uiName Terms and conditions checkbox + */ + @Prop() allowBankingCollection: string = + "I have read the {termsAndConditionsLink} and allow impact.com to collect my tax and banking information"; + /** + * The link text that appears in the terms and conditions checkbox + * @uiName Terms and conditions text + * @uiWidget textArea + */ + @Prop() termsAndConditionsLabel: string = "terms and conditions"; + /** + * The link that appears in the terms and conditions checkbox + * @uiName Terms and conditions link + */ + @Prop() termsAndConditionsLink: string = + "https://terms.advocate.impact.com/PayoutTermsAndConditions.html"; + /** + * @uiName Country label + */ + @Prop() + countryLabel: string = "Country"; + + /** + * @uiName Currency label + */ + @Prop() + currencyLabel: string = "Currency"; + + /** + * @uiName Submit button label + */ + @Prop() + submitButtonLabel: string = "Submit"; + + /** + * @uiName Confirm button label + */ + @Prop() + confirmButtonLabel: string = "Confirm"; + + /** + * @uiName Search country placeholder + */ + @Prop() + searchCountryPlaceholder: string = "Search for a country"; + + /** + * @uiName Search currency placeholder + */ + @Prop() + searchCurrencyPlaceholder: string = "Search for a currency"; + + /** + * @uiName Network error text + * @uiWidget textArea + */ + @Prop() + networkErrorText: string = "An error occurred. Please try again."; + + /** + * @uiName Missing fields error text + * @uiWidget textArea + */ + @Prop() + missingFieldsErrorText: string = "Please select both a country and currency."; + + /** + * Used to render in another modal. + * @undocumented + */ + @Prop() inModal: boolean = false; + + /** + * @undocumented + * @componentState { "title": "New partner", "props": { "states": { "open": true, "isExistingPartner": false } } } + * @componentState { "title": "Existing partner", "props": { "states": { "open": true, "isExistingPartner": true, "countryCode": "US", "currency": "USD" } } } + * @componentState { "title": "Connected (hidden)", "props": { "states": { "open": false } } } + */ + @Prop() stateController: string = "{}"; + + /** + * @undocumented + * @uiType object + */ + @Prop() demoData?: DemoData; + + constructor() { + withHooks(this); + } + disconnectedCallback() {} + + getTextProps() { + return getProps(this); + } + + render() { + const props = isDemo() + ? useDemoPartnerInfoModal(this) + : usePartnerInfoModal(this); + + if (this.inModal) { + return ; + } + + return ; + } +} + +function useDemoPartnerInfoModal( + props: PartnerInfoModal, +): PartnerInfoModalViewProps { + const [countryCode, setCountryCode] = useState("US"); + const [currency, setCurrency] = useState(""); + const [error, setError] = useState(""); + const [allowBankingCollection, setAllowBankingCollection] = useState(false); + + const parsed = parseStates(props.stateController); + const stateOverride = parsed?.["sqm-partner-info-modal"] || parsed || {}; + + // @ts-ignore + return deepmerge( + { + states: { + open: false, + loading: false, + submitting: false, + isExistingPartner: false, + countryCode, + currency, + error, + success: false, + filteredCountries: [], + filteredCurrencies: [], + allowBankingCollection, + disabled: false, + }, + callbacks: { + onCountryChange: (e: any) => { + const value = e?.detail?.item?.__value; + if (value) { + setCountryCode(value); + setCurrency(""); + } + }, + onCurrencyChange: (e: any) => { + const value = e?.detail?.item?.__value; + if (value) setCurrency(value); + }, + onCheckboxChange: (e: any) => { + setAllowBankingCollection(e.target.checked); + }, + setCountrySearch: () => {}, + setCurrencySearch: () => {}, + onSubmit: () => { + if (!countryCode || !currency) { + setError(props.missingFieldsErrorText); + return; + } + setError(""); + }, + onClose: () => {}, + }, + text: { + modalHeader: props.modalHeader, + descriptionNewPartner: props.descriptionNewPartner, + descriptionExistingPartner: props.descriptionExistingPartner, + countryLabel: props.countryLabel, + currencyLabel: props.currencyLabel, + submitButtonLabel: props.submitButtonLabel, + confirmButtonLabel: props.confirmButtonLabel, + searchCountryPlaceholder: props.searchCountryPlaceholder, + searchCurrencyPlaceholder: props.searchCurrencyPlaceholder, + supportDescriptionExistingPartner: + props.supportDescriptionExistingPartner, + supportLink: props.supportLink, + modalHeaderExistingPartner: props.modalHeaderExistingPartner, + }, + }, + props.demoData || stateOverride, + { arrayMerge: (_, a) => a }, + ); +} diff --git a/packages/mint-components/src/components/sqm-partner-info-modal/usePartnerInfoModal.tsx b/packages/mint-components/src/components/sqm-partner-info-modal/usePartnerInfoModal.tsx new file mode 100644 index 0000000000..b6050f2380 --- /dev/null +++ b/packages/mint-components/src/components/sqm-partner-info-modal/usePartnerInfoModal.tsx @@ -0,0 +1,360 @@ +import { + useLocale, + useMutation, + useQuery, + useSetParent, +} from "@saasquatch/component-boilerplate"; +import { useEffect, useMemo, useState } from "@saasquatch/universal-hooks"; +import { gql } from "graphql-request"; +import { PartnerInfoModal } from "./sqm-partner-info-modal"; +import { PartnerInfoModalViewProps } from "./sqm-partner-info-modal-view"; +import { StartImpactConnectionResult } from "../tax-and-cash/sqm-indirect-tax-form/useIndirectTaxForm"; +import { TAX_FORM_UPDATED_EVENT_KEY } from "../tax-and-cash/eventKeys"; +import { PARTNER_CREATED_NAMESPACE } from "../sqm-widget-verification/keys"; +import { + GET_FINANCE_NETWORK_SETTINGS, + FinanceNetworkSettingsQuery, +} from "../tax-and-cash/data"; + +export const GET_USER_PARTNER_INFO = gql` + query getUserPartnerInfo { + user: viewer { + ... on User { + id + accountId + firstName + lastName + email + countryCode + customFields + impactConnection { + connected + connectionStatus + publisher { + id + countryCode + currency + } + } + } + } + } +`; + +export const GET_COUNTRIES = gql` + query getCountries { + impactPayoutCountries(limit: 1000) { + data { + countryCode + displayName + } + } + } +`; + +export const GET_CURRENCIES = gql` + query currencies($locale: RSLocale) { + currencies(limit: 300) { + data { + displayName(locale: $locale) + currencyCode + } + } + } +`; + +export const CONNECT_PARTNER = gql` + mutation createImpactConnection($vars: ImpactConnectionInput!) { + createImpactConnection(impactConnectionInput: $vars) { + success + validationErrors { + field + message + } + user { + id + accountId + impactConnection { + connected + publisher { + brandedSignup + requiredTaxDocumentType + currentTaxDocument { + type + status + } + } + } + } + } + } +`; + +const START_IMPACT_CONNECTION = gql` + mutation startImpactConnection($vars: ImpactConnectionInput!) { + startImpactConnection(impactConnectionInput: $vars) { + success + validationErrors { + field + message + } + user { + id + accountId + impactConnection { + connected + publisher { + brandedSignup + requiredTaxDocumentType + currentTaxDocument { + type + status + } + } + } + } + } + } +`; + +export type TaxCountry = { + countryCode: string; + displayName: string; +}; + +export type CountriesQuery = { + impactPayoutCountries: { + data: TaxCountry[]; + }; +}; + +export function usePartnerInfoModal( + props: PartnerInfoModal, +): PartnerInfoModalViewProps { + const locale = useLocale(); + + const setPartnerCreated = useSetParent(PARTNER_CREATED_NAMESPACE); + + const { + data: userData, + loading: userLoading, + refetch, + } = useQuery(GET_USER_PARTNER_INFO, {}); + + const user = userData?.user; + + const { data: currenciesData, loading: currenciesLoading } = useQuery( + GET_CURRENCIES, + { variables: { locale } }, + ); + + const { data: countriesData, loading: countriesLoading } = useQuery( + GET_COUNTRIES, + {}, + ); + + const { data: financeNetworkData } = useQuery( + GET_FINANCE_NETWORK_SETTINGS, + { + variables: { filter: {} }, + }, + ); + + const [startImpactConnection, { loading: connectLoading }] = + useMutation(START_IMPACT_CONNECTION); + + const [allowBankingCollection, setAllowBankingCollection] = useState(false); + // No pre-filled country, use locale to determine countryCode instead + const [countryCode, setCountryCode] = useState( + user?.impactConnection?.publisher?.countryCode || + locale.replace(/^.*_/, ""), + ); + + const [currency, setCurrency] = useState( + user?.impactConnection?.publisher?.currency || "", + ); + + const countries = countriesData?.impactPayoutCountries?.data || []; + + // copied from useTaxAndCash for displaying currencies based on country - could be in helper? + const currencies = useMemo(() => { + const allValidCurrencies = + financeNetworkData?.impactFinanceNetworkSettings?.data?.reduce( + (agg, settings) => { + const currency = currenciesData?.currencies?.data?.find( + (c) => c.currencyCode === settings.currency, + ); + if (!currency) return agg; + if (agg.find((c) => c.currencyCode === settings.currency)) return agg; + if (countryCode && settings.countryCode !== countryCode) return agg; + return [...agg, currency]; + }, + [], + ); + return (allValidCurrencies || []).sort((a, b) => + a.displayName.localeCompare(b.displayName), + ); + }, [financeNetworkData, currenciesData, countryCode]); + + const [countrySearch, setCountrySearch] = useState(""); + const [currencySearch, setCurrencySearch] = useState(""); + const [filteredCountries, setFilteredCountries] = useState( + countriesData?.impactPayoutCountries?.data || [], + ); + const [filteredCurrencies, setFilteredCurrencies] = useState( + currencies || [], + ); + + const [error, setError] = useState(""); + const [success, setSuccess] = useState(false); + + useEffect(() => { + const publisher = user?.impactConnection?.publisher; + if (!userData || !publisher) return; + setCountryCode(publisher.countryCode); + setCurrency(publisher.currency); + }, [userData, user]); + + useEffect(() => { + if (!countries?.length) return; + if (countrySearch.trim() === "") { + setFilteredCountries(countries || []); + } else { + setFilteredCountries( + countries.filter((c) => + c.displayName.toLowerCase().includes(countrySearch.toLowerCase()), + ) || [], + ); + } + }, [countrySearch, countries]); + + useEffect(() => { + if (!currencies?.length) return; + if (currencySearch.trim() === "") { + setFilteredCurrencies(currencies || []); + } else { + setFilteredCurrencies( + currencies.filter((c) => + c.currencyCode.toLowerCase().includes(currencySearch.toLowerCase()), + ) || [], + ); + } + }, [currencySearch, currencies]); + + const impactConnection = user?.impactConnection; + + function onCountryChange(e: any) { + const value = e.detail?.item?.__value; + if (!value) return; + setCountryCode(value); + setCurrency(""); + setError(""); + } + + function onCurrencyChange(e: any) { + const value = e.detail?.item?.__value; + if (!value) return; + setCurrency(value); + setError(""); + } + + function onCheckboxChange(e: any) { + const checked = e.target.checked; + setAllowBankingCollection(checked); + } + + async function onSubmit() { + if (!allowBankingCollection) { + setError(props.missingFieldsErrorText); + return; + } + if (!countryCode || !currency) { + setError(props.missingFieldsErrorText); + return; + } + setError(""); + + if (!user) { + setError(props.networkErrorText); + return; + } + + try { + const vars = { + user: { + id: user.id, + accountId: user.accountId, + }, + firstName: user.firstName, + lastName: user.lastName, + countryCode, + currency, + }; + + const result = await startImpactConnection({ vars }); + + if (!result || (result as Error)?.message) { + setError(props.networkErrorText); + return; + } + + const connectionResult = (result as StartImpactConnectionResult) + .startImpactConnection; + + if (!connectionResult?.success) { + const validationMsg = connectionResult?.validationErrors + ?.map((e) => e.message) + .join(". "); + setError(validationMsg || props.networkErrorText); + console.error( + "Failed to create Impact connection:", + connectionResult?.validationErrors, + ); + return; + } + + window.dispatchEvent(new Event(TAX_FORM_UPDATED_EVENT_KEY)); + + await refetch(); + setPartnerCreated?.(true); + setSuccess(true); + } catch (e) { + console.error("Partner creation error:", e); + setError(props.networkErrorText); + } + } + + const showModal = + !success && + !userLoading && + impactConnection?.connectionStatus === "NOT_STARTED"; + + return { + states: { + open: showModal, + loading: userLoading || countriesLoading || currenciesLoading, + submitting: connectLoading, + isExistingPartner: !!impactConnection?.publisher, + countryCode, + currency, + error, + success, + filteredCountries: filteredCountries || [], + filteredCurrencies: filteredCurrencies || [], + allowBankingCollection, + disabled: userLoading || connectLoading, + }, + callbacks: { + onCountryChange, + onCurrencyChange, + onCheckboxChange, + setCurrencySearch, + setCountrySearch, + onSubmit, + onClose: () => setSuccess(true), + }, + text: props.getTextProps(), + }; +} + +export type PartnerInfoModalResult = ReturnType; diff --git a/packages/mint-components/src/components/sqm-referral-table/ReferralTable.stories.tsx b/packages/mint-components/src/components/sqm-referral-table/ReferralTable.stories.tsx index 7acb343e81..40f822f22f 100644 --- a/packages/mint-components/src/components/sqm-referral-table/ReferralTable.stories.tsx +++ b/packages/mint-components/src/components/sqm-referral-table/ReferralTable.stories.tsx @@ -103,6 +103,7 @@ const baseReward: Reward = { }, ], }, + rewardedCash: false, }; // Reward Status Cases diff --git a/packages/mint-components/src/components/sqm-referral-table/ReferralTableRewardsCell.stories.tsx b/packages/mint-components/src/components/sqm-referral-table/ReferralTableRewardsCell.stories.tsx index a8d99a611d..e2e312df87 100644 --- a/packages/mint-components/src/components/sqm-referral-table/ReferralTableRewardsCell.stories.tsx +++ b/packages/mint-components/src/components/sqm-referral-table/ReferralTableRewardsCell.stories.tsx @@ -88,6 +88,7 @@ const cashPayoutSentReward: Reward = { statuses: ["AVAILABLE"], globalRewardKey: "Key", rewardRedemptionTransactions: null, + rewardedCash: true, }; const nullExpiresIn = { diff --git a/packages/mint-components/src/components/sqm-referral-table/TaxAndCashReferralTable.stories.tsx b/packages/mint-components/src/components/sqm-referral-table/TaxAndCashReferralTable.stories.tsx index 02468d93df..6a3c51c092 100644 --- a/packages/mint-components/src/components/sqm-referral-table/TaxAndCashReferralTable.stories.tsx +++ b/packages/mint-components/src/components/sqm-referral-table/TaxAndCashReferralTable.stories.tsx @@ -12,7 +12,8 @@ import { PendingTaxReview, PendingNewTaxForm, PendingTaxSubmission, - PendingPartnerCreation, + PartnerNotCreatedSetupNotStarted, + PartnerCreatedSetupStartedButIncomplete, PendingW9, CashReward, } from "./TaxAndCashReferralTableRewardsCell.stories"; @@ -94,7 +95,7 @@ const taxAndCashTableProps = { , , , - , + , ], [ , diff --git a/packages/mint-components/src/components/sqm-referral-table/TaxAndCashReferralTableRewardsCell.stories.tsx b/packages/mint-components/src/components/sqm-referral-table/TaxAndCashReferralTableRewardsCell.stories.tsx index 1aac4f4307..f7b9da8979 100644 --- a/packages/mint-components/src/components/sqm-referral-table/TaxAndCashReferralTableRewardsCell.stories.tsx +++ b/packages/mint-components/src/components/sqm-referral-table/TaxAndCashReferralTableRewardsCell.stories.tsx @@ -1,18 +1,13 @@ import { h } from "@stencil/core"; -import { DateTime } from "luxon"; import { Reward, ImpactConnection } from "../../saasquatch"; export default { title: "Components/Tax And Cash Referral Table Rewards Cell", }; -function getDays() { - return DateTime.now().toMillis() + 600000000; -} - -function getMonths() { - return DateTime.now().toMillis() + 10000000000; -} +// Reusable timestamps (current date is May 2026) +const PAST = 1640995200000; // Jan 1, 2022 +const FUTURE = 2779257600000; // ~2058 const cashReward: Reward = { id: "1234", @@ -20,251 +15,366 @@ const cashReward: Reward = { value: 50, unit: "USD", name: "test", - dateScheduledFor: getDays(), - dateExpires: getMonths(), - dateCancelled: 134400, - dateRedeemed: 0, + dateScheduledFor: null, + dateExpires: null, + dateCancelled: null, + dateRedeemed: null, fuelTankCode: null, fuelTankType: null, currency: "USD", prettyValue: "$50.00", - statuses: ["AVAILABLE"], + statuses: [], globalRewardKey: "Key", rewardRedemptionTransactions: null, partnerFundsTransfer: null, + rewardedCash: true, }; -const taxConnection: ImpactConnection = { +// ============================================================ +// Reusable tax connections +// ============================================================ + +const fullySetupTaxConnection: ImpactConnection = { connected: true, taxHandlingEnabled: true, publisher: { requiredTaxDocumentType: "W9", + currentTaxDocument: { + status: "ACTIVE", + type: "W9", + dateCreated: PAST, + }, withdrawalSettings: { paymentMethod: "BANK_TRANSFER" }, payoutsAccount: null, + }, +}; + +const connectedNoWithdrawalSettings: ImpactConnection = { + connected: true, + taxHandlingEnabled: true, + publisher: { + requiredTaxDocumentType: "W9", currentTaxDocument: { status: "ACTIVE", type: "W9", - dateCreated: 1627427794891, + dateCreated: PAST, }, + withdrawalSettings: null, + payoutsAccount: null, }, }; -const defaultPFT: Reward["partnerFundsTransfer"] = { - id: "ID1234", - status: null, - dateCreated: null, - dateScheduled: null, - dateTransferred: null, +const notConnectedTaxConnection: ImpactConnection = { + connected: false, + taxHandlingEnabled: true, + publisher: null, }; -const defaultTaxDocument: ImpactConnection["publisher"]["currentTaxDocument"] = - { - status: "NOT_VERIFIED", - type: "W9", - dateCreated: DateTime.now().toMillis() - 1000000, - }; - const defaultProps = { statusText: "{status, select, AVAILABLE {Available} CANCELLED {Cancelled} PENDING {Pending} PENDING_REVIEW {Pending} PAYOUT_APPROVED {Payout Approved} PROCESSING {Payment Processing} PAYOUT_FAILED {Payout Failed} PAYOUT_CANCELLED {Payout Cancelled} PENDING_TAX_REVIEW {Pending} PENDING_NEW_TAX_FORM {Pending} PENDING_TAX_SUBMISSION {Pending} PENDING_PARTNER_CREATION {Pending} DENIED {Denied} EXPIRED {Expired} REDEEMED {Redeemed} other {Not available} }", statusLongText: - "{status, select, AVAILABLE {Reward expiring on} CANCELLED {Reward cancelled on} PENDING {Available on} PENDING_REVIEW {Pending since} PAYOUT_APPROVED {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PAYOUT_FAILED {Payout failed due to a fulfillment issue and is currently being retried.} PAYOUT_CANCELLED {If you think this is a mistake, contact our Support team.} PENDING_TAX_REVIEW {Awaiting tax form review} PENDING_NEW_TAX_FORM {Invalid tax form. Submit a new form to receive your rewards.} PROCESSING {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PENDING_TAX_SUBMISSION {Submit your tax documents to receive your rewards} PENDING_PARTNER_CREATION {Complete your tax and cash payout setup to receive your rewards} DENIED {Denied on} EXPIRED {Reward expired on} other {Not available} }", + "{status, select, AVAILABLE {Reward expiring on} CANCELLED {Reward cancelled on} PENDING {Available on} PENDING_REVIEW {Pending since} PAYOUT_APPROVED {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PAYOUT_FAILED {Payout failed due to a fulfillment issue and is currently being retried.} PAYOUT_CANCELLED {If you think this is a mistake, contact our Support team.} PENDING_TAX_REVIEW {Awaiting tax form review} PENDING_NEW_TAX_FORM {Invalid tax form. Submit a new form to receive your rewards.} PROCESSING {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PENDING_TAX_SUBMISSION {Submit your tax documents to receive your rewards} PENDING_PARTNER_CREATION {Complete cash payout setup to receive your rewards} DENIED {Denied on} EXPIRED {Reward expired on} other {Not available} }", rewardReceivedText: "Reward received on", hideDetails: false, }; -export const CashReward = () => { - return ( - - ); -}; +// ============================================================ +// STATE PRECEDENCE LADDER — one story per rule +// (See referral-table-rewards-column-new.feature § 2) +// ============================================================ -export const PayoutApproved = () => { - return ( - - ); -}; +// 1. Fraud check denied the referral → state is DENIED +export const RewardsCellFraudDenied = () => ( + +); -export const PayoutProcessing = () => { - return ( - - ); -}; +// 2. Fraud check is still pending review → state is PENDING_REVIEW +export const RewardsCellFraudPendingReview = () => ( + +); -export const PayoutFailed = () => { - return ( - - ); -}; +// 3a. Cash reward but the user has not connected an Impact partner → shows the partner-setup prompt +export const RewardsCellPartnerNotCreatedSetupNotStarted = () => ( + +); -export const PayoutCancelled = () => { - return ( - ( + - ); -}; + }, + ]} + taxConnection={connectedNoWithdrawalSettings} + {...defaultProps} + > +); -export const PendingTaxReview = () => { - return ( - ( + - ); -}; + }, + ]} + taxConnection={fullySetupTaxConnection} + {...defaultProps} + > +); -export const PendingNewTaxForm = () => { - return ( - ( + - ); -}; + }, + ]} + taxConnection={fullySetupTaxConnection} + {...defaultProps} + > +); -export const PendingTaxSubmission = () => { - return ( - ( + +); + +// 7. Partner funds transfer has been transferred → state is PAYOUT_APPROVED +export const RewardsCellPayoutApproved = () => ( + - ); -}; + }, + ]} + taxConnection={fullySetupTaxConnection} + {...defaultProps} + > +); -export const PendingPartnerCreation = () => { - return ( - ( + +); + +// 9. Reward is pending US_TAX and the partner is not connected → shows the partner-setup prompt +export const RewardsCellUsTaxPartnerNotConnected = () => ( + +); + +// 10. Partner is connected but has not submitted any tax documents → shows the submit-tax-docs prompt +export const RewardsCellPendingTaxSubmission = () => ( + +); + +// 11. Partner's tax document is inactive (rejected) → shows the submit-a-new-form prompt +export const RewardsCellPendingNewTaxForm = () => ( + - ); -}; + }, + }} + {...defaultProps} + > +); -export const PendingW9 = () => { - return ( - ( + - ); -}; + }, + }} + {...defaultProps} + > +); + +// 13. Partner has an active tax form but has not configured withdrawal settings → shows the partner-setup prompt +export const RewardsCellExistingTaxFormNoWithdrawalSettings = () => ( + +); + +// 14. Reward has MISSING_PAYOUT_CONFIGURATION pending reason → shows the partner-setup prompt +export const RewardsCellMissingPayoutConfiguration = () => ( + +); + +// 18. Reward does not match any precedence rule → state is undefined (Not available) +export const RewardsCellNoMatchingRule = () => ( + +); + +// ============================================================ +// Aliases kept for backwards compatibility with existing references +// ============================================================ + +export const CashReward = RewardsCellPayoutApproved; +export const PayoutApproved = RewardsCellPayoutApproved; +export const PayoutProcessing = RewardsCellPayoutProcessing; +export const PayoutFailed = RewardsCellPayoutFailed; +export const PayoutCancelled = RewardsCellPayoutCancelled; +export const PendingTaxReview = RewardsCellPendingTaxReview; +export const PendingNewTaxForm = RewardsCellPendingNewTaxForm; +export const PendingTaxSubmission = RewardsCellPendingTaxSubmission; +export const PartnerNotCreatedSetupNotStarted = + RewardsCellPartnerNotCreatedSetupNotStarted; +export const PartnerCreatedSetupStartedButIncomplete = + RewardsCellPartnerCreatedSetupStartedButIncomplete; +export const PendingW9 = RewardsCellPendingW9Required; diff --git a/packages/mint-components/src/components/sqm-referral-table/cells/sqm-referral-table-rewards-cell.tsx b/packages/mint-components/src/components/sqm-referral-table/cells/sqm-referral-table-rewards-cell.tsx index 45478a51a7..a02ea60a24 100644 --- a/packages/mint-components/src/components/sqm-referral-table/cells/sqm-referral-table-rewards-cell.tsx +++ b/packages/mint-components/src/components/sqm-referral-table/cells/sqm-referral-table-rewards-cell.tsx @@ -17,7 +17,7 @@ export class ReferralTableRewardsCell { @Prop() statusText: string = "{status, select, AVAILABLE {Available} CANCELLED {Cancelled} PENDING {Pending} PENDING_REVIEW {Pending} PAYOUT_APPROVED {Payout Approved} PROCESSING {Payment Processing} PAYOUT_FAILED {Payout Failed} PAYOUT_CANCELLED {Payout Cancelled} PENDING_TAX_REVIEW {Pending} PENDING_NEW_TAX_FORM {Pending} PENDING_TAX_SUBMISSION {Pending} PENDING_PARTNER_CREATION {Pending} DENIED {Denied} EXPIRED {Expired} REDEEMED {Redeemed} other {Not available} }"; @Prop() statusLongText: string = - "{status, select, AVAILABLE {Reward expiring on} CANCELLED {Reward cancelled on} PENDING {Available on} PENDING_REVIEW {Pending since} PAYOUT_APPROVED {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PAYOUT_FAILED {Payout failed due to a fulfillment issue and is currently being retried.} PAYOUT_CANCELLED {If you think this is a mistake, contact our Support team.} PENDING_TAX_REVIEW {Awaiting tax form review} PENDING_NEW_TAX_FORM {Invalid tax form. Submit a new form to receive your rewards.} PROCESSING {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PENDING_TAX_SUBMISSION {Submit your tax documents to receive your rewards} PENDING_PARTNER_CREATION {Complete your tax and cash payout setup to receive your rewards} DENIED {Denied on} EXPIRED {Reward expired on} other {Not available} }"; + "{status, select, AVAILABLE {Reward expiring on} CANCELLED {Reward cancelled on} PENDING {Available on} PENDING_REVIEW {Pending since} PAYOUT_APPROVED {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PAYOUT_FAILED {Payout failed due to a fulfillment issue and is currently being retried.} PAYOUT_CANCELLED {If you think this is a mistake, contact our Support team.} PENDING_TAX_REVIEW {Awaiting tax form review} PENDING_NEW_TAX_FORM {Invalid tax form. Submit a new form to receive your rewards.} PROCESSING {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PENDING_TAX_SUBMISSION {Submit your tax documents to receive your rewards} PENDING_PARTNER_CREATION {Complete your cash payout setup to receive your rewards} DENIED {Denied on} EXPIRED {Reward expired on} other {Not available} }"; @Prop() fuelTankText: string; @Prop() rewardReceivedText: string; @Prop() expiringText: string; @@ -171,12 +171,24 @@ export class ReferralTableRewardsCell { return "DENIED"; } + const isCashReward = reward.rewardedCash; + if (isCashReward) { + if ( + !this.taxConnection?.connected || + (this.taxConnection?.connected && + !this.taxConnection?.publisher?.withdrawalSettings) + ) + return "PENDING_PARTNER_CREATION"; + } + const partnerFundsStatus = reward.partnerFundsTransfer?.status; if (reward.partnerFundsTransfer) { if (partnerFundsStatus === "REVERSED") return "PAYOUT_CANCELLED"; if (partnerFundsStatus === "OVERDUE") return "PAYOUT_FAILED"; + } + if (reward.partnerFundsTransfer) { if ( reward.partnerFundsTransfer.dateScheduled && reward.partnerFundsTransfer.dateScheduled > Date.now() @@ -213,6 +225,19 @@ export class ReferralTableRewardsCell { if (!taxConnection?.publisher?.withdrawalSettings) return "PENDING_PARTNER_CREATION"; } + + // Fallback: when rewardStatus() forced PENDING because the user is + // connected but hasn't set up withdrawal settings (no pendingReasons + // were returned by the API, e.g. for credit rewards with a PFT). + if (reward.rewardedCash) { + if ( + !taxConnection?.connected || + (taxConnection?.connected && + !taxConnection?.publisher?.withdrawalSettings) + ) + return "PENDING_PARTNER_CREATION"; + } + if (reward?.pendingReasons?.includes("MISSING_PAYOUT_CONFIGURATION")) { return "PENDING_PARTNER_CREATION"; } @@ -347,7 +372,7 @@ export class ReferralTableRewardsCell { )} - {state === "PAYOUT_APPROVED" && ( + {state === "" && (
{statusText}
@@ -357,6 +382,11 @@ export class ReferralTableRewardsCell { {statusText} )} + {state === "PAYOUT_APPROVED" && ( +
+ {statusText} +
+ )} {state === "PAYOUT_FAILED" && (
{statusText} diff --git a/packages/mint-components/src/components/sqm-referral-table/columns/referral-table-rewards-column.feature b/packages/mint-components/src/components/sqm-referral-table/columns/referral-table-rewards-column.feature index 982a5d960f..0f682645d2 100644 --- a/packages/mint-components/src/components/sqm-referral-table/columns/referral-table-rewards-column.feature +++ b/packages/mint-components/src/components/sqm-referral-table/columns/referral-table-rewards-column.feature @@ -2,11 +2,38 @@ Feature: Referral Table Reward Column Shows the reward associated with each referral - Background: + Background: Given the status column is included in the referral table And at least one referral exists + @motivating + Scenario Outline: State precedence ladder + Given a reward, its referral's fraud state, and the user's tax connection + Then is produced + And the , , and is determined in the following : + Examples: + | order | rule | resultingState | resultingBadgeText | resultingDescriptionBody | + | 1 | referral.fraudData.moderationStatus is "DENIED" | DENIED | Denied | Denied on Jan 1, 2026. Contact support. | + | 2 | referral.fraudData.moderationStatus is "PENDING" | PENDING_REVIEW | Pending | Pending since Jan 1, 2026 | + | 3 | reward.rewardedCash is true AND impactConnection is NOT connected | PENDING_PARTNER_CREATION | Pending | Complete your tax and cash payout setup to receive your rewards | + | 4 | reward.rewardedCash is true AND impactConnection is connected AND publisher.withdrawalSettings is missing | PENDING_PARTNER_CREATION | Pending | Complete your tax and cash payout setup to receive your rewards | + | 5 | partnerFundsTransfer.status is "REVERSED" | PAYOUT_CANCELLED | Payout Cancelled | If you think this is a mistake, contact our Support team. | + | 6 | partnerFundsTransfer.status is "OVERDUE" | PAYOUT_FAILED | Payout Failed | Payout failed due to a fulfillment issue and is currently being retried. | + | 7 | partnerFundsTransfer.dateScheduled is in the future | PROCESSING | Payment Processing | Processing until Jan 1, 2026. Payout is then scheduled based on your settings. | + | 8 | partnerFundsTransfer.status is "TRANSFERRED" / "NOT_YET_DUE", or dateScheduled has passed without REVERSED/OVERDUE | PAYOUT_APPROVED | Payout Approved | Processing until Jan 1, 2026. Payout is then scheduled based on your settings. | + | 9 | reward.pendingReasons includes "US_TAX" AND impactConnection.taxHandlingEnabled is false | PENDING | Pending | Available on Jan 1, 2026 (if dateScheduledFor set; else no body line) | + | 10 | reward.pendingReasons includes "US_TAX" AND impactConnection.connected is false | PENDING_PARTNER_CREATION | Pending | Complete your tax and cash payout setup to receive your rewards | + | 11 | reward.pendingReasons includes "US_TAX" AND publisher.requiredTaxDocumentType is set AND publisher.currentTaxDocument is missing | PENDING_TAX_SUBMISSION | Pending | Submit your tax documents to receive your rewards | + | 12 | reward.pendingReasons includes "US_TAX" AND publisher.currentTaxDocument.status is "INACTIVE" / "INVALID_W9_ELECTRONIC_DOCUMENT" / "INVALID_W9_ELECTRONIC_DOCUMENT_CHECK_INTERNAL" | PENDING_NEW_TAX_FORM | Pending | Invalid tax form. Submit a new form to receive your rewards. | + | 13 | reward.pendingReasons includes "US_TAX" AND publisher.currentTaxDocument.status is "NOT_VERIFIED" | PENDING_TAX_REVIEW | Pending | Awaiting tax form review | + | 14 | reward.pendingReasons includes "US_TAX" AND publisher.currentTaxDocument.status is "ACTIVE" AND publisher.withdrawalSettings missing | PENDING_PARTNER_CREATION | Pending | Complete your tax and cash payout setup to receive your rewards | + | 15 | reward.pendingReasons includes "MISSING_PAYOUT_CONFIGURATION" | PENDING_PARTNER_CREATION | Pending | Complete your tax and cash payout setup to receive your rewards | + | 16 | statuses includes "REDEEMED" | REDEEMED | Redeemed | (no state-specific body line) | + | 17 | statuses includes "CANCELLED" | CANCELLED | Cancelled | Reward cancelled on Jan 1, 2026 | + | 18 | statuses includes "EXPIRED" | EXPIRED | Expired | Reward expired on Jan 1, 2026 | + | 19 | statuses includes "PENDING" | PENDING | Pending (or "Pending for {date}" overlay if dateScheduledFor set) | Available on Jan 1, 2026 (if dateScheduledFor set; else no body line) | + | 20 | statuses includes "AVAILABLE" | AVAILABLE | Available (plus info pill "{expiringText} {relative}" if dateExpires set) | Reward expiring on Jan 1, 2026 | @motivating @ui Scenario Outline: The referral reward and its status are shown for each referral @@ -15,24 +42,24 @@ Feature: Referral Table Reward Column And the status of each reward is displayed as a pill in the cell And rewards of have a pill with the text - Examples: - | status | pillColour | statusText | - | Available | success | Available | - | Pending | warning | Pending | - | Pending Fraud Review | warning | Pending | - | Pending Tax Review | warning | Pending | - | Pending New Tax Form | warning | Pending | - | Pending Tax Submission | warning | Pending | - | Pending Partner Creation | warning | Pending | - | Cancelled | danger | Cancelled | - | Payout Overdue | danger | Payout Failed | - | Payout Reversed | danger | Payout Cancelled | - | Expired | danger | Expired | - | Denied | danger | Denied | - | Redeemed | primary | Redeemed | - | Payout Transferred | primary | Payout Approved | - | Payout Not Yet Due | primary | Payout Approved | - | Payout Processing | primary | Payment Processing | + Examples: + | status | pillColour | statusText | + | Available | success | Available | + | Pending | warning | Pending | + | Pending Fraud Review | warning | Pending | + | Pending Tax Review | warning | Pending | + | Pending New Tax Form | warning | Pending | + | Pending Tax Submission | warning | Pending | + | Pending Partner Creation | warning | Pending | + | Cancelled | danger | Cancelled | + | Payout Overdue | danger | Payout Failed | + | Payout Reversed | danger | Payout Cancelled | + | Expired | danger | Expired | + | Denied | danger | Denied | + | Redeemed | primary | Redeemed | + | Payout Transferred | primary | Payout Approved | + | Payout Not Yet Due | primary | Payout Approved | + | Payout Processing | primary | Payment Processing | @motivating Scenario: The pending period of a referral reward is shown inside the pill if scheduled @@ -41,11 +68,11 @@ Feature: Referral Table Reward Column Then the status pill of the reward will contain the text "Pending for " And the date is localized to the user's locale - Examples: + Examples: | relativeTime | - | 2 days | - | 1 week | - | 3 months | + | 2 days | + | 1 week | + | 3 months | @motivating Scenario: The expiry date of a reward is shown in a secondary pill @@ -54,10 +81,10 @@ Feature: Referral Table Reward Column Then an additional info pill will appear next to the status pill with the text "Expiring in " And the date is localized to the user's locale - Examples: + Examples: | relativeTime | - | 2 days | - | 1 week | + | 2 days | + | 1 week | @motivating @ui Scenario Outline: Expanding the reward cell shows specific detailed status messages @@ -67,28 +94,28 @@ Feature: Referral Table Reward Column Then the detail text displays Examples: Payout States - | status | detailMessage | - | Payout Approved | Processing until {date}. Payout is then scheduled based on your settings. | - | Payout Failed | Payout failed due to a fulfillment issue and is currently being retried. | - | Payout Cancelled | If you think this is a mistake, contact our Support team. | - | Processing | Processing until {date}. Payout is then scheduled based on your settings. | + | status | detailMessage | + | Payout Approved | Processing until {date}. Payout is then scheduled based on your settings. | + | Payout Failed | Payout failed due to a fulfillment issue and is currently being retried. | + | Payout Cancelled | If you think this is a mistake, contact our Support team. | + | Processing | Processing until {date}. Payout is then scheduled based on your settings. | Examples: Tax Compliance States - | status | detailMessage | - | Pending Tax Review | Awaiting tax form review | - | Pending New Tax Form | Invalid tax form. Submit a new form to receive your rewards. | - | Pending Tax Submission | Submit your tax documents to receive your rewards | - | Pending Partner Creation | Complete your tax and cash payout setup to receive your rewards | + | status | detailMessage | + | Pending Tax Review | Awaiting tax form review | + | Pending New Tax Form | Invalid tax form. Submit a new form to receive your rewards. | + | Pending Tax Submission | Submit your tax documents to receive your rewards | + | Pending Partner Creation | Complete your tax and cash payout setup to receive your rewards | Examples: Standard States - | status | detailMessage | - | Available | Reward expiring on | - | Cancelled | Reward cancelled on | - | Pending | Available on | - | Pending Review | Pending since | - | Denied | Denied on | - | Expired | Reward expired on | - | Redeemed | Redeemed | + | status | detailMessage | + | Available | Reward expiring on | + | Cancelled | Reward cancelled on | + | Pending | Available on | + | Pending Review | Pending since | + | Denied | Denied on | + | Expired | Reward expired on | + | Redeemed | Redeemed | @motivating Scenario: Fuel Tank codes are displayed in the expanded view @@ -114,9 +141,9 @@ Feature: Referral Table Reward Column And the status is displayed in a pill Examples: - | pftState | status | text | pillColour | - | transfer date is in the future | PROCESSING | Payment Processing | primary | - | successfully transferred to payment provider | PAYOUT_TRANSFERRED | Payout Approved | primary | - | approved but payout scheduled date not yet arrived | PAYOUT_NOT_YET_DUE | Payout Approved | primary | - | failed due to fulfillment issue and retrying | PAYOUT_OVERDUE | Payout Failed | danger | - | reversed or cancelled after being processed | PAYOUT_REVERSED | Payout Cancelled | danger | + | pftState | status | text | pillColour | + | transfer date is in the future | PROCESSING | Payment Processing | primary | + | successfully transferred to payment provider | PAYOUT_TRANSFERRED | Payout Approved | primary | + | approved but payout scheduled date not yet arrived | PAYOUT_NOT_YET_DUE | Payout Approved | primary | + | failed due to fulfillment issue and retrying | PAYOUT_OVERDUE | Payout Failed | danger | + | reversed or cancelled after being processed | PAYOUT_REVERSED | Payout Cancelled | danger | diff --git a/packages/mint-components/src/components/sqm-rewards-table/RewardsTableCell.stories.tsx b/packages/mint-components/src/components/sqm-rewards-table/RewardsTableCell.stories.tsx index a8d3655d1d..40a46962af 100644 --- a/packages/mint-components/src/components/sqm-rewards-table/RewardsTableCell.stories.tsx +++ b/packages/mint-components/src/components/sqm-rewards-table/RewardsTableCell.stories.tsx @@ -138,6 +138,7 @@ const cashReward = { }, exchangedRewardRedemptionTransaction: null, pendingReasons: [], + rewardedCash: true, }; const taxConnection: ImpactConnection = { diff --git a/packages/mint-components/src/components/sqm-rewards-table/TaxAndCashRewardsTable.stories.tsx b/packages/mint-components/src/components/sqm-rewards-table/TaxAndCashRewardsTable.stories.tsx index b90c7b5af8..bfc5907082 100644 --- a/packages/mint-components/src/components/sqm-rewards-table/TaxAndCashRewardsTable.stories.tsx +++ b/packages/mint-components/src/components/sqm-rewards-table/TaxAndCashRewardsTable.stories.tsx @@ -5,13 +5,13 @@ import { StatusCellPayoutSent, StatusCellPayoutFailed, StatusCellPendingNewTaxForm, - StatusCellPendingPartnerCreation, StatusCellPendingTaxReview, StatusCellPendingTaxSubmission, StatusCellPayoutProcessing, CashReward, StatusCellPendingW9, StatusCellPayoutCancelled, + StatusCellPartnerNotCreatedSetupNotStarted, } from "./TaxAndCashRewardsTableCell.stories"; export default { @@ -84,7 +84,7 @@ const r_pending_tax_review = [ const r_pending_partner_creation = [ , - , + , , , ]; diff --git a/packages/mint-components/src/components/sqm-rewards-table/TaxAndCashRewardsTableCell.stories.tsx b/packages/mint-components/src/components/sqm-rewards-table/TaxAndCashRewardsTableCell.stories.tsx index 994442ef8f..4e6ae0ed0b 100644 --- a/packages/mint-components/src/components/sqm-rewards-table/TaxAndCashRewardsTableCell.stories.tsx +++ b/packages/mint-components/src/components/sqm-rewards-table/TaxAndCashRewardsTableCell.stories.tsx @@ -5,6 +5,10 @@ export default { title: "Components/Tax And Cash Rewards Table Cell", }; +// Reusable timestamps (current date is May 2026) +const PAST = 1640995200000; // Jan 1, 2022 +const FUTURE = 2779257600000; // ~2058 + const cashReward = { id: "68c34fd98a6cb4f5f8394084", type: "CREDIT", @@ -24,13 +28,13 @@ const cashReward = { name: "Cash", }, name: null, - dateCreated: 1757630425085, - dateScheduledFor: 1757631025115, - dateGiven: 1757630737115, + dateCreated: PAST, + dateScheduledFor: null, + dateGiven: PAST, dateExpires: null, dateCancelled: null, - dateRedeemed: 1757630737115, - dateModified: 1757630737115, + dateRedeemed: null, + dateModified: PAST, rewardSource: "MANUAL" as const, fuelTankCode: null, fuelTankType: null, @@ -65,225 +69,385 @@ const cashReward = { }, referral: null, description: null, - statuses: ["REDEEMED"], + statuses: [], rewardRedemptionTransactions: { data: null, }, exchangedRewardRedemptionTransaction: null, pendingReasons: [], + rewardedCash: true, }; -const pending = { - statuses: ["PENDING"], -}; - -const payoutSent = { - statuses: ["PAYOUT_APPROVED"], -}; -const payoutFailed = { - statuses: ["PAYOUT_FAILED"], -}; -const payoutCancelled = { - statuses: ["PAYOUT_CANCELLED"], - dateCancelled: 1355612521321, -}; +// ============================================================ +// Reusable tax connections +// ============================================================ -const processingPFT = { - partnerFundsTransfer: { - id: "123", - status: null, - dateCreated: 1355612521321, - dateScheduled: 2779257600000, - dateTransferred: null, +const fullySetupTaxConnection: ImpactConnection = { + connected: true, + taxHandlingEnabled: true, + connectionStatus: "COMPLETED", + publisher: { + requiredTaxDocumentType: "W9", + currentTaxDocument: { + status: "ACTIVE", + type: "W9", + dateCreated: PAST, + }, + withdrawalSettings: { paymentMethod: "BANK_TRANSFER" }, + payoutsAccount: null, }, }; -const taxConnection: ImpactConnection = { +const connectedNoWithdrawalSettings: ImpactConnection = { connected: true, taxHandlingEnabled: true, + connectionStatus: "COMPLETED", publisher: { - requiredTaxDocumentType: "W8BEN", + requiredTaxDocumentType: "W9", currentTaxDocument: { - status: "NOT_VERIFIED", - type: "W8BEN", - dateCreated: 321321487, - }, - withdrawalSettings: { - paymentMethod: "BANK_TRANSFER", + status: "ACTIVE", + type: "W9", + dateCreated: PAST, }, + withdrawalSettings: null, payoutsAccount: null, }, }; -export const CashReward = () => { - return ( - - ); +const notConnectedTaxConnection: ImpactConnection = { + connected: false, + taxHandlingEnabled: true, + connectionStatus: "NOT_STARTED", + publisher: null, }; -export const StatusCellPendingTaxReview = () => { - return ( - - ); -}; +// ============================================================ +// Reward Cell (kept from original) +// ============================================================ -export const StatusCellPendingNewTaxForm = () => { - return ( - - ); -}; +export const CashReward = () => ( + +); -export const StatusCellPendingTaxSubmission = () => { - return ( - - ); -}; +// ============================================================ +// STATUS PRECEDENCE LADDER — one story per rule +// (See sqm-rewards-table-status-column-new.feature § 2) +// ============================================================ -export const StatusCellPendingPartnerCreation = () => { - return ( - - ); -}; +// 1. Fraud check denied the referral → status is Denied +export const StatusCellFraudDenied = () => ( + +); -export const StatusCellPendingW9 = () => { - return ( - - ); -}; +// 2. Fraud check is still pending review → status is Pending Review +export const StatusCellFraudPendingReview = () => ( + +); -export const StatusCellPayoutSent = () => { - return ( - ( + +); + +// 4. Partner funds transfer is overdue → status is Payout Failed +export const StatusCellPayoutFailed = () => ( + +); + +// 5. Connected partner has not finished withdrawal settings setup → status is Pending +export const StatusCellPartnerCreatedSetupStartedButIncomplete = () => ( + +); + +// Reward is pending US_TAX and the partner has not been created yet → shows the partner-setup prompt +export const StatusCellPartnerNotCreatedSetupNotStarted = () => ( + +); + +// 6. Reward has MISSING_PAYOUT_CONFIGURATION pending reason and no withdrawal settings → status is Pending +export const StatusCellMissingPayoutConfiguration = () => ( + +); + +// 7. Partner funds transfer is scheduled for a future date → status is Processing +export const StatusCellPayoutProcessing = () => ( + +); + +// 8. Partner funds transfer has been transferred → status is Payout Approved +export const StatusCellPayoutApproved = () => ( + +); + +// 9. Reward has a cancellation date set → status is Cancelled +export const StatusCellRewardCancelled = () => ( + +); + +// 10. Reward statuses include EXPIRED → status is Expired +export const StatusCellRewardExpired = () => ( + +); + +// 11. Reward is pending and scheduled for a future date → status is Pending with the scheduled date shown +export const StatusCellPendingScheduled = () => ( + +); + +// 12. Reward does not match any precedence rule → no badge text, no description +export const StatusCellNoMatchingRule = () => ( + +); + +// ============================================================ +// US_TAX getTaxPendingReasons branches (Pending Description Resolution § 5) +// ============================================================ + +// Reward is pending US_TAX but tax handling is disabled → shows "W-9 required" +export const StatusCellPendingW9Required = () => ( + +); + +// Partner is connected but has not submitted any tax documents → shows the submit-tax-docs prompt +export const StatusCellPendingTaxSubmission = () => ( + +); + +// Partner's tax document is inactive (rejected) → shows the submit-a-new-form prompt +export const StatusCellPendingNewTaxForm = () => ( + - ); -}; + }, + }} + > +); -export const StatusCellPayoutFailed = () => { - return ( - ( + - ); -}; + }, + }} + > +); -export const StatusCellPayoutProcessing = () => { - return ( - - ); -}; +// Partner has an active tax form but has not configured withdrawal settings → shows the partner-setup prompt +export const StatusCellExistingTaxFormNoWithdrawalSettings = () => ( + +); -export const StatusCellPayoutCancelled = () => { - return ( - - ); -}; +// Partner is connected, no tax form is required, but withdrawal settings are not submitted → shows the partner-setup prompt +export const StatusCellConnectedNoTaxRequiredNoWithdrawalSettings = () => ( + +); + +// Aliases kept for the table-level stories file +export const StatusCellPayoutSent = StatusCellPayoutApproved; +export const StatusCellPendingW9 = StatusCellPendingW9Required; diff --git a/packages/mint-components/src/components/sqm-rewards-table/cells/readme.md b/packages/mint-components/src/components/sqm-rewards-table/cells/readme.md index 7a516afdd9..e771957ab7 100644 --- a/packages/mint-components/src/components/sqm-rewards-table/cells/readme.md +++ b/packages/mint-components/src/components/sqm-rewards-table/cells/readme.md @@ -17,7 +17,7 @@ | `payoutFailed` | `payout-failed` | | `string` | `"Payout failed due to a fulfillment issue and is currently being retried."` | | `payoutProcessing` | `payout-processing` | | `string` | `"Processing until {date}. Payout is then scheduled based on your settings."` | | `pendingNewTaxForm` | `pending-new-tax-form` | | `string` | `"Invalid tax form. Submit a new form to receive your rewards."` | -| `pendingPartnerCreation` | `pending-partner-creation` | | `string` | `"Complete your tax and cash payout setup to receive your rewards."` | +| `pendingPartnerCreation` | `pending-partner-creation` | | `string` | `"Complete your cash payout setup to receive your rewards."` | | `pendingReviewText` | `pending-review-text` | | `string` | `"Awaiting review"` | | `pendingScheduled` | `pending-scheduled` | | `string` | `"Until"` | | `pendingTaxReview` | `pending-tax-review` | | `string` | `"Awaiting tax form review."` | diff --git a/packages/mint-components/src/components/sqm-rewards-table/cells/sqm-rewards-table-status-cell.tsx b/packages/mint-components/src/components/sqm-rewards-table/cells/sqm-rewards-table-status-cell.tsx index 7f2c42ca67..ecc050a9d4 100644 --- a/packages/mint-components/src/components/sqm-rewards-table/cells/sqm-rewards-table-status-cell.tsx +++ b/packages/mint-components/src/components/sqm-rewards-table/cells/sqm-rewards-table-status-cell.tsx @@ -81,7 +81,7 @@ export class RewardTableStatusCell { @Prop() pendingTaxSubmission: string = "Submit your tax documents to receive your rewards."; @Prop() pendingPartnerCreation: string = - "Complete your tax and cash payout setup to receive your rewards."; + "Complete your cash payout setup to receive your rewards."; @Prop() pendingScheduled: string = "Until"; @Prop() pendingUnhandled: string = "Fulfillment error"; @Prop() pendingReviewText: string = "Awaiting review"; @@ -101,16 +101,30 @@ export class RewardTableStatusCell { const integrationOrFueltankReward = reward.type === "INTEGRATION" || reward.type === "FUELTANK"; + // AL: TODO Scott said we should change this to use pendingReasons instead of fraudStatus - probably dont want to change this for backwards compatibility const fraudStatus = reward.referral?.fraudData?.moderationStatus; if (fraudStatus === "DENIED") return "DENIED"; if (fraudStatus === "PENDING") return "PENDING_REVIEW"; + const isCashReward = reward.rewardedCash; + + console.log(this.reward, "reward in status cell"); + + // pft can now be created before withdrawal settings exist + if (isCashReward) { + if ( + !this.taxConnection?.connected || + (this.taxConnection?.connected && + !this.taxConnection?.publisher?.withdrawalSettings) + ) + return "PENDING"; + } + const partnerTransferStatus = reward.partnerFundsTransfer?.status; if (reward.partnerFundsTransfer) { if (partnerTransferStatus === "REVERSED") return "PAYOUT_CANCELLED"; if (partnerTransferStatus === "OVERDUE") return "PAYOUT_FAILED"; - if ( reward.partnerFundsTransfer.dateScheduled && reward.partnerFundsTransfer.dateScheduled > Date.now() @@ -171,13 +185,26 @@ export class RewardTableStatusCell { if (status === "INACTIVE") return this.pendingNewTaxForm; if (status === "NOT_VERIFIED") return this.pendingTaxReview; } - if (!taxConnection?.publisher?.withdrawalSettings) + if (!taxConnection?.publisher?.withdrawalSettings) { return this.pendingPartnerCreation; + } } if (reward?.pendingReasons?.includes("MISSING_PAYOUT_CONFIGURATION")) { return this.pendingPartnerCreation; } + // Fallback: when rewardStatus() forced PENDING because the user is + // connected but hasn't set up withdrawal settings (no pendingReasons + // were returned by the API, e.g. for credit rewards with a PFT). + if (reward.rewardedCash) { + if ( + !taxConnection?.connected || + (taxConnection?.connected && + !taxConnection?.publisher?.withdrawalSettings) + ) + return this.pendingPartnerCreation; + } + return ""; } diff --git a/packages/mint-components/src/components/sqm-rewards-table/columns/sqm-rewards-table-status-column.feature b/packages/mint-components/src/components/sqm-rewards-table/columns/sqm-rewards-table-status-column.feature index af4cbd3b08..e8e7aae672 100644 --- a/packages/mint-components/src/components/sqm-rewards-table/columns/sqm-rewards-table-status-column.feature +++ b/packages/mint-components/src/components/sqm-rewards-table/columns/sqm-rewards-table-status-column.feature @@ -41,6 +41,50 @@ Feature: Reward Table Status Column | PENDING_PARTNER_CREATION | Pending | warning | | DENIED | Denied | danger | + @motivating + Scenario Outline: Status precedence ladder + Given a reward, its referral fraud state, the user's Impact tax connection + Then is produced + And the , , and is determined in the following : + + Examples: + | order | rule | resultingStatus | resultingBadgeText | resultingDescription | + | 1 | referral.fraudData.moderationStatus is "DENIED" | DENIED | Denied | Detected self-referral | + | 2 | referral.fraudData.moderationStatus is "PENDING" | PENDING_REVIEW | Pending | Awaiting review | + | 3 | reward.rewardedCash is true AND impactConnection is NOT connected | PENDING | Pending | Complete your cash payout setup to receive your rewards. | + | 4 | reward.rewardedCash is true AND impactConnection is connected AND publisher.withdrawalSettings is missing | PENDING | Pending | Complete your cash payout setup to receive your rewards. | + | 5 | partnerFundsTransfer.status is "REVERSED" | PAYOUT_CANCELLED | Payout Cancelled | If you think this is a mistake, contact our Support team. | + | 6 | partnerFundsTransfer.status is "OVERDUE" | PAYOUT_FAILED | Payout Failed | Payout failed due to a fulfillment issue and is currently being retried. | + | 7 | reward.pendingReasons includes "MISSING_PAYOUT_CONFIGURATION" AND publisher.withdrawalSettings is missing | PENDING | Pending | Complete your cash payout setup to receive your rewards. | + | 8 | partnerFundsTransfer.dateScheduled is in the future | PROCESSING | Payment Processing | Processing until Jan 1, 2026. Payout is then scheduled based on your settings. | + | 9 | partnerFundsTransfer.status is "TRANSFERRED" / "NOT_YET_DUE", or dateScheduled has passed without REVERSED/OVERDUE | PAYOUT_APPROVED | Payout Approved | Payout approved and scheduled for payment based on your settings. | + | 10 | reward.dateCancelled is set | CANCELLED | Cancelled | Jan 1, 2026 | + | 11 | reward.statuses includes "EXPIRED" | EXPIRED | Expired | Jan 1, 2026 | + | 12 | reward.statuses includes "PENDING" | PENDING | Pending | Until Jan 1, 2026 | + | 13 | statuses includes "REDEEMED" | REDEEMED | Redeemed | Jan 1, 2026 | + | 14 | statuses includes "AVAILABLE" | AVAILABLE | Available | Expires Jan 1, 2026 | + | 15 | statuses includes "CANCELLED" | CANCELLED | Cancelled | Jan 1, 2026 | +# This spec should probably be inserted in to the above spec after rule 9 because it gets invoked when the reward state is pending +# and does not hit the rules that output pending from above + + @motivating + Scenario Outline: PENDING description precedence ladder + Given a PENDING reward, its pendingReasons, and the user's Impact tax connection + Then is produced + And the , , and is determined in the following order: + + Examples: + | order | rule | resultingStatus | resultingBadgeText | resultingDescription | + | 1 | pendingReasons includes "US_TAX" AND impactConnection.taxHandlingEnabled is false | PENDING | Pending | W-9 required | + | 2 | pendingReasons includes "US_TAX" AND impactConnection is NOT connected | PENDING | Pending | Complete your tax and cash payout setup to receive your rewards. | + | 3 | pendingReasons includes "US_TAX" AND publisher.requiredTaxDocumentType is set AND publisher.currentTaxDocument is missing | PENDING | Pending | Submit your tax documents to receive your rewards. | + | 4 | pendingReasons includes "US_TAX" AND publisher.requiredTaxDocumentType is set AND publisher.currentTaxDocument.status is "INACTIVE" | PENDING | Pending | Invalid tax form. Submit a new form to receive your rewards. | + | 5 | pendingReasons includes "US_TAX" AND publisher.requiredTaxDocumentType is set AND publisher.currentTaxDocument.status is "NOT_VERIFIED" | PENDING | Pending | Awaiting tax form review. | + | 6 | pendingReasons includes "US_TAX" AND publisher.withdrawalSettings is missing | PENDING | Pending | Complete your tax and cash payout setup to receive your rewards. | + | 7 | pendingReasons includes "MISSING_PAYOUT_CONFIGURATION" | PENDING | Pending | Complete your tax and cash payout setup to receive your rewards. | + | 8 | reward.rewardedCash is true AND impactConnection is NOT connected (fallback when no pendingReason returned) | PENDING | Pending | Complete your tax and cash payout setup to receive your rewards. | + | 9 | reward.rewardedCash is true AND impactConnection is connected AND publisher.withdrawalSettings is missing (fallback) | PENDING | Pending | Complete your tax and cash payout setup to receive your rewards. | + @motivating Scenario Outline: Reward status related information is displayed under status pills Given a user @@ -58,21 +102,21 @@ Feature: Reward Table Status Column | expired reward | | | cancelled reward | | | pending reward with a scheduled date | Until | - + Examples: Tax & Payout Rewards - | reward | text | - | pending reward due to W9 | W-9 required | - | pending reward due to fulfillment error | Fulfillment error | - | reward pending review of referral | Awaiting review | - | pending reward due to no connected Impact partner | Complete your tax and cash payout setup to receive your rewards. | - | pending reward due to an invalid tax document | Invalid tax form. Submit a new form to receive your rewards. | - | pending reward due to user required to submit a tax document | Submit your tax documents to receive your rewards. | - | pending reward due to tax document being in review | Awaiting tax form review. | - | reward whose payout is processing | Processing until . Payout is then scheduled based on your settings. | - | reward whose payout failed | Payout failed due to a fulfillment issue and is currently being retried. | - | reward whose payout was approved | Payout approved and scheduled for payment based on your settings. | - | reward whose payout was cancelled | If you think this is a mistake, contact our Support team. | - | cancelled reward from denied referral | Detected self-referral | + | reward | text | + | pending reward due to W9 | W-9 required | + | pending reward due to fulfillment error | Fulfillment error | + | reward pending review of referral | Awaiting review | + | pending reward due to no connected Impact partner | Complete your tax and cash payout setup to receive your rewards. | + | pending reward due to an invalid tax document | Invalid tax form. Submit a new form to receive your rewards. | + | pending reward due to user required to submit a tax document | Submit your tax documents to receive your rewards. | + | pending reward due to tax document being in review | Awaiting tax form review. | + | reward whose payout is processing | Processing until . Payout is then scheduled based on your settings. | + | reward whose payout failed | Payout failed due to a fulfillment issue and is currently being retried. | + | reward whose payout was approved | Payout approved and scheduled for payment based on your settings. | + | reward whose payout was cancelled | If you think this is a mistake, contact our Support team. | + | cancelled reward from denied referral | Detected self-referral | @minutia Scenario Outline: Tax-related reward statuses are based on the user's Impact tax connection @@ -128,9 +172,9 @@ Feature: Reward Table Status Column And under the pill is Examples: - | pftState | status | text | pillColour | description | - | transfer date is in the future | PROCESSING | Processing | warning | Processing until . Payout is then scheduled based on your settings. | - | successfully transferred to payment provider | PAYOUT_TRANSFERRED | Payout Approved | primary | Payout approved and scheduled for payment based on your settings. | - | approved but payout scheduled date not yet arrived | PAYOUT_NOT_YET_DUE | Payout Approved | primary | Payout approved and scheduled for payment based on your settings. | - | failed due to fulfillment issue and retrying | PAYOUT_OVERDUE | Payout Failed | danger | Payout failed due to a fulfillment issue and is currently being retried. | - | reversed or cancelled after being processed | PAYOUT_REVERSED | Payout Cancelled | danger | If you think this is a mistake, contact our Support team. | \ No newline at end of file + | pftState | status | text | pillColour | description | + | transfer date is in the future | PROCESSING | Processing | warning | Processing until . Payout is then scheduled based on your settings. | + | successfully transferred to payment provider | PAYOUT_TRANSFERRED | Payout Approved | primary | Payout approved and scheduled for payment based on your settings. | + | approved but payout scheduled date not yet arrived | PAYOUT_NOT_YET_DUE | Payout Approved | primary | Payout approved and scheduled for payment based on your settings. | + | failed due to fulfillment issue and retrying | PAYOUT_OVERDUE | Payout Failed | danger | Payout failed due to a fulfillment issue and is currently being retried. | + | reversed or cancelled after being processed | PAYOUT_REVERSED | Payout Cancelled | danger | If you think this is a mistake, contact our Support team. | diff --git a/packages/mint-components/src/components/sqm-rewards-table/useRewardsTable.tsx b/packages/mint-components/src/components/sqm-rewards-table/useRewardsTable.tsx index 12019131cd..8d68cd9dbf 100644 --- a/packages/mint-components/src/components/sqm-rewards-table/useRewardsTable.tsx +++ b/packages/mint-components/src/components/sqm-rewards-table/useRewardsTable.tsx @@ -60,6 +60,7 @@ const GET_REWARDS = gql` fuelTankCode fuelTankType currency + rewardedCash prettyValue(locale: $locale) prettyValueNumber: prettyValue( formatType: NUMBER_FORMATTED diff --git a/packages/mint-components/src/components/sqm-stencilbook/readme.md b/packages/mint-components/src/components/sqm-stencilbook/readme.md index ea883e9018..77969aaccf 100644 --- a/packages/mint-components/src/components/sqm-stencilbook/readme.md +++ b/packages/mint-components/src/components/sqm-stencilbook/readme.md @@ -104,6 +104,8 @@ - [sqm-lead-input-field](../sqm-lead-form) - [sqm-lead-dropdown-field](../sqm-lead-form) - [sqm-lead-form](../sqm-lead-form) +- [sqm-partner-info-modal](../sqm-partner-info-modal) +- [sqm-widget-verification](../sqm-widget-verification) ### Graph ```mermaid @@ -205,6 +207,8 @@ graph TD; sqm-stencilbook --> sqm-lead-input-field sqm-stencilbook --> sqm-lead-dropdown-field sqm-stencilbook --> sqm-lead-form + sqm-stencilbook --> sqm-partner-info-modal + sqm-stencilbook --> sqm-widget-verification sqm-form-message --> sqm-skeleton sqm-portal-register --> sqm-form-message sqm-portal-register --> sqm-password-field @@ -283,6 +287,10 @@ graph TD; sqm-payout-status-alert --> sqm-form-message sqm-lead-form --> sqm-form-message sqm-lead-form --> sqm-lead-input-field + sqm-partner-info-modal --> sqm-form-message + sqm-widget-verification --> sqm-partner-info-modal + sqm-widget-verification --> sqm-code-verification + sqm-widget-verification --> sqm-email-verification style sqm-stencilbook fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/packages/mint-components/src/components/sqm-stencilbook/sqm-stencilbook.tsx b/packages/mint-components/src/components/sqm-stencilbook/sqm-stencilbook.tsx index b52a78359a..f694d18bd8 100644 --- a/packages/mint-components/src/components/sqm-stencilbook/sqm-stencilbook.tsx +++ b/packages/mint-components/src/components/sqm-stencilbook/sqm-stencilbook.tsx @@ -108,6 +108,8 @@ import * as LeadFormDropdownField from "../sqm-lead-form/LeadFormDropdownField.s import * as LeadCheckboxField from "../sqm-lead-form/LeadCheckboxField.stories"; import * as Skeleton from "../sqm-skeleton/Skeleton.stories"; import * as UserInfoFormView from "../tax-and-cash/sqm-user-info-form/UserInfoFormView.stories"; +import * as PartnerInfoModal from "../sqm-partner-info-modal/PartnerInfoModal.stories"; +import * as WidgetVerification from "../sqm-widget-verification/WidgetVerification.stories"; import { ShadowViewAddon } from "../../ShadowViewAddon"; import { CucumberAddon } from "./CucumberAddon"; @@ -221,6 +223,8 @@ const stories = [ TaxAndCashRewardsTable, TaxAndCashReferralTableRewardsCell, TaxAndCashReferralTable, + PartnerInfoModal, + WidgetVerification, ]; /** diff --git a/packages/mint-components/src/components/sqm-text-span/sqm-text-span-view.tsx b/packages/mint-components/src/components/sqm-text-span/sqm-text-span-view.tsx index 472eaa27d4..49b97713c5 100644 --- a/packages/mint-components/src/components/sqm-text-span/sqm-text-span-view.tsx +++ b/packages/mint-components/src/components/sqm-text-span/sqm-text-span-view.tsx @@ -62,7 +62,7 @@ export function TextSpanView(props: TextSpanViewProps, children: VNode) { `; return ( - + + { + e.preventDefault(); + }} + onSl-hide={(e: any) => { + if (e.target?.tagName === "SL-DIALOG") { + e.preventDefault(); + } + }} + > +

{dialogLabel}

+ {renderStepContent()} +
); } @@ -215,7 +369,7 @@ function useDemoWidgetVerificationInternal(props: WidgetVerification) { key === "sqm-widget-verification" ? { ...prev, ...states[key] } : { ...prev, [`${key}_stateController`]: states[key] }, - {} + {}, ); const onVerification = () => { @@ -223,8 +377,14 @@ function useDemoWidgetVerificationInternal(props: WidgetVerification) { }; return deepmerge( - { showCode, onVerification, loading: false }, + { + showCode, + showPartnerModal: false, + onVerification, + onPartnerModalComplete: () => {}, + loading: false, + }, formatted || {}, - { arrayMerge: (_, a) => a } + { arrayMerge: (_, a) => a }, ); } diff --git a/packages/mint-components/src/components/sqm-widget-verification/useWidgetVerification.ts b/packages/mint-components/src/components/sqm-widget-verification/useWidgetVerification.ts index ec7442ce05..809784bb72 100644 --- a/packages/mint-components/src/components/sqm-widget-verification/useWidgetVerification.ts +++ b/packages/mint-components/src/components/sqm-widget-verification/useWidgetVerification.ts @@ -2,13 +2,14 @@ import { useLazyQuery, useParentState, useSetParent, - useUserIdentity, } from "@saasquatch/component-boilerplate"; import { useState } from "@saasquatch/stencil-hooks"; import { useEffect } from "@saasquatch/universal-hooks"; import { gql } from "graphql-request"; import { + PARTNER_CREATED_NAMESPACE, SHOW_CODE_NAMESPACE, + SHOW_PARTNER_MODAL_NAMESPACE, VERIFICATION_EMAIL_NAMESPACE, VERIFICATION_PARENT_NAMESPACE, } from "./keys"; @@ -25,23 +26,36 @@ const USER_LOOKUP = gql` email emailVerified } + impactConnection { + connected + } } } } `; export function useWidgetVerification() { - const userIdentity = useUserIdentity(); - const [showCode, setShowCode] = useParentState({ + const [showCode] = useParentState({ namespace: SHOW_CODE_NAMESPACE, initialValue: false, }); - const [email, setEmail] = useParentState({ + + useParentState({ namespace: VERIFICATION_EMAIL_NAMESPACE, - initialValue: userIdentity?.email, + initialValue: undefined, }); + const setContext = useSetParent(VERIFICATION_PARENT_NAMESPACE); const [loading, setLoading] = useState(true); + const [showPartnerModal, setShowPartnerModal] = useParentState({ + namespace: SHOW_PARTNER_MODAL_NAMESPACE, + initialValue: false, + }); + + const [partnerCreated, setPartnerCreated] = useParentState({ + namespace: PARTNER_CREATED_NAMESPACE, + initialValue: false, + }); const [fetch] = useLazyQuery(USER_LOOKUP); useEffect(() => { @@ -50,8 +64,19 @@ export function useWidgetVerification() { const res = await fetch({}); if (!res || res instanceof Error) throw new Error(); - if (res?.viewer?.emailVerified) setContext(true); - else if (res?.viewer?.managedIdentity?.emailVerified) setContext(true); + // Flow changed to send email -> verify code -> show early partner creation modal + const emailVerified = + res?.viewer?.emailVerified || + res?.viewer?.managedIdentity?.emailVerified; + const isConnected = res?.viewer?.impactConnection?.connected; + + if (isConnected) { + // Partner already created, show widget content + setContext(true); + } else if (emailVerified) { + // Email verified but no partner yet, show partner modal + setShowPartnerModal(true); + } } catch (e) { console.error("Could not fetch user information:", e); } finally { @@ -63,8 +88,24 @@ export function useWidgetVerification() { }, []); const onVerification = () => { + setShowPartnerModal(true); + }; + + const onPartnerModalComplete = () => { + setShowPartnerModal(false); + setPartnerCreated(false); setContext(true); }; - return { showCode, onVerification, loading }; + useEffect(() => { + if (partnerCreated) onPartnerModalComplete(); + }, [partnerCreated]); + + return { + showCode, + showPartnerModal, + onVerification, + onPartnerModalComplete, + loading, + }; } diff --git a/packages/mint-components/src/components/tax-and-cash/data.ts b/packages/mint-components/src/components/tax-and-cash/data.ts index 3f3b78e9e5..6719adc7be 100644 --- a/packages/mint-components/src/components/tax-and-cash/data.ts +++ b/packages/mint-components/src/components/tax-and-cash/data.ts @@ -71,6 +71,7 @@ export const GET_USER = gql` } impactConnection { connected + connectionStatus user { firstName lastName @@ -194,6 +195,7 @@ export type UserQuery = { impactConnection: null | { connected: boolean; user: null | ImpactUser; + connectionStatus: "NOT_STARTED" | "STARTED" | "COMPLETED"; publisher: null | ImpactPublisher; }; }; diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/formDefinitions.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/formDefinitions.tsx index 1b1b7e7406..def9c5cced 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/formDefinitions.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/formDefinitions.tsx @@ -11,6 +11,8 @@ export function getFormMap({ getValidationErrorMessage: (props: { type: "required" | "invalid"; label: string; + errorCode?: string; + fieldName?: string; }) => string; bankCountry?: string; }) { @@ -32,6 +34,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.beneficiaryAccountName?.type, label: props.text.beneficiaryAccountNameLabel, + errorCode: errors?.inputErrors?.beneficiaryAccountName?.errorCode, + fieldName: "beneficiaryAccountName", }), })} > @@ -50,6 +54,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.bankAccountType?.type, label: props.text.bankAccountTypeLabel, + errorCode: errors?.inputErrors?.bankAccountType?.errorCode, + fieldName: "bankAccountType", }), })} > @@ -77,6 +83,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.bankAccountNumber?.type, label: props.text.bankAccountNumberLabel, + errorCode: errors?.inputErrors?.bankAccountNumber?.errorCode, + fieldName: "bankAccountNumber", }), })} > @@ -97,6 +105,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.bankAccountNumber?.type, label: props.text.ibanLabel, + errorCode: errors?.inputErrors?.bankAccountNumber?.errorCode, + fieldName: "bankAccountNumber", }), })} > @@ -117,6 +127,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.swiftCode?.type, label: props.text.swiftCodeLabel, + errorCode: errors?.inputErrors?.swiftCode?.errorCode, + fieldName: "swiftCode", }), })} > @@ -152,6 +164,8 @@ export function getFormMap({ bankCountry, } ), + errorCode: errors?.inputErrors?.routingCode?.errorCode, + fieldName: "routingCode", }), })} > @@ -171,6 +185,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.bankName?.type, label: props.text.bankNameLabel, + errorCode: errors?.inputErrors?.bankName?.errorCode, + fieldName: "bankName", }), })} > @@ -189,6 +205,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.beneficiaryClassification?.type, label: props.text.classificationLabel, + errorCode: errors?.inputErrors?.beneficiaryClassification?.errorCode, + fieldName: "beneficiaryClassification", }), })} > @@ -222,6 +240,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.beneficiaryTaxPayerId?.type, label: props.text.taxPayerIdLabel, + errorCode: errors?.inputErrors?.taxPayerId?.errorCode, + fieldName: "taxPayerId", }), })} >, @@ -240,6 +260,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.beneficiaryClassification?.type, label: props.text.classificationCPFLabel, + errorCode: errors?.inputErrors?.beneficiaryClassification?.errorCode, + fieldName: "beneficiaryClassification", }), })} > @@ -262,6 +284,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.patronymicName?.type, label: props.text.patronymicNameLabel, + errorCode: errors?.inputErrors?.patronymicName?.errorCode, + fieldName: "patronymicName", }), })} > @@ -280,6 +304,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.voCode?.type, label: props.text.voCodeLabel, + errorCode: errors?.inputErrors?.voCode?.errorCode, + fieldName: "voCode", }), })} > @@ -299,6 +325,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.agencyCode?.type, label: props.text.agencyCodeLabel, + errorCode: errors?.inputErrors?.agencyCode?.errorCode, + fieldName: "agencyCode", }), })} > @@ -318,6 +346,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.bankAddress?.type, label: props.text.bankAddressLabel, + errorCode: errors?.inputErrors?.bankAddress?.errorCode, + fieldName: "bankAddress", }), })} >, @@ -333,6 +363,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.bankCity?.type, label: props.text.bankCityLabel, + errorCode: errors?.inputErrors?.bankCity?.errorCode, + fieldName: "bankCity", }), })} >, @@ -348,6 +380,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.bankState?.type, label: props.text.bankStateLabel, + errorCode: errors?.inputErrors?.bankState?.errorCode, + fieldName: "bankState", }), })} >, @@ -363,6 +397,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.bankPostalCode?.type, label: props.text.bankPostalCodeLabel, + errorCode: errors?.inputErrors?.bankPostalCode?.errorCode, + fieldName: "bankPostalCode", }), })} >, @@ -382,6 +418,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.branchCode?.type, label: props.text.branchCodeLabel, + errorCode: errors?.inputErrors?.branchCode?.errorCode, + fieldName: "branchCode", }), })} > @@ -400,6 +438,8 @@ export function getFormMap({ helpText: getValidationErrorMessage({ type: errors?.inputErrors?.beneficiaryClassification?.type, label: props.text.classificationLabel, + errorCode: errors?.inputErrors?.beneficiaryClassification?.errorCode, + fieldName: "beneficiaryClassification", }), })} > diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/readme.md b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/readme.md index 53516c5e15..55cc4173c3 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/readme.md +++ b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/readme.md @@ -5,69 +5,89 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------------------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `agencyCodeLabel` | `agency-code-label` | | `string` | `"Agency code"` | -| `backButton` | `back-button` | Text for the back button in the form | `string` | `"Back"` | -| `bankAccountNumberLabel` | `bank-account-number-label` | | `string` | `"Bank account number"` | -| `bankAccountTypeLabel` | `bank-account-type-label` | | `string` | `"Bank account type"` | -| `bankAddressLabel` | `bank-address-label` | | `string` | `"Bank address"` | -| `bankCityLabel` | `bank-city-label` | | `string` | `"Bank city"` | -| `bankLocationLabel` | `bank-location-label` | | `string` | `"Bank country location"` | -| `bankNameLabel` | `bank-name-label` | | `string` | `"Bank Name"` | -| `bankPostalCodeLabel` | `bank-postal-code-label` | | `string` | `"Bank postal code"` | -| `bankStateLabel` | `bank-state-label` | | `string` | `"Bank province/state"` | -| `beneficiaryAccountNameDescription` | `beneficiary-account-name-description` | | `string` | `"The beneficiary name of your bank account. Ensure this matches the name on your tax form."` | -| `beneficiaryAccountNameLabel` | `beneficiary-account-name-label` | | `string` | `"Account holder name"` | -| `branchCodeLabel` | `branch-code-label` | | `string` | `"Branch code"` | -| `businessSelectItemLabel` | `business-select-item-label` | One of three options listed for the classification field | `string` | `"Business"` | -| `checkingSelectItemLabel` | `checking-select-item-label` | | `string` | `"Checking"` | -| `classificationCPFLabel` | `classification-c-p-f-label` | | `string` | `"Classification CPF"` | -| `classificationEntityLabel` | `classification-entity-label` | | `string` | `"Classification Entity"` | -| `classificationLabel` | `classification-label` | Label text for the classification input field | `string` | `"Classification"` | -| `continueButton` | `continue-button` | | `string` | `"Save"` | -| `demoData` | -- | | `{ states?: { showVerification: boolean; step?: string; locale?: string; loading: boolean; saveLoading?: boolean; disabled: boolean; saveDisabled: boolean; hideSteps?: boolean; hasPayPal: boolean; hideBanking?: boolean; hidePayPal?: boolean; hideBalanceThreshold?: boolean; hideFixedDay?: boolean; hideBackButton: boolean; feeCap?: string; isPartner: boolean; paymentMethodFeeLabel?: string; loadingError: boolean; formState: BankingInfoFormData & { paymentMethodChecked?: "toBankAccount" \| "toPayPalAccount"; paymentScheduleChecked?: "BALANCE_THRESHOLD" \| "FIXED_DAY"; errors?: { general?: boolean; inputErrors?: { [field: string]: { type: "required" \| "invalid"; }; }; }; }; bitset?: number; currency?: string; thresholds: string[]; countries?: { countryCode: string; displayName: string; }[]; allCountries?: { countryCode: string; displayName: string; }[]; currentPaymentOption?: any; showInputs?: boolean; bankCountry?: string; countrySearch?: string; email?: string; showModal: boolean; }; slots?: { verificationDialogSlot?: VNode; formInputsSlot?: VNode[]; countryInputSlot?: VNode; paymentMethodSlot?: VNode; paymentThresholdSelectSlot?: VNode; paymentFixedDaySelectSlot?: VNode; paypalInputSlot?: VNode; }; refs?: { formRef: any; }; }` | `undefined` | -| `directlyToBankAccount` | `directly-to-bank-account` | | `string` | `"Directly to my bank account"` | -| `eftWithdrawalLabel` | `eft-withdrawal-label` | Default payment method to the participants’ bank account. | `string` | `"EFT withdrawal (free)"` | -| `fieldInvalidError` | `field-invalid-error` | Displayed under a field when it has an invalid entry. | `string` | `"{fieldName} is invalid"` | -| `fieldRequiredError` | `field-required-error` | Displayed under a field that is missing required information. | `string` | `"{fieldName} is required"` | -| `foreignSelectItemLabel` | `foreign-select-item-label` | One of three options listed for the classification field | `string` | `"Foreign"` | -| `formStep` | `form-step` | | `string` | `"Step {step} of {count}"` | -| `fxWireProcessingFeeLabel` | `fx-wire-processing-fee-label` | | `string` | `"FX Wire (Processing Fee {currency}{defaultFxFee}.00)"` | -| `generalErrorDescription` | `general-error-description` | Part of the alert displayed at the top of the page. | `string` | `"Please review your information and try again. If this problem continues, contact our {supportLink}."` | -| `generalErrorTitle` | `general-error-title` | Part of the alert displayed at the top of the page. | `string` | `"There was a problem submitting your information"` | -| `ibanLabel` | `iban-label` | | `string` | `"IBAN"` | -| `individualSelectItemLabel` | `individual-select-item-label` | One of three options listed for the classification field | `string` | `"Individual"` | -| `isPartnerAlertDescription` | `is-partner-alert-description` | Part of the alert displayed at the top of the page if the participant is already a registered partner on impact.com. | `string` | `"If you don’t recognize this referral program provider or believe this is a mistake, please contact our {supportLink} or sign up for this referral program with a different email."` | -| `isPartnerAlertHeader` | `is-partner-alert-header` | Part of the alert displayed at the top of the page if the participant is already a registered partner on impact.com. | `string` | `"An account with this email already exists with our referral program provider, impact.com"` | -| `loadingErrorAlertDescription` | `loading-error-alert-description` | Part of the alert displayed at the top of the page. | `string` | `"Please refresh the page and try again. If this problem continues, contact Support."` | -| `loadingErrorAlertHeader` | `loading-error-alert-header` | Part of the alert displayed at the top of the page. | `string` | `"There was a problem loading your form"` | -| `modalButtonText` | `modal-button-text` | | `string` | `"I understand, update my information"` | -| `modalDescription` | `modal-description` | | `string` | `"Updating payment information places your account and payouts on hold for up to 48 hours while we verify your change. Payments scheduled during the hold period are skipped."` | -| `modalTitle` | `modal-title` | | `string` | `"Important Note"` | -| `patronymicNameLabel` | `patronymic-name-label` | | `string` | `"Patronymic name"` | -| `payPalInputLabel` | `pay-pal-input-label` | Displayed to participants who choose PayPal as their payout method | `string` | `"PayPal email"` | -| `paymentDayFifteenthOfMonthLabelText` | `payment-day-fifteenth-of-month-label-text` | Label text for the payment day select option for the fifteenth of the month | `string` | `"15th of the month"` | -| `paymentDayFirstOfMonthLabelText` | `payment-day-first-of-month-label-text` | One of two payment day options | `string` | `"1st of the month"` | -| `paymentDaySelectLabel` | `payment-day-select-label` | Let the participant choose what day of the month they’ll get paid | `string` | `"Payment Day"` | -| `paymentMethod` | `payment-method` | | `string` | `"Payment method"` | -| `paymentMethodSubtext` | `payment-method-subtext` | | `string` | `"Payouts will be sent from our referral program provider, impact.com."` | -| `paymentSchedule` | `payment-schedule` | | `string` | `"Payment schedule"` | -| `paymentScheduleBalanceThreshold` | `payment-schedule-balance-threshold` | | `string` | `"Pay me when my balance reaches a threshold"` | -| `paymentScheduleFixedDay` | `payment-schedule-fixed-day` | | `string` | `"Pay me on a fixed day of the month"` | -| `paymentThresholdSelectLabel` | `payment-threshold-select-label` | Participant use this field to select the balance at which they want to be paid | `string` | `"Payment Threshold"` | -| `routingCodeLabel` | `routing-code-label` | | `string` | `"{bankCountry, select, AU {BSB number} CA {Routing number} CZ {Bank code} HK {Clearing code} SG {Clearing code} US {ABA routing number} NZ {BSB number} ZA {Bank/Branch number} IN {IFSC} CNY {CNAPS} other {Routing code} }"` | -| `savingsSelectItemLabel` | `savings-select-item-label` | | `string` | `"Savings"` | -| `searchForCountryText` | `search-for-country-text` | Placeholder text displayed in the country search dropdown | `string` | `"Search for country.."` | -| `supportLink` | `support-link` | | `string` | `"support team"` | -| `swiftCodeLabel` | `swift-code-label` | | `string` | `"SWIFT code"` | -| `taxAndPayouts` | `tax-and-payouts` | | `string` | `"Payouts"` | -| `taxAndPayoutsDescription` | `tax-and-payouts-description` | Displayed at the top of the page on all set up steps. | `string` | `"Submit your tax documents and add your banking information to receive your rewards."` | -| `taxPayerIdLabel` | `tax-payer-id-label` | | `string` | `"{country, select, AR {CUIT/CUIL} KR {Classification ID} other { Beneficiary INN } }"` | -| `toPayPalAccount` | `to-pay-pal-account` | | `string` | `"PayPal (2% processing fee capped to {feeCap})"` | -| `verifyEmailDescriptionText` | `verify-email-description-text` | | `string` | `"Verify your email to update your payment settings. Enter the code sent to {email} from our referral provider, impact.com."` | -| `verifyEmailHeaderText` | `verify-email-header-text` | Text for verify email dialog | `string` | `"Verify your email"` | -| `voCodeLabel` | `vo-code-label` | | `string` | `"VO code"` | +| Property | Attribute | Description | Type | Default | +| ------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `agencyCodeError` | `agency-code-error` | Error messages for the agency code field. Supports error codes: empty, alphanumeric, tooShort | `string` | `"{errorCode, select, empty {Agency code is required} alphanumeric {Agency code must contain only letters and numbers} tooShort {Agency code must be at least 5 characters} other {{errorCode}}}"` | +| `agencyCodeLabel` | `agency-code-label` | | `string` | `"Agency code"` | +| `backButton` | `back-button` | Text for the back button in the form | `string` | `"Back"` | +| `bankAccountNumberError` | `bank-account-number-error` | Error messages for the bank account number / IBAN field. Supports error codes: empty, invalidUk, invalid, ibanEmpty, ibanAlphanumeric, ibanInvalid, ibanCountryMismatch | `string` | `"{errorCode, select, empty {Account number is required} invalidUk {Please enter a valid UK account number} invalid {Account number is invalid} ibanEmpty {IBAN is required} ibanAlphanumeric {IBAN must contain only letters and numbers} ibanInvalid {IBAN is invalid} ibanCountryMismatch {UK accounts must use an IBAN starting with GB} other {{errorCode}}}"` | +| `bankAccountNumberLabel` | `bank-account-number-label` | | `string` | `"Bank account number"` | +| `bankAccountTypeError` | `bank-account-type-error` | Error messages for the bank account type field. Supports error codes: empty | `string` | `"{errorCode, select, empty {Bank account type is required} other {{errorCode}}}"` | +| `bankAccountTypeLabel` | `bank-account-type-label` | | `string` | `"Bank account type"` | +| `bankAddressError` | `bank-address-error` | Error messages for the bank address field. Supports error codes: empty | `string` | `"{errorCode, select, empty {Bank address is required} other {{errorCode}}}"` | +| `bankAddressLabel` | `bank-address-label` | | `string` | `"Bank address"` | +| `bankCityError` | `bank-city-error` | Error messages for the bank city field. Supports error codes: empty | `string` | `"{errorCode, select, empty {Bank city is required} other {{errorCode}}}"` | +| `bankCityLabel` | `bank-city-label` | | `string` | `"Bank city"` | +| `bankLocationLabel` | `bank-location-label` | | `string` | `"Bank country location"` | +| `bankNameError` | `bank-name-error` | Error messages for the bank name field. Supports error codes: empty | `string` | `"{errorCode, select, empty {Bank name is required} other {{errorCode}}}"` | +| `bankNameLabel` | `bank-name-label` | | `string` | `"Bank Name"` | +| `bankPostalCodeError` | `bank-postal-code-error` | Error messages for the bank postal code field. Supports error codes: empty | `string` | `"{errorCode, select, empty {Bank postal code is required} other {{errorCode}}}"` | +| `bankPostalCodeLabel` | `bank-postal-code-label` | | `string` | `"Bank postal code"` | +| `bankStateError` | `bank-state-error` | Error messages for the bank province/state field. Supports error codes: empty | `string` | `"{errorCode, select, empty {Bank province/state is required} other {{errorCode}}}"` | +| `bankStateLabel` | `bank-state-label` | | `string` | `"Bank province/state"` | +| `beneficiaryAccountNameDescription` | `beneficiary-account-name-description` | | `string` | `"The beneficiary name of your bank account. Ensure this matches the name on your tax form."` | +| `beneficiaryAccountNameError` | `beneficiary-account-name-error` | Error messages for the beneficiary / account holder name field. Supports error codes: empty, invalidCharacters, numeric, tooLong, nonEnglish, businessNameMismatch, nameMismatch, businessPayeeMismatch, payeeMismatch | `string` | `"{errorCode, select, empty {Account holder name is required} invalidCharacters {Account holder name contains invalid characters} numeric {Account holder name cannot be purely numeric} tooLong {Account holder name must be 70 characters or fewer} nonEnglish {Account holder name must contain only English characters for this currency} businessNameMismatch {Beneficiary name must match the name on your tax document} nameMismatch {Beneficiary name must match the name on your tax document} businessPayeeMismatch {Payee name must match the name on your tax document} payeeMismatch {Payee name must match the name on your tax document} other {{errorCode}}}"` | +| `beneficiaryAccountNameLabel` | `beneficiary-account-name-label` | | `string` | `"Account holder name"` | +| `branchCodeError` | `branch-code-error` | Error messages for the branch code field. Supports error codes: invalid | `string` | `"{errorCode, select, invalid {Branch code is invalid} other {{errorCode}}}"` | +| `branchCodeLabel` | `branch-code-label` | | `string` | `"Branch code"` | +| `branchNameError` | `branch-name-error` | Error messages for the branch name field. Supports error codes: empty | `string` | `"{errorCode, select, empty {Branch name is required} other {{errorCode}}}"` | +| `businessSelectItemLabel` | `business-select-item-label` | One of three options listed for the classification field | `string` | `"Business"` | +| `checkingSelectItemLabel` | `checking-select-item-label` | | `string` | `"Checking"` | +| `classificationCPFLabel` | `classification-c-p-f-label` | | `string` | `"Classification CPF"` | +| `classificationCodeError` | `classification-code-error` | Error messages for the classification code field. Supports error codes: empty, invalidKzt | `string` | `"{errorCode, select, empty {Classification code is required} invalidKzt {Classification code must be exactly 2 characters} other {{errorCode}}}"` | +| `classificationEntityLabel` | `classification-entity-label` | | `string` | `"Classification Entity"` | +| `classificationLabel` | `classification-label` | Label text for the classification input field | `string` | `"Classification"` | +| `continueButton` | `continue-button` | | `string` | `"Save"` | +| `demoData` | -- | | `{ states?: { showVerification: boolean; step?: string; locale?: string; loading: boolean; saveLoading?: boolean; disabled: boolean; saveDisabled: boolean; hideSteps?: boolean; hasPayPal: boolean; hideBanking?: boolean; hidePayPal?: boolean; hideBalanceThreshold?: boolean; hideFixedDay?: boolean; hideBackButton: boolean; feeCap?: string; isPartner: boolean; paymentMethodFeeLabel?: string; loadingError: boolean; formState: BankingInfoFormData & { paymentMethodChecked?: "toBankAccount" \| "toPayPalAccount"; paymentScheduleChecked?: "BALANCE_THRESHOLD" \| "FIXED_DAY"; errors?: { general?: boolean; inputErrors?: { [field: string]: { type: "required" \| "invalid"; errorCode?: string; }; }; }; }; bitset?: number; currency?: string; thresholds: string[]; countries?: { countryCode: string; displayName: string; }[]; allCountries?: { countryCode: string; displayName: string; }[]; currentPaymentOption?: any; showInputs?: boolean; bankCountry?: string; countrySearch?: string; email?: string; showModal: boolean; }; slots?: { verificationDialogSlot?: VNode; formInputsSlot?: VNode[]; countryInputSlot?: VNode; paymentMethodSlot?: VNode; paymentThresholdSelectSlot?: VNode; paymentFixedDaySelectSlot?: VNode; paypalInputSlot?: VNode; }; refs?: { formRef: any; }; }` | `undefined` | +| `directlyToBankAccount` | `directly-to-bank-account` | | `string` | `"Directly to my bank account"` | +| `eftWithdrawalLabel` | `eft-withdrawal-label` | Default payment method to the participants’ bank account. | `string` | `"EFT withdrawal (free)"` | +| `fieldInvalidError` | `field-invalid-error` | Displayed under a field when it has an invalid entry. | `string` | `"{fieldName} is invalid"` | +| `fieldRequiredError` | `field-required-error` | Displayed under a field that is missing required information. | `string` | `"{fieldName} is required"` | +| `foreignSelectItemLabel` | `foreign-select-item-label` | One of three options listed for the classification field | `string` | `"Foreign"` | +| `formStep` | `form-step` | | `string` | `"Step {step} of {count}"` | +| `fxWireProcessingFeeLabel` | `fx-wire-processing-fee-label` | | `string` | `"FX Wire (Processing Fee {currency}{defaultFxFee}.00)"` | +| `generalErrorDescription` | `general-error-description` | Part of the alert displayed at the top of the page. | `string` | `"Please review your information and try again. If this problem continues, contact our {supportLink}."` | +| `generalErrorTitle` | `general-error-title` | Part of the alert displayed at the top of the page. | `string` | `"There was a problem submitting your information"` | +| `ibanLabel` | `iban-label` | | `string` | `"IBAN"` | +| `individualSelectItemLabel` | `individual-select-item-label` | One of three options listed for the classification field | `string` | `"Individual"` | +| `isPartnerAlertDescription` | `is-partner-alert-description` | Part of the alert displayed at the top of the page if the participant is already a registered partner on impact.com. | `string` | `"If you don’t recognize this referral program provider or believe this is a mistake, please contact our {supportLink} or sign up for this referral program with a different email."` | +| `isPartnerAlertHeader` | `is-partner-alert-header` | Part of the alert displayed at the top of the page if the participant is already a registered partner on impact.com. | `string` | `"An account with this email already exists with our referral program provider, impact.com"` | +| `loadingErrorAlertDescription` | `loading-error-alert-description` | Part of the alert displayed at the top of the page. | `string` | `"Please refresh the page and try again. If this problem continues, contact Support."` | +| `loadingErrorAlertHeader` | `loading-error-alert-header` | Part of the alert displayed at the top of the page. | `string` | `"There was a problem loading your form"` | +| `modalButtonText` | `modal-button-text` | | `string` | `"I understand, update my information"` | +| `modalDescription` | `modal-description` | | `string` | `"Updating payment information places your account and payouts on hold for up to 48 hours while we verify your change. Payments scheduled during the hold period are skipped."` | +| `modalTitle` | `modal-title` | | `string` | `"Important Note"` | +| `patronymicNameError` | `patronymic-name-error` | Error messages for the patronymic name field. Supports error codes: empty, alphanumeric | `string` | `"{errorCode, select, empty {Patronymic name is required} alphanumeric {Patronymic name must contain only letters and numbers} other {{errorCode}}}"` | +| `patronymicNameLabel` | `patronymic-name-label` | | `string` | `"Patronymic name"` | +| `payPalInputLabel` | `pay-pal-input-label` | Displayed to participants who choose PayPal as their payout method | `string` | `"PayPal email"` | +| `paymentDayError` | `payment-day-error` | Error messages for the payment day field. Supports error codes: empty, invalid | `string` | `"{errorCode, select, empty {Payment day is required} invalid {Payment day must be the 1st or the 15th} other {{errorCode}}}"` | +| `paymentDayFifteenthOfMonthLabelText` | `payment-day-fifteenth-of-month-label-text` | Label text for the payment day select option for the fifteenth of the month | `string` | `"15th of the month"` | +| `paymentDayFirstOfMonthLabelText` | `payment-day-first-of-month-label-text` | One of two payment day options | `string` | `"1st of the month"` | +| `paymentDaySelectLabel` | `payment-day-select-label` | Let the participant choose what day of the month they’ll get paid | `string` | `"Payment Day"` | +| `paymentMethod` | `payment-method` | | `string` | `"Payment method"` | +| `paymentMethodSubtext` | `payment-method-subtext` | | `string` | `"Payouts will be sent from our referral program provider, impact.com."` | +| `paymentSchedule` | `payment-schedule` | | `string` | `"Payment schedule"` | +| `paymentScheduleBalanceThreshold` | `payment-schedule-balance-threshold` | | `string` | `"Pay me when my balance reaches a threshold"` | +| `paymentScheduleFixedDay` | `payment-schedule-fixed-day` | | `string` | `"Pay me on a fixed day of the month"` | +| `paymentThresholdError` | `payment-threshold-error` | Error messages for the payment threshold field. Supports error codes: empty, invalid | `string` | `"{errorCode, select, empty {Payment threshold is required} invalid {Payment threshold is invalid} other {{errorCode}}}"` | +| `paymentThresholdSelectLabel` | `payment-threshold-select-label` | Participant use this field to select the balance at which they want to be paid | `string` | `"Payment Threshold"` | +| `paypalEmailError` | `paypal-email-error` | Error messages for the PayPal email field. Supports error codes: empty, unsupportedCurrency, invalidEmail, verificationIncomplete | `string` | `"{errorCode, select, empty {PayPal email is required} unsupportedCurrency {PayPal is not supported for this currency} invalidEmail {Please enter a valid email address} verificationIncomplete {PayPal verification is not complete} other {{errorCode}}}"` | +| `routingCodeError` | `routing-code-error` | Error messages for the routing code / sort code / BSB field. Supports error codes: invalidBsb, invalidSortCode, empty, invalid | `string` | `"{errorCode, select, invalidBsb {Please enter a valid BSB number} invalidSortCode {Please enter a valid sort code} empty {Routing number is required} invalid {Routing number is invalid} other {{errorCode}}}"` | +| `routingCodeLabel` | `routing-code-label` | | `string` | `"{bankCountry, select, AU {BSB number} CA {Routing number} CZ {Bank code} HK {Clearing code} SG {Clearing code} US {ABA routing number} NZ {BSB number} ZA {Bank/Branch number} IN {IFSC} CNY {CNAPS} other {Routing code} }"` | +| `savingsSelectItemLabel` | `savings-select-item-label` | | `string` | `"Savings"` | +| `searchForCountryText` | `search-for-country-text` | Placeholder text displayed in the country search dropdown | `string` | `"Search for country.."` | +| `supportLink` | `support-link` | | `string` | `"support team"` | +| `swiftCodeError` | `swift-code-error` | Error messages for the SWIFT / BIC code field. Supports error codes: empty, alphanumeric, invalid | `string` | `"{errorCode, select, empty {SWIFT/BIC code is required} alphanumeric {SWIFT/BIC code must contain only letters and numbers} invalid {SWIFT/BIC code is invalid} other {{errorCode}}}"` | +| `swiftCodeLabel` | `swift-code-label` | | `string` | `"SWIFT code"` | +| `taxAndPayouts` | `tax-and-payouts` | | `string` | `"Payouts"` | +| `taxAndPayoutsDescription` | `tax-and-payouts-description` | Displayed at the top of the page on all set up steps. | `string` | `"Submit your tax documents and add your banking information to receive your rewards."` | +| `taxPayerIdError` | `tax-payer-id-error` | Error messages for the tax payer ID / classification entity field. Supports error codes: empty, emptyAr, emptyKr, alphanumeric, alphanumericAr, alphanumericKr, invalid, invalidAr, invalidKr, invalidKzt, cnpjTooShort, cpfTooShort | `string` | `"{errorCode, select, empty {Tax payer ID is required} emptyAr {CUIT/CUIL is required} emptyKr {Classification ID is required} alphanumeric {Tax payer ID must contain only letters and numbers} alphanumericAr {CUIT/CUIL must contain only letters and numbers} alphanumericKr {Classification ID must contain only letters and numbers} invalid {Tax payer ID is invalid} invalidAr {CUIT/CUIL must be 11 characters} invalidKr {Classification ID length is invalid} invalidKzt {Tax payer ID must be 12 characters for KZT} cnpjTooShort {CNPJ must be at least 14 characters} cpfTooShort {CPF must be at least 11 characters} other {{errorCode}}}"` | +| `taxPayerIdLabel` | `tax-payer-id-label` | | `string` | `"{country, select, AR {CUIT/CUIL} KR {Classification ID} other { Beneficiary INN } }"` | +| `toPayPalAccount` | `to-pay-pal-account` | | `string` | `"PayPal (2% processing fee capped to {feeCap})"` | +| `verifyEmailDescriptionText` | `verify-email-description-text` | | `string` | `"Verify your email to update your payment settings. Enter the code sent to {email} from our referral provider, impact.com."` | +| `verifyEmailHeaderText` | `verify-email-header-text` | Text for verify email dialog | `string` | `"Verify your email"` | +| `voCodeError` | `vo-code-error` | Error messages for the VO code field. Supports error codes: empty, alphanumeric | `string` | `"{errorCode, select, empty {VO code is required} alphanumeric {VO code must contain only letters and numbers} other {{errorCode}}}"` | +| `voCodeLabel` | `vo-code-label` | | `string` | `"VO code"` | ## Dependencies diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/sqm-banking-info-form-view.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/sqm-banking-info-form-view.tsx index 806eaf1139..3819882246 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/sqm-banking-info-form-view.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/sqm-banking-info-form-view.tsx @@ -32,6 +32,7 @@ export interface BankingInfoFormViewProps { inputErrors?: { [field: string]: { type: "required" | "invalid"; + errorCode?: string; }; }; }; @@ -105,6 +106,7 @@ export interface BankingInfoFormViewProps { generalTitle: string; generalDescription: string; }; + errorMessages?: { [field: string]: string }; }; refs: { formRef: any; diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/sqm-banking-info-form.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/sqm-banking-info-form.tsx index 2a674f973d..8d005baa3e 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/sqm-banking-info-form.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/sqm-banking-info-form.tsx @@ -350,6 +350,197 @@ export class BankingInfoForm { */ @Prop() modalButtonText: string = "I understand, update my information"; + // ────────────────────────────────────────────────────────────────── + // Per-field validation error messages + // Each prop uses ICU select on {errorCode} to pick the right message. + // Error codes are short frontend keys mapped from the API error codes. + // The `other` branch displays the raw API message directly via {errorCode}, + // which is already human-readable English (e.g. "Invalid Routing Code"). + // ────────────────────────────────────────────────────────────────── + + /** + * Error messages for the beneficiary / account holder name field. + * Supports error codes: empty, invalidCharacters, numeric, tooLong, + * nonEnglish, businessNameMismatch, nameMismatch, businessPayeeMismatch, payeeMismatch + * @uiName Beneficiary account name error + * @uiWidget textArea + */ + @Prop() beneficiaryAccountNameError: string = + "{errorCode, select, empty {Account holder name is required} invalidCharacters {Account holder name contains invalid characters} numeric {Account holder name cannot be purely numeric} tooLong {Account holder name must be 70 characters or fewer} nonEnglish {Account holder name must contain only English characters for this currency} businessNameMismatch {Beneficiary name must match the name on your tax document} nameMismatch {Beneficiary name must match the name on your tax document} businessPayeeMismatch {Payee name must match the name on your tax document} payeeMismatch {Payee name must match the name on your tax document} other {{errorCode}}}"; + + /** + * Error messages for the bank account number / IBAN field. + * Supports error codes: empty, invalidUk, invalid, ibanEmpty, + * ibanAlphanumeric, ibanInvalid, ibanCountryMismatch + * @uiName Bank account number / IBAN error + * @uiWidget textArea + */ + @Prop() bankAccountNumberError: string = + "{errorCode, select, empty {Account number is required} invalidUk {Please enter a valid UK account number} invalid {Account number is invalid} ibanEmpty {IBAN is required} ibanAlphanumeric {IBAN must contain only letters and numbers} ibanInvalid {IBAN is invalid} ibanCountryMismatch {UK accounts must use an IBAN starting with GB} other {{errorCode}}}"; + + /** + * Error messages for the routing code / sort code / BSB field. + * Supports error codes: invalidBsb, invalidSortCode, empty, invalid + * @uiName Routing code error + * @uiWidget textArea + */ + @Prop() routingCodeError: string = + "{errorCode, select, invalidBsb {Please enter a valid BSB number} invalidSortCode {Please enter a valid sort code} empty {Routing number is required} invalid {Routing number is invalid} other {{errorCode}}}"; + + /** + * Error messages for the SWIFT / BIC code field. + * Supports error codes: empty, alphanumeric, invalid + * @uiName SWIFT code error + * @uiWidget textArea + */ + @Prop() swiftCodeError: string = + "{errorCode, select, empty {SWIFT/BIC code is required} alphanumeric {SWIFT/BIC code must contain only letters and numbers} invalid {SWIFT/BIC code is invalid} other {{errorCode}}}"; + + /** + * Error messages for the bank account type field. + * Supports error codes: empty + * @uiName Bank account type error + * @uiWidget textArea + */ + @Prop() bankAccountTypeError: string = + "{errorCode, select, empty {Bank account type is required} other {{errorCode}}}"; + + /** + * Error messages for the bank name field. + * Supports error codes: empty + * @uiName Bank name error + * @uiWidget textArea + */ + @Prop() bankNameError: string = + "{errorCode, select, empty {Bank name is required} other {{errorCode}}}"; + + /** + * Error messages for the tax payer ID / classification entity field. + * Supports error codes: empty, emptyAr, emptyKr, alphanumeric, alphanumericAr, + * alphanumericKr, invalid, invalidAr, invalidKr, invalidKzt, cnpjTooShort, cpfTooShort + * @uiName Tax payer ID error + * @uiWidget textArea + */ + @Prop() taxPayerIdError: string = + "{errorCode, select, empty {Tax payer ID is required} emptyAr {CUIT/CUIL is required} emptyKr {Classification ID is required} alphanumeric {Tax payer ID must contain only letters and numbers} alphanumericAr {CUIT/CUIL must contain only letters and numbers} alphanumericKr {Classification ID must contain only letters and numbers} invalid {Tax payer ID is invalid} invalidAr {CUIT/CUIL must be 11 characters} invalidKr {Classification ID length is invalid} invalidKzt {Tax payer ID must be 12 characters for KZT} cnpjTooShort {CNPJ must be at least 14 characters} cpfTooShort {CPF must be at least 11 characters} other {{errorCode}}}"; + + /** + * Error messages for the patronymic name field. + * Supports error codes: empty, alphanumeric + * @uiName Patronymic name error + * @uiWidget textArea + */ + @Prop() patronymicNameError: string = + "{errorCode, select, empty {Patronymic name is required} alphanumeric {Patronymic name must contain only letters and numbers} other {{errorCode}}}"; + + /** + * Error messages for the VO code field. + * Supports error codes: empty, alphanumeric + * @uiName VO code error + * @uiWidget textArea + */ + @Prop() voCodeError: string = + "{errorCode, select, empty {VO code is required} alphanumeric {VO code must contain only letters and numbers} other {{errorCode}}}"; + + /** + * Error messages for the agency code field. + * Supports error codes: empty, alphanumeric, tooShort + * @uiName Agency code error + * @uiWidget textArea + */ + @Prop() agencyCodeError: string = + "{errorCode, select, empty {Agency code is required} alphanumeric {Agency code must contain only letters and numbers} tooShort {Agency code must be at least 5 characters} other {{errorCode}}}"; + + /** + * Error messages for the bank address field. + * Supports error codes: empty + * @uiName Bank address error + * @uiWidget textArea + */ + @Prop() bankAddressError: string = + "{errorCode, select, empty {Bank address is required} other {{errorCode}}}"; + + /** + * Error messages for the bank city field. + * Supports error codes: empty + * @uiName Bank city error + * @uiWidget textArea + */ + @Prop() bankCityError: string = + "{errorCode, select, empty {Bank city is required} other {{errorCode}}}"; + + /** + * Error messages for the bank province/state field. + * Supports error codes: empty + * @uiName Bank province/state error + * @uiWidget textArea + */ + @Prop() bankStateError: string = + "{errorCode, select, empty {Bank province/state is required} other {{errorCode}}}"; + + /** + * Error messages for the bank postal code field. + * Supports error codes: empty + * @uiName Bank postal code error + * @uiWidget textArea + */ + @Prop() bankPostalCodeError: string = + "{errorCode, select, empty {Bank postal code is required} other {{errorCode}}}"; + + /** + * Error messages for the branch code field. + * Supports error codes: invalid + * @uiName Branch code error + * @uiWidget textArea + */ + @Prop() branchCodeError: string = + "{errorCode, select, invalid {Branch code is invalid} other {{errorCode}}}"; + + /** + * Error messages for the branch name field. + * Supports error codes: empty + * @uiName Branch name error + * @uiWidget textArea + */ + @Prop() branchNameError: string = + "{errorCode, select, empty {Branch name is required} other {{errorCode}}}"; + + /** + * Error messages for the classification code field. + * Supports error codes: empty, invalidKzt + * @uiName Classification code error + * @uiWidget textArea + */ + @Prop() classificationCodeError: string = + "{errorCode, select, empty {Classification code is required} invalidKzt {Classification code must be exactly 2 characters} other {{errorCode}}}"; + + /** + * Error messages for the PayPal email field. + * Supports error codes: empty, unsupportedCurrency, invalidEmail, verificationIncomplete + * @uiName PayPal email error + * @uiWidget textArea + */ + @Prop() paypalEmailError: string = + "{errorCode, select, empty {PayPal email is required} unsupportedCurrency {PayPal is not supported for this currency} invalidEmail {Please enter a valid email address} verificationIncomplete {PayPal verification is not complete} other {{errorCode}}}"; + + /** + * Error messages for the payment threshold field. + * Supports error codes: empty, invalid + * @uiName Payment threshold error + * @uiWidget textArea + */ + @Prop() paymentThresholdError: string = + "{errorCode, select, empty {Payment threshold is required} invalid {Payment threshold is invalid} other {{errorCode}}}"; + + /** + * Error messages for the payment day field. + * Supports error codes: empty, invalid + * @uiName Payment day error + * @uiWidget textArea + */ + @Prop() paymentDayError: string = + "{errorCode, select, empty {Payment day is required} invalid {Payment day must be the 1st or the 15th} other {{errorCode}}}"; + /** * @undocumented * @uiType object @@ -373,6 +564,28 @@ export class BankingInfoForm { loadingErrorAlertDescription: props.loadingErrorAlertDescription, loadingErrorAlertHeader: props.loadingErrorAlertHeader, }, + errorMessages: { + beneficiaryAccountName: props.beneficiaryAccountNameError, + bankAccountNumber: props.bankAccountNumberError, + routingCode: props.routingCodeError, + swiftCode: props.swiftCodeError, + bankAccountType: props.bankAccountTypeError, + bankName: props.bankNameError, + taxPayerId: props.taxPayerIdError, + patronymicName: props.patronymicNameError, + voCode: props.voCodeError, + agencyCode: props.agencyCodeError, + bankAddress: props.bankAddressError, + bankCity: props.bankCityError, + bankState: props.bankStateError, + bankPostalCode: props.bankPostalCodeError, + branchCode: props.branchCodeError, + branchName: props.branchNameError, + beneficiaryClassification: props.classificationCodeError, + paypalEmailAddress: props.paypalEmailError, + paymentThreshold: props.paymentThresholdError, + paymentDay: props.paymentDayError, + }, }; } @@ -389,10 +602,32 @@ export class BankingInfoForm { function getValidationErrorMessage({ type, label, + errorCode, + fieldName, }: { type: "required" | "invalid"; label: string; + errorCode?: string; + fieldName?: string; }) { + // If we have a specific error code from the API, try to use + // the per-field ICU error message template for a rich message + if (type === "invalid" && errorCode && fieldName) { + const errorTemplate = props.text.errorMessages?.[fieldName]; + if (errorTemplate) { + return intl.formatMessage( + { + id: `fieldError-${fieldName}-${errorCode}`, + defaultMessage: errorTemplate, + }, + { + errorCode, + fieldName: label, + } + ); + } + } + if (type === "required") { return intl.formatMessage( { @@ -525,6 +760,8 @@ export class BankingInfoForm { helpText: getValidationErrorMessage({ type: errors?.inputErrors?.bankCountry?.type, label: props.text.bankLocationLabel, + errorCode: errors?.inputErrors?.bankCountry?.errorCode, + fieldName: "bankCountry", }), })} > @@ -578,6 +815,8 @@ export class BankingInfoForm { helpText: getValidationErrorMessage({ type: errors?.inputErrors?.paymentThreshold?.type, label: props.text.paymentThresholdSelectLabel, + errorCode: errors?.inputErrors?.paymentThreshold?.errorCode, + fieldName: "paymentThreshold", }), })} > @@ -601,6 +840,8 @@ export class BankingInfoForm { helpText: getValidationErrorMessage({ type: errors?.inputErrors?.paymentDay?.type, label: props.text.paymentDaySelectLabel, + errorCode: errors?.inputErrors?.paymentDay?.errorCode, + fieldName: "paymentDay", }), })} > @@ -629,6 +870,10 @@ export class BankingInfoForm { type: props.states.formState?.errors?.inputErrors ?.paypalEmailAddress?.type, label: props.text.payPalInputLabel, + errorCode: + props.states.formState?.errors?.inputErrors + ?.paypalEmailAddress?.errorCode, + fieldName: "paypalEmailAddress", }), })} > diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/useBankingInfoForm.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/useBankingInfoForm.tsx index 09a1cb7bfd..f8303c24ad 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/useBankingInfoForm.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-banking-info-form/useBankingInfoForm.tsx @@ -9,7 +9,7 @@ import { } from "@saasquatch/component-boilerplate"; import { useEffect, useRef, useState } from "@saasquatch/universal-hooks"; import { gql } from "graphql-request"; -import JSONPointer, { set } from "jsonpointer"; +import JSONPointer from "jsonpointer"; import { intl } from "../../../global/global"; import { VERIFICATION_EVENT_KEY } from "../../sqm-widget-verification/keys"; import { @@ -49,6 +49,115 @@ const ACH_PAYMENT_METHOD = 3; const WIRE_PAYMENT_METHOD = 5; const PAYPAL_PAYMENT_METHOD = 7; +/** + * Maps GraphQL validation error field names to form field names. + */ +const API_FIELD_TO_FORM_FIELD: Record = { + // bankProvinceState → form uses bankState + bankProvinceState: "bankState", +}; + +/** + * Maps Impact API error code paths (from validationErrors[].errorPath) to short, + * readable frontend error codes used in the ICU select props. + */ +const API_ERROR_PATH_TO_FRONTEND: Record = { + // Beneficiary account name + "withdrawal.settings.error.empty_beneficiaryname": "empty", + "withdrawal.settings.error.invalid_character_beneficiaryname": + "invalidCharacters", + "withdrawal.settings.error.numeric_beneficiaryname": "numeric", + "withdrawal_settings.error.beneficiaryname.size": "tooLong", + "withdrawal.settings.error.non_english_beneficiaryname": "nonEnglish", + "withdrawal_settings.error.business_beneficiaryname_match": + "businessNameMismatch", + "withdrawal_settings.error.beneficiaryname_match": "nameMismatch", + "withdrawal_settings.error.business_checkpayeename_match": + "businessPayeeMismatch", + "withdrawal_settings.error.checkpayeename_match": "payeeMismatch", + + // Bank account number + "withdrawal.settings.error.accountnumber.empty": "empty", + "withdrawal.settings.error.accountnumber.uk": "invalidUk", + "withdrawal.settings.error.bankaccount.invalid": "invalid", + + // IBAN + "withdrawal.settings.error.iban": "ibanEmpty", + "withdrawal.settings.error.iban.alphanumeric": "ibanAlphanumeric", + "withdrawal.settings.error.iban.invalid": "ibanInvalid", + "withdrawal.settings.error.iban.uk.country.mismatch": "ibanCountryMismatch", + + // Routing code + "withdrawal.settings.error.bsbNumber": "invalidBsb", + "withdrawal.settings.error.sortcode": "invalidSortCode", + "withdrawal.settings.error.routingNumber": "empty", + "withdrawal.settings.error.routingcode": "invalid", + + // SWIFT / BIC + "withdrawal.settings.error.bic": "empty", + "withdrawal.settings.error.bic.alphanumeric": "alphanumeric", + "withdrawal.settings.error.bic.invalid": "invalid", + + // Bank account type + "global.error.invalid.accounttype": "empty", + + // Bank name + "withdrawal.settings.error.bankName": "empty", + + // Tax payer ID + "withdrawal.settings.error.taxPayerId": "empty", + "withdrawal.settings.error.taxPayerId.ar": "emptyAr", + "withdrawal.settings.error.taxPayerId.kr": "emptyKr", + "withdrawal.settings.error.taxPayerId.alphanumeric": "alphanumeric", + "withdrawal.settings.error.taxPayerId.alphanumeric.ar": "alphanumericAr", + "withdrawal.settings.error.taxPayerId.alphanumeric.kr": "alphanumericKr", + "withdrawal.settings.error.taxPayerId.invalid": "invalid", + "withdrawal.settings.error.taxPayerId.invalid.ar": "invalidAr", + "withdrawal.settings.error.taxPayerId.invalid.kr": "invalidKr", + "withdrawal.settings.error.taxPayerId.invalid.kzt": "invalidKzt", + "withdrawal.settings.error.taxPayerId.cnpj": "cnpjTooShort", + "withdrawal.settings.error.taxPayerId.cpf": "cpfTooShort", + + // Patronymic name + "withdrawal.settings.error.patronymicName": "empty", + "withdrawal.settings.error.patronymicName.alphanumeric": "alphanumeric", + + // VO code + "withdrawal.settings.error.voCode": "empty", + "withdrawal.settings.error.voCode.alphanumeric": "alphanumeric", + + // Agency code + "withdrawal.settings.error.agencyCode": "empty", + "withdrawal.settings.error.agencyCode.alphanumeric": "alphanumeric", + "withdrawal.settings.error.agencyCode.length": "tooShort", + + // Bank address fields + "withdrawal.settings.error.bankAddress": "empty", + "withdrawal.settings.error.bankCity": "empty", + "withdrawal.settings.error.bankProvinceState": "empty", + "withdrawal.settings.error.bankPostalCode": "empty", + + // Branch code / name + "withdrawal.settings.error.branchCode": "invalid", + "withdrawal.settings.error.branchName": "empty", + + // Classification code + "withdrawal.settings.error.classificationCode.invalid": "empty", + "withdrawal.settings.error.classificationCode.invalid.kzt": "invalidKzt", + + // PayPal + "payment.error.email": "empty", + "payment.error.paypal_not_supported": "unsupportedCurrency", + "payment.error.email.invalid": "invalidEmail", + "payment.error.paypal_verification_incomplete": "verificationIncomplete", + + // Payment schedule + "payment.error.no_threshold": "empty", + "payment.error.invalid_threshold": "invalid", + "payment.error.no_dayOfMonth": "empty", + "payment.error.invalid_dayOfMonth": "invalid", +}; + export type BankingInfoFormData = { // Fields that are auto-filled bankCountry?: string; @@ -101,7 +210,11 @@ export function getFormInputs({ bitset, formMap }) { type SetImpactPublisherWithdrawalSettingsResult = { setImpactPublisherWithdrawalSettings: { success: boolean; - validationErrors: { field: string; message: string }[]; + validationErrors: { + field: string; + message: string; + errorPath: string; + }[]; }; }; type SetImpactPublisherWithdrawalSettingsInput = { @@ -120,7 +233,11 @@ type UpdateImpactPublisherWithdrawalSettingsInput = type UpdateImpactPublisherWithdrawalSettingsResult = { updateImpactPublisherWithdrawalSettings: { success: boolean; - validationErrors: { field: string; message: string }[]; + validationErrors: { + field: string; + message: string; + errorPath: string; + }[]; }; }; @@ -135,6 +252,7 @@ const SAVE_WITHDRAWAL_SETTINGS = gql` validationErrors { field message + code } } } @@ -151,6 +269,7 @@ const UPDATE_WITHDRAWAL_SETTINGS = gql` validationErrors { field message + code } } } @@ -176,7 +295,7 @@ function parseImpactThreshold(threshold: string) { } export function useBankingInfoForm( - props: BankingInfoForm + props: BankingInfoForm, ): BankingInfoFormViewProps { const host = useHost(); const locale = useLocale(); @@ -193,7 +312,7 @@ export function useBankingInfoForm( loading: paymentOptionsLoading, errors: paymentOptionsError, } = useParentQueryValue( - FINANCE_NETWORK_SETTINGS_NAMESPACE + FINANCE_NETWORK_SETTINGS_NAMESPACE, ); const { data: userData, @@ -202,11 +321,11 @@ export function useBankingInfoForm( } = useParentQueryValue(USER_QUERY_NAMESPACE); const [saveWithdrawalSettings] = useMutation( - SAVE_WITHDRAWAL_SETTINGS + SAVE_WITHDRAWAL_SETTINGS, ); const [updateWithdrawalSettings] = useMutation( - UPDATE_WITHDRAWAL_SETTINGS + UPDATE_WITHDRAWAL_SETTINGS, ); const [showVerification, setShowVerification] = useState(false); @@ -244,14 +363,14 @@ export function useBankingInfoForm( { currency: currency, defaultFxFee: currentPaymentOption?.defaultFxFee || 0, - } + }, ), }; const paymentMethodFeeLabel = paymentMethodFeeMap[currentPaymentOption?.defaultFinancePaymentMethodId]; const hasPayPal = !!paymentOptions?.find( - (option) => option.defaultFinancePaymentMethodId === PAYPAL_PAYMENT_METHOD + (option) => option.defaultFinancePaymentMethodId === PAYPAL_PAYMENT_METHOD, ); const paymentMethodChecked = !hasPayPal @@ -282,7 +401,7 @@ export function useBankingInfoForm( paypalEmailAddress: withdrawalSettings.paypalEmailAddress, paymentSchedulingType: withdrawalSettings.paymentSchedulingType, paymentThreshold: parseImpactThreshold( - withdrawalSettings.paymentThreshold + withdrawalSettings.paymentThreshold, ), paymentDay: withdrawalSettings.paymentDay, }; @@ -305,7 +424,7 @@ export function useBankingInfoForm( setPaymentMethodChecked( initialData.paymentMethod === "PAYPAL" ? "toPayPalAccount" - : "toBankAccount" + : "toBankAccount", ); setCurrentPaymentOption(currentPaymentOption); setPaymentScheduleChecked(initialData.paymentSchedulingType); @@ -319,8 +438,8 @@ export function useBankingInfoForm( } else { setFilteredCountries( countries.filter((c) => - c.displayName.toLowerCase().includes(countrySearch.toLowerCase()) - ) || [] + c.displayName.toLowerCase().includes(countrySearch.toLowerCase()), + ) || [], ); } }, [countrySearch, countries]); @@ -390,15 +509,19 @@ export function useBankingInfoForm( const mappedValidationErrors = validationErrors?.reduce( (agg, error) => { + const formField = + API_FIELD_TO_FORM_FIELD[error.field] || error.field; + const errorCode = + API_ERROR_PATH_TO_FRONTEND[error.errorPath] || error.errorPath; return { ...agg, - - [error.field]: { + [formField]: { type: "invalid", + errorCode, }, }; }, - {} + {}, ); setErrors({ @@ -469,12 +592,12 @@ export function useBankingInfoForm( new CustomEvent(VERIFICATION_EVENT_KEY, { detail: { token }, bubbles: false, - }) + }), ); }; function setPaymentMethodChecked( - paymentMethod: "toBankAccount" | "toPayPalAccount" + paymentMethod: "toBankAccount" | "toPayPalAccount", ) { _setPaymentMethodChecked(paymentMethod); @@ -486,7 +609,7 @@ export function useBankingInfoForm( setCurrentPaymentOption(currentPaymentOption); } else if (paymentMethod === "toBankAccount") { const currentPaymentOption = paymentOptions?.find( - (paymentOption) => paymentOption.countryCode === formState.bankCountry + (paymentOption) => paymentOption.countryCode === formState.bankCountry, ); setCurrentPaymentOption(currentPaymentOption); } diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-indirect-tax-form/useIndirectTaxForm.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-indirect-tax-form/useIndirectTaxForm.tsx index b7d9910d3e..1051fd2e2e 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-indirect-tax-form/useIndirectTaxForm.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-indirect-tax-form/useIndirectTaxForm.tsx @@ -55,6 +55,14 @@ export type ConnectPartnerResult = { } | null; }; }; + +export type StartImpactConnectionResult = { + startImpactConnection: ConnectPartnerResult["createImpactConnection"]; +}; + +export type CompletePartnerResult = { + completeImpactConnection: ConnectPartnerResult["createImpactConnection"]; +}; type ImpactConnectionInput = { user: { id: string; @@ -104,6 +112,33 @@ export const CONNECT_PARTNER = gql` } `; +export const COMPLETE_PARTNER = gql` + mutation completeImpactConnection($vars: ImpactConnectionInput!) { + completeImpactConnection(impactConnectionInput: $vars) { + success + validationErrors { + field + message + } + user { + id + accountId + impactConnection { + connected + publisher { + brandedSignup + requiredTaxDocumentType + currentTaxDocument { + type + status + } + } + } + } + } + } +`; + function getOption(countries: TaxCountry[] | undefined, countryCode: string) { if (!countries) return; @@ -123,10 +158,10 @@ export function useIndirectTaxForm(props: IndirectTaxForm) { const context = useParentValue(TAX_FORM_CONTEXT_NAMESPACE); const [step, setStep] = useParent(TAX_CONTEXT_NAMESPACE); - const [ - connectImpactPartner, - { loading: connectLoading, errors: connectErrors }, - ] = useMutation(CONNECT_PARTNER); + const [connectImpactPartner, { loading: connectLoading }] = + useMutation(CONNECT_PARTNER); + const [completeImpactPartner, { loading: completeLoading }] = + useMutation(COMPLETE_PARTNER); const userForm = useParentValue(USER_FORM_CONTEXT_NAMESPACE); const { data: userData, @@ -141,9 +176,9 @@ export function useIndirectTaxForm(props: IndirectTaxForm) { const _countries = useMemo( () => _countriesRes?.impactPayoutCountries?.data?.map((country) => - getCountryObj({ countryCode: country.countryCode, locale: intlLocale }) + getCountryObj({ countryCode: country.countryCode, locale: intlLocale }), ), - [_countriesRes?.impactPayoutCountries?.data] + [_countriesRes?.impactPayoutCountries?.data], ); const [loading, setLoading] = useState(false); @@ -168,7 +203,7 @@ export function useIndirectTaxForm(props: IndirectTaxForm) { const _option = getOption( _countries, - publisher.taxInformation.indirectTaxCountryCode + publisher.taxInformation.indirectTaxCountryCode, ); setOption(_option); }, [publisher, _countries]); @@ -179,8 +214,8 @@ export function useIndirectTaxForm(props: IndirectTaxForm) { } else { setFilteredCountries( _countries?.filter((c) => - c.displayName.toLowerCase().includes(countrySearch.toLowerCase()) - ) || [] + c.displayName.toLowerCase().includes(countrySearch.toLowerCase()), + ) || [], ); } }, [countrySearch, _countries]); @@ -244,16 +279,30 @@ export function useIndirectTaxForm(props: IndirectTaxForm) { withholdingTaxId: formData.subRegionTaxNumber, } as ImpactConnectionInput; - const result = await connectImpactPartner({ - vars, - }); + // If the partner has already been started call completeImpactConnection + // to fill in the remaining details. Otherwise create from scratch. + let result = null; + let connectionResult; + if (userData?.user?.impactConnection?.connectionStatus === "STARTED") { + result = await completeImpactPartner({ + vars, + }); + connectionResult = (result as CompletePartnerResult) + ?.completeImpactConnection; + } else { + result = await connectImpactPartner({ + vars, + }); + connectionResult = (result as ConnectPartnerResult) + ?.createImpactConnection; + } if (!result || (result as Error)?.message) throw new Error(); - if (!(result as ConnectPartnerResult).createImpactConnection?.success) { + if (!connectionResult?.success) { // Output backend errors to console for now console.error( "Failed to create Impact connection: ", - (result as ConnectPartnerResult).createImpactConnection.validationErrors + connectionResult?.validationErrors, ); throw new Error(); @@ -261,8 +310,7 @@ export function useIndirectTaxForm(props: IndirectTaxForm) { await refetch(); - const resultPublisher = (result as ConnectPartnerResult) - .createImpactConnection?.user?.impactConnection?.publisher; + const resultPublisher = connectionResult?.user?.impactConnection?.publisher; const hasValidCurrentDocument = validTaxDocument(resultPublisher?.requiredTaxDocumentType) && @@ -308,9 +356,8 @@ export function useIndirectTaxForm(props: IndirectTaxForm) { setLoading(true); try { - const { resultPublisher, hasValidCurrentDocument } = await connectPartner( - formData - ); + const { resultPublisher, hasValidCurrentDocument } = + await connectPartner(formData); if ( resultPublisher?.requiredTaxDocumentType && @@ -342,8 +389,9 @@ export function useIndirectTaxForm(props: IndirectTaxForm) { states: { step: step?.replace("/", ""), hideSteps: context.hideSteps, - disabled: loading || countriesLoading || connectLoading, - loading: loading || connectLoading || countriesLoading, + disabled: + loading || countriesLoading || connectLoading || completeLoading, + loading: loading || connectLoading || countriesLoading || completeLoading, isPartner: !!userData?.user?.impactConnection?.publisher, loadingError: !!userError?.message, formState: { diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash-dashboard/useTaxAndCashDashboard.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash-dashboard/useTaxAndCashDashboard.tsx index cb43daf717..3557aa2abe 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash-dashboard/useTaxAndCashDashboard.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash-dashboard/useTaxAndCashDashboard.tsx @@ -62,7 +62,7 @@ function getIndirectTaxType(taxInformation: ImpactPublisher["taxInformation"]) { if (taxInformation?.indirectTaxRegion) { const standardRegion = taxInformation.indirectTaxRegion.replace("_", ""); const taxType = regions.find( - (r) => r.regionCode === standardRegion + (r) => r.regionCode === standardRegion, )?.taxType; if (taxType) return taxType; @@ -78,7 +78,7 @@ function getIndirectTaxType(taxInformation: ImpactPublisher["taxInformation"]) { } export const useTaxAndCashDashboard = ( - props: TaxAndCashDashboard + props: TaxAndCashDashboard, ): Omit => { const setStep = useSetParent(TAX_CONTEXT_NAMESPACE); const setContext = useSetParent(TAX_FORM_CONTEXT_NAMESPACE); @@ -91,7 +91,7 @@ export const useTaxAndCashDashboard = ( const { data: taxSettingRes } = useQuery( GET_TAX_SETTING, - {} + {}, ); const locale = useLocale(); @@ -147,7 +147,7 @@ export const useTaxAndCashDashboard = ( }; const provinceName = INDIRECT_TAX_PROVINCES.find( - (p) => p.regionCode === publisher?.taxInformation?.indirectTaxRegion + (p) => p.regionCode === publisher?.taxInformation?.indirectTaxRegion, )?.displayName; const payoutStatus = data ? getStatus(data) : null; @@ -179,7 +179,7 @@ export const useTaxAndCashDashboard = ( province: provinceName, country: getCountryName( publisher?.taxInformation?.indirectTaxCountryCode, - locale + locale, ), notRegistered: !publisher?.taxInformation?.indirectTaxId, noFormNeeded: !documentType, diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/readme.md b/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/readme.md index 68f4733144..f3fd7c6281 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/readme.md +++ b/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/readme.md @@ -5,199 +5,198 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| --------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `backButton` | `back-button` | | `string` | `"Back"` | -| `cancelButton` | `cancel-button` | | `string` | `"Cancel"` | -| `continueButton` | `continue-button` | | `string` | `"Continue"` | -| `dashboard_accountReviewDescription` | `dashboard_account-review-description` | | `string` | `"This process takes 48 hours, payouts are on hold until it's completed. You will receive an email from our referral provider, Impact.com, if any issues arise. It contains details on how to resolve this issue. If you need further assistance, please reach out to our {supportLink}."` | -| `dashboard_accountReviewHeader` | `dashboard_account-review-header` | | `string` | `"Your account is under review"` | -| `dashboard_accountText` | `dashboard_account-text` | Shown before the participant’s bank account information. | `string` | `"Account"` | -| `dashboard_badgeTextAwaitingReview` | `dashboard_badge-text-awaiting-review` | Additional text displayed next to the tax form's status badge. | `string` | `"Awaiting review. Submitted on {dateSubmitted}."` | -| `dashboard_badgeTextSubmittedOn` | `dashboard_badge-text-submitted-on` | Additional text displayed next to the tax form's status badge | `string` | `"Submitted on {dateSubmitted}."` | -| `dashboard_badgeTextSubmittedOnW8` | `dashboard_badge-text-submitted-on-w-8` | Additional text displayed next to the tax form's status badge. | `string` | `"Submitted on {dateSubmitted}. Valid for three years after submission."` | -| `dashboard_bankNameMismatchDescription` | `dashboard_bank-name-mismatch-description` | | `string` | `"The bank account (beneficiary) name in your payment information does not match what was submitted in your tax form. Please review and update your payment information or tax form so that they match exactly and do not include any invalid characters. Your payouts are on hold until this is resolved."` | -| `dashboard_bankNameMismatchHeader` | `dashboard_bank-name-mismatch-header` | | `string` | `"Your payment information does not match your tax form"` | -| `dashboard_bankingInformationSectionHeader` | `dashboard_banking-information-section-header` | | `string` | `"Payout Information"` | -| `dashboard_beneficiaryNameInvalidDescription` | `dashboard_beneficiary-name-invalid-description` | | `string` | `"The account holder (beneficiary) name in your payment information does not match what was submitted in your tax form. Please review and update your payment information or tax form so that they match exactly and do not include any invalid characters. Your payouts are on hold until this is resolved."` | -| `dashboard_beneficiaryNameInvalidHeader` | `dashboard_beneficiary-name-invalid-header` | | `string` | `"Your payment information does not match your tax form"` | -| `dashboard_beneficiaryNameMismatchDescription` | `dashboard_beneficiary-name-mismatch-description` | | `string` | `"The account holder (beneficiary) name in your payment information does not match what was submitted in your tax form. Please review and update your payment information or tax form so that they match exactly and do not include any invalid characters. Your payouts are on hold until this is resolved."` | -| `dashboard_beneficiaryNameMismatchHeader` | `dashboard_beneficiary-name-mismatch-header` | | `string` | `"Your payment information does not match your tax form"` | -| `dashboard_dateColumnTitle` | `dashboard_date-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Date"` | -| `dashboard_earningsAfterTaxColumnTitle` | `dashboard_earnings-after-tax-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Earnings after tax"` | -| `dashboard_earningsColumnTitle` | `dashboard_earnings-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Earnings"` | -| `dashboard_editPaymentInformationButton` | `dashboard_edit-payment-information-button` | | `string` | `"Edit payout information"` | -| `dashboard_indirectTaxColumnTitle` | `dashboard_indirect-tax-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Indirect tax"` | -| `dashboard_indirectTaxDetails` | `dashboard_indirect-tax-details` | Displayed to participants who have submitted their indirect tax information. | `string` | `"{indirectTaxType} number: {indirectTaxNumber}"` | -| `dashboard_indirectTaxInfoCanada` | `dashboard_indirect-tax-info-canada` | If the participant is registered for indirect tax in Canada, display the province they’re registered in. | `string` | `"Registered in {province}, {country}"` | -| `dashboard_indirectTaxInfoOtherCountry` | `dashboard_indirect-tax-info-other-country` | If the participant is registered for indirect tax, display the country they’re registered in. | `string` | `"Registered in {country}"` | -| `dashboard_indirectTaxInfoSectionHeader` | `dashboard_indirect-tax-info-section-header` | | `string` | `"Indirect tax"` | -| `dashboard_indirectTaxInfoSpain` | `dashboard_indirect-tax-info-spain` | If the participant is registered for indirect tax in Spain, display the region they’re registered in. | `string` | `"Registered in {country}, {subRegion}"` | -| `dashboard_indirectTaxTooltipSupport` | `dashboard_indirect-tax-tooltip-support` | | `string` | `"To make changes to your indirect tax information, please contact our {supportLink}."` | -| `dashboard_invalidForm` | `dashboard_invalid-form` | Additional text displayed next to the tax form's status badge. | `string` | `"Make sure your information is correct and submit new form."` | -| `dashboard_invoiceColumnTitle` | `dashboard_invoice-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Invoice"` | -| `dashboard_invoiceDescription` | `dashboard_invoice-description` | | `string` | `"View and download your invoices to report your earnings and stay tax compliant."` | -| `dashboard_invoiceEmptyStateHeader` | `dashboard_invoice-empty-state-header` | | `string` | `"View your invoice details"` | -| `dashboard_invoiceEmptyStateText` | `dashboard_invoice-empty-state-text` | | `string` | `"Refer a friend to view the status of your invoices and rewards earned"` | -| `dashboard_invoiceHeader` | `dashboard_invoice-header` | | `string` | `"Invoices"` | -| `dashboard_invoiceMoreLabel` | `dashboard_invoice-more-label` | | `string` | `"Next"` | -| `dashboard_invoicePrevLabel` | `dashboard_invoice-prev-label` | | `string` | `"Prev"` | -| `dashboard_newFormButton` | `dashboard_new-form-button` | | `string` | `"Submit new tax form"` | -| `dashboard_noFormNeededSubtext` | `dashboard_no-form-needed-subtext` | No other statuses or badges will be displayed in the tax form section in this case. | `string` | `"Tax documents are only required if you are based in the US or joining the referral program of a US based brand."` | -| `dashboard_notRegisteredForTax` | `dashboard_not-registered-for-tax` | | `string` | `"Not registered for indirect tax. If you’ve previously registered with your tax authority, contact our {supportLink} to add your information to stay tax compliant."` | -| `dashboard_paymentOnHoldDescription` | `dashboard_payment-on-hold-description` | | `string` | `"Your payout is temporarily on hold while we review your new payment information, this process is usually resolved within 48 hours."` | -| `dashboard_paymentOnHoldHeader` | `dashboard_payment-on-hold-header` | | `string` | `"We are reviewing your new payout settings"` | -| `dashboard_paymentReturnedDescription` | `dashboard_payment-returned-description` | | `string` | `"Our recent payment attempt for your earnings was unsuccessful. Please review your payment information and make sure it is correct."` | -| `dashboard_paymentReturnedHeader` | `dashboard_payment-returned-header` | | `string` | `"Payout unsuccessful"` | -| `dashboard_payoutFromImpact` | `dashboard_payout-from-impact` | Displayed under the payout details card. | `string` | `"Your balance may take up to 24 hours to update. Payouts will be sent from our referral program provider, impact.com."` | -| `dashboard_payoutHoldAlertDescription` | `dashboard_payout-hold-alert-description` | Part of the alert displayed at the top of the page when there’s been an issue preventing payouts. | `string` | `"Please contact our {supportLink} or check your inbox for an email from our referral program provider, impact.com."` | -| `dashboard_payoutHoldAlertHeader` | `dashboard_payout-hold-alert-header` | Part of the alert displayed at the top of the page when there’s been an issue preventing payouts. | `string` | `"Your payout is on hold"` | -| `dashboard_payoutMissingInformationText` | `dashboard_payout-missing-information-text` | Text displayed for existing publishers that do not have saved banking information. | `string` | `"Missing banking information, go to Impact.com to resolve."` | -| `dashboard_qstNumber` | `dashboard_qst-number` | Displayed to participants registered in Quebec, Canada. | `string` | `"QST number: {qstNumber}"` | -| `dashboard_replaceTaxFormModalBodyText` | `dashboard_replace-tax-form-modal-body-text` | | `string` | `"Submitting a new tax form will remove your existing form. Make sure to sign and complete your new tax form to prevent any issues with your next payout."` | -| `dashboard_replaceTaxFormModalHeader` | `dashboard_replace-tax-form-modal-header` | | `string` | `"Replace existing tax form"` | -| `dashboard_requiredTaxForm` | `dashboard_required-tax-form` | Additional text displayed next to the tax form's status badge | `string` | `"Your payouts are on hold until you submit a {taxFormType} tax form."` | -| `dashboard_statusBadgeText` | `dashboard_status-badge-text` | | `string` | `"{badgeText, select, payoutToday {Payout Today} nextPayout {Next Payout} }"` | -| `dashboard_statusTextActive` | `dashboard_status-text-active` | | `string` | `"Active"` | -| `dashboard_statusTextNotActive` | `dashboard_status-text-not-active` | | `string` | `"Invalid Tax Form"` | -| `dashboard_statusTextNotVerified` | `dashboard_status-text-not-verified` | Displayed when the participant submitted their form but it is awaiting review. | `string` | `"Not Verified"` | -| `dashboard_statusTextRequired` | `dashboard_status-text-required` | Displayed when the participant has not submitted their required tax form. | `string` | `"Required"` | -| `dashboard_subRegionTaxNumber` | `dashboard_sub-region-tax-number` | | `string` | `"Income tax number: {subRegionTaxNumber}"` | -| `dashboard_taxAlertHeaderNotActiveW8` | `dashboard_tax-alert-header-not-active-w-8` | Part of the alert displayed at the top of the page. | `string` | `"{documentType} tax form is invalid"` | -| `dashboard_taxAlertHeaderNotActiveW9` | `dashboard_tax-alert-header-not-active-w-9` | Part of the alert displayed at the top of the page. | `string` | `"Your W-9 tax form has personal information that doesn’t match your profile"` | -| `dashboard_taxAlertNotActiveMessageW8` | `dashboard_tax-alert-not-active-message-w-8` | Part of the alert displayed at the top of the page. | `string` | `"Your tax form may have expired or has personal information that doesn’t match your profile. Please submit a new {documentType} form."` | -| `dashboard_taxAlertNotActiveMessageW9` | `dashboard_tax-alert-not-active-message-w-9` | Part of the alert displayed at the top of the page. | `string` | `"Please resubmit a new {documentType} form."` | -| `dashboard_taxDocumentSectionHeader` | `dashboard_tax-document-section-header` | | `string` | `"Tax documents"` | -| `dashboard_taxDocumentSectionSubHeader` | `dashboard_tax-document-section-sub-header` | Displayed under the tax document section header. | `string` | `"{documentType} tax form"` | -| `dashboard_termsAndConditions` | `dashboard_terms-and-conditions` | | `string` | `"Terms and Conditions"` | -| `dashboard_thresholdPayoutText` | `dashboard_threshold-payout-text` | Display participants' payout preference on the payout information card, indicating the balance at which they want to get paid. | `string` | `"Next payout occurs when balance is {thresholdBalance}"` | -| `dashboard_verificationFailedInternalDescription` | `dashboard_verification-failed-internal-description` | | `string` | `"Identity verification has failed. Our team is reviewing the report and will contact you with further information. If you don't hear from us contact our {supportLink}."` | -| `dashboard_verificationFailedInternalHeader` | `dashboard_verification-failed-internal-header` | | `string` | `"Identity verification usuccessful"` | -| `dashboard_verificationRequiredButtonText` | `dashboard_verification-required-button-text` | Part of the alert displayed at the top of the page when the user needs to verify their identity. | `string` | `"Start Verification"` | -| `dashboard_verificationRequiredDescription` | `dashboard_verification-required-description` | Part of the alert displayed at the top of the page when the user needs to verify their identity | `string` | `"Complete your verification to start receiving your cash rewards. It should only take a few minutes verify. If you run in to an issue verifying your identity contact our {supportLink}."` | -| `dashboard_verificationRequiredHeader` | `dashboard_verification-required-header` | Part of the alert displayed at the top of the page when the user needs to verify their identity. | `string` | `"Verify your identity"` | -| `dashboard_verificationRequiredInternalDescription` | `dashboard_verification-required-internal-description` | | `string` | `"Identity verification submission has been received. Our system is currently performing additional checks and analyzing the results. You will be updated shortly. If you don't hear from us contact our {supportLink}."` | -| `dashboard_verificationRequiredInternalHeader` | `dashboard_verification-required-internal-header` | | `string` | `"Identity verification in progress"` | -| `dashboard_verificationReviewInternalDescription` | `dashboard_verification-review-internal-description` | | `string` | `"Identity verification requires further review due to a potential error. Our team is reviewing the information and will update you shortly. If you don't hear from us contact our {supportLink}."` | -| `dashboard_verificationReviewInternalHeader` | `dashboard_verification-review-internal-header` | | `string` | `"Identity verification under review"` | -| `dashboard_w9RequiredButtonText` | `dashboard_w-9-required-button-text` | | `string` | `"Submit W-9"` | -| `dashboard_w9RequiredDescription` | `dashboard_w-9-required-description` | | `string` | `"You have surpassed the $600 threshold requiring a W-9 form or have multiple accounts with impact.com. To remove the hold, please submit your W-9 form."` | -| `dashboard_w9RequiredHeader` | `dashboard_w-9-required-header` | | `string` | `"Your next payout is on hold"` | -| `dashboard_withdrawalSettingsInvalidDescription` | `dashboard_withdrawal-settings-invalid-description` | | `string` | `"There are missing fields or invalid characters in your payment information. Please review your information and make sure it is correct. Your payouts are on hold until this is resolved."` | -| `dashboard_withdrawalSettingsInvalidHeader` | `dashboard_withdrawal-settings-invalid-header` | | `string` | `"Your payment information is incomplete or includes invalid characters"` | -| `demoData` | -- | | `{ step1_firstName?: string; step1_lastName?: string; step1_email?: string; step1_country?: string; step1_phoneNumber?: string; step1_address?: string; step1_city?: string; step1_state?: string; step1_province?: string; step1_region?: string; step1_postalCode?: string; step1_currency?: string; step1_currencyHelpText?: string; step1_allowBankingCollection?: string; step1_personalInformation?: string; step1_termsAndConditionsLabel?: string; step1_termsAndConditionsLink?: string; step1_searchForCurrencyText?: string; step2_indirectTax?: string; step2_indirectTaxDescription?: string; step2_indirectTaxDetails?: string; step2_otherRegion?: string; step2_otherRegionSubtext?: string; step2_notRegistered?: string; step2_notRegisteredSubtext?: string; step2_selectedRegion?: string; step2_indirectTaxNumber?: string; step2_province?: string; step2_indirectTaxNumberError?: string; step2_qstNumber?: string; step2_isRegisteredQST?: string; step2_isRegisteredSubRegionIncomeTax?: string; step2_subRegion?: string; step2_subRegionTaxNumberLabel?: string; step2_cannotChangeInfoAlert?: string; step3_taxForm?: string; step3_taxFormLabel?: string; step3_participantType?: string; step3_businessEntity?: string; step3_individualParticipant?: string; step3_taxFormDescription?: string; step3_taxFormDescriptionIndividualParticipant?: string; step3_taxFormDescriptionBusinessEntity?: string; step3_docusignExpired?: string; step3_docusignSessionWarning?: string; step3_docusignError?: string; step3_refreshButton?: string; step3_exitButton?: string; step3_modalTitle?: string; step3_modalDescription?: string; step3_modalButtonText?: string; step4_taxAndPayouts?: string; step4_directlyToBankAccount?: string; step4_toPayPalAccount?: string; step4_paymentScheduleBalanceThreshold?: string; step4_paymentScheduleFixedDay?: string; step4_paymentDaySelectLabel?: string; step4_paymentThresholdSelectLabel?: string; step4_paymentDayFirstOfMonthLabelText?: string; step4_paymentDayFifteenthOfMonthLabelText?: string; step4_paymentMethod?: string; step4_paymentSchedule?: string; step4_paymentMethodSubtext?: string; step4_payPalInputLabel?: string; step4_bankLocationLabel?: string; step4_beneficiaryAccountNameLabel?: string; step4_beneficiaryAccountNameDescription?: string; step4_bankAccountTypeLabel?: string; step4_checkingSelectItemLabel?: string; step4_savingsSelectItemLabel?: string; step4_bankAccountNumberLabel?: string; step4_ibanLabel?: string; step4_swiftCodeLabel?: string; step4_routingCodeLabel?: string; step4_bankNameLabel?: string; step4_classificationEntityLabel?: string; step4_businessSelectItemLabel?: string; step4_individualSelectItemLabel?: string; step4_foreignSelectItemLabel?: string; step4_classificationCPFLabel?: string; step4_patronymicNameLabel?: string; step4_voCodeLabel?: string; step4_agencyCodeLabel?: string; step4_branchCodeLabel?: string; step4_classificationLabel?: string; step4_taxPayerIdLabel?: string; step4_bankAddressLabel?: string; step4_bankCityLabel?: string; step4_bankStateLabel?: string; step4_bankPostalCodeLabel?: string; step4_eftWithdrawalLabel?: string; step4_fxWireProcessingFeeLabel?: string; step4_verifyEmailHeaderText?: string; step4_verifyEmailDescriptionText?: string; step4_modalTitle?: string; step4_modalDescription?: string; step4_modalButtonText?: string; dashboard_statusTextActive?: string; dashboard_statusTextNotActive?: string; dashboard_statusTextNotVerified?: string; dashboard_statusTextRequired?: string; dashboard_requiredTaxForm?: string; dashboard_badgeTextSubmittedOn?: string; dashboard_badgeTextSubmittedOnW8?: string; dashboard_badgeTextAwaitingReview?: string; dashboard_taxAlertHeaderNotActiveW9?: string; dashboard_taxAlertHeaderNotActiveW8?: string; dashboard_taxAlertNotActiveMessageW9?: string; dashboard_taxAlertNotActiveMessageW8?: string; dashboard_invalidForm?: string; dashboard_bankingInformationSectionHeader?: string; dashboard_taxDocumentSectionHeader?: string; dashboard_taxDocumentSectionSubHeader?: string; dashboard_noFormNeededSubtext?: string; dashboard_indirectTaxInfoSectionHeader?: string; dashboard_indirectTaxInfoCanada?: string; dashboard_indirectTaxInfoOtherCountry?: string; dashboard_indirectTaxInfoSpain?: string; dashboard_indirectTaxTooltipSupport?: string; dashboard_indirectTaxDetails?: string; dashboard_newFormButton?: string; dashboard_editPaymentInformationButton?: string; dashboard_notRegisteredForTax?: string; dashboard_qstNumber?: string; dashboard_subRegionTaxNumber?: string; dashboard_statusBadgeText?: string; dashboard_thresholdPayoutText?: string; dashboard_accountText?: string; dashboard_invoiceColumnTitle?: string; dashboard_dateColumnTitle?: string; dashboard_earningsColumnTitle?: string; dashboard_indirectTaxColumnTitle?: string; dashboard_payoutFromImpact?: string; dashboard_earningsAfterTaxColumnTitle?: string; dashboard_payoutHoldAlertHeader?: string; dashboard_payoutHoldAlertDescription?: string; dashboard_payoutMissingInformationText?: string; dashboard_invoiceDescription?: string; dashboard_invoicePrevLabel?: string; dashboard_invoiceMoreLabel?: string; dashboard_invoiceHeader?: string; dashboard_invoiceEmptyStateHeader?: string; dashboard_invoiceEmptyStateText?: string; dashboard_replaceTaxFormModalHeader?: string; dashboard_replaceTaxFormModalBodyText?: string; dashboard_verificationRequiredHeader?: string; dashboard_verificationRequiredDescription?: string; dashboard_verificationRequiredInternalHeader?: string; dashboard_verificationRequiredInternalDescription?: string; dashboard_verificationReviewInternalHeader?: string; dashboard_verificationReviewInternalDescription?: string; dashboard_verificationFailedInternalHeader?: string; dashboard_verificationFailedInternalDescription?: string; dashboard_verificationRequiredButtonText?: string; dashboard_w9RequiredHeader?: string; dashboard_w9RequiredDescription?: string; dashboard_accountReviewHeader?: string; dashboard_accountReviewDescription?: string; dashboard_paymentOnHoldHeader?: string; dashboard_paymentOnHoldDescription?: string; dashboard_beneficiaryNameInvalidHeader?: string; dashboard_beneficiaryNameInvalidDescription?: string; dashboard_beneficiaryNameMismatchHeader?: string; dashboard_beneficiaryNameMismatchDescription?: string; dashboard_bankNameMismatchHeader?: string; dashboard_bankNameMismatchDescription?: string; dashboard_withdrawalSettingsInvalidHeader?: string; dashboard_withdrawalSettingsInvalidDescription?: string; dashboard_paymentReturnedHeader?: string; dashboard_paymentReturnedDescription?: string; dashboard_termsAndConditions?: string; dashboard_w9RequiredButtonText?: string; formStep?: string; generalErrorTitle?: string; generalErrorDescription?: string; fieldRequiredError?: string; invalidCharacterError?: string; fieldInvalidError?: string; continueButton?: string; backButton?: string; cancelButton?: string; isPartnerAlertHeader?: string; isPartnerAlertDescription?: string; searchForCountryText?: string; loadingErrorAlertHeader?: string; loadingErrorAlertDescription?: string; taxAndPayoutsDescription?: string; supportLink?: string; termsAndConditions?: string; stateController?: string; demoData?: Partial>; disconnectedCallback?: () => void; getGeneralStepTextProps?: (prefix: string) => PickPrefix & { generalErrorTitle: string; generalErrorDescription: string; fieldRequiredError: string; invalidCharacterError: string; fieldInvalidError: string; continueButton: string; backButton: string; cancelButton: string; isPartnerAlertHeader: string; isPartnerAlertDescription: string; loadingErrorAlertHeader: string; loadingErrorAlertDescription: string; taxAndPayoutsDescription: string; searchForCountryText: string; formStep: string; supportLink: string; }; render?: () => any; }` | `undefined` | -| `fieldInvalidError` | `field-invalid-error` | Displayed under a field when it has an invalid entry. | `string` | `"{fieldName} is invalid"` | -| `fieldRequiredError` | `field-required-error` | Displayed under a field that is missing required information. | `string` | `"{fieldName} is required"` | -| `formStep` | `form-step` | | `string` | `"Step {step} of {count}"` | -| `generalErrorDescription` | `general-error-description` | Part of the alert displayed at the top of the page. | `string` | `"Please review your information and try again. If this problem continues, contact our {supportLink}."` | -| `generalErrorTitle` | `general-error-title` | Part of the alert displayed at the top of the page. | `string` | `"There was a problem submitting your information"` | -| `invalidCharacterError` | `invalid-character-error` | Displayed under a field that includes invalid characters (non-ASCII). | `string` | `"{fieldName} includes characters that aren't supported."` | -| `isPartnerAlertDescription` | `is-partner-alert-description` | Part of the alert displayed at the top of the page if the participant is already a registered partner on impact.com. | `string` | `"If you don’t recognize this referral program provider or believe this is a mistake, please contact our {supportLink} or sign up for this referral program with a different email."` | -| `isPartnerAlertHeader` | `is-partner-alert-header` | Part of the alert displayed at the top of the page if the participant is already a registered partner on impact.com. | `string` | `"An account with this email already exists with our referral program provider, impact.com"` | -| `loadingErrorAlertDescription` | `loading-error-alert-description` | Part of the alert displayed at the top of the page. | `string` | `"Please refresh the page and try again. If this problem continues, contact our {supportLink}."` | -| `loadingErrorAlertHeader` | `loading-error-alert-header` | Part of the alert displayed at the top of the page. | `string` | `"There was a problem loading your form"` | -| `searchForCountryText` | `search-for-country-text` | Placeholder text displayed in the country search dropdown | `string` | `"Search for country.."` | -| `stateController` | `state-controller` | | `string` | `"{}"` | -| `step1_address` | `step-1_address` | | `string` | `"Address"` | -| `step1_allowBankingCollection` | `step-1_allow-banking-collection` | Edit the property called terms and conditions text to change what's displayed for {termsAndConditionsLink}. | `string` | `"I have read the {termsAndConditionsLink} and allow impact.com to collect my tax and banking information"` | -| `step1_city` | `step-1_city` | | `string` | `"City"` | -| `step1_country` | `step-1_country` | | `string` | `"Country"` | -| `step1_currency` | `step-1_currency` | | `string` | `"Currency"` | -| `step1_currencyHelpText` | `step-1_currency-help-text` | | `string` | `"Choose your preferred payout currency"` | -| `step1_email` | `step-1_email` | | `string` | `"Email"` | -| `step1_firstName` | `step-1_first-name` | | `string` | `"First name"` | -| `step1_lastName` | `step-1_last-name` | | `string` | `"Last name"` | -| `step1_personalInformation` | `step-1_personal-information` | | `string` | `"Personal Information"` | -| `step1_phoneNumber` | `step-1_phone-number` | | `string` | `"Phone number"` | -| `step1_postalCode` | `step-1_postal-code` | | `string` | `"Postal code"` | -| `step1_province` | `step-1_province` | | `string` | `"Province"` | -| `step1_region` | `step-1_region` | | `string` | `"Region"` | -| `step1_searchForCurrencyText` | `step-1_search-for-currency-text` | Placeholder text displayed in the currency search dropdown | `string` | `"Search for currency.."` | -| `step1_state` | `step-1_state` | | `string` | `"State"` | -| `step1_termsAndConditionsLabel` | `step-1_terms-and-conditions-label` | The link text that appears in the terms and conditions checkbox | `string` | `"terms and conditions"` | -| `step1_termsAndConditionsLink` | `step-1_terms-and-conditions-link` | The link that appears in the terms and conditions checkbox | `string` | `"https://terms.advocate.impact.com/PayoutTermsAndConditions.html"` | -| `step2_cannotChangeInfoAlert` | `step-2_cannot-change-info-alert` | Communicate that after this step, only Support can change personal and indirect tax information. | `string` | `"Changes to your personal and indirect tax information can only be made through our {supportLink} after you complete this step. Make sure these are correct before continuing."` | -| `step2_indirectTax` | `step-2_indirect-tax` | | `string` | `"Indirect Tax"` | -| `step2_indirectTaxDescription` | `step-2_indirect-tax-description` | Displayed under the title of this step. | `string` | `"Indirect taxes (e.g. VAT, HST, GST) are transaction based taxes often applied to goods and services. Service providers are typically required to register with their tax authority and collect these taxes on behalf governments."` | -| `step2_indirectTaxDetails` | `step-2_indirect-tax-details` | Displayed with indirect tax registration options. | `string` | `"Indirect tax details"` | -| `step2_indirectTaxNumber` | `step-2_indirect-tax-number` | | `string` | `"{taxType, select, GST {GST number} HST {HST number} VAT {VAT number} CT {CT number} SST {SST number} GENERAL {Indirect tax number}}"` | -| `step2_indirectTaxNumberError` | `step-2_indirect-tax-number-error` | | `string` | `"{taxType, select, GST {GST number} HST {HST number} VAT {VAT number} CT {CT number} SST {SST number} GENERAL {Indirect tax number}} is required"` | -| `step2_isRegisteredQST` | `step-2_is-registered-q-s-t` | Displayed to participants registered for indirect tax in Quebec, Canada. | `string` | `"I am registered for QST Tax"` | -| `step2_isRegisteredSubRegionIncomeTax` | `step-2_is-registered-sub-region-income-tax` | Displayed to participants registered for indirect tax in Spain. | `string` | `"I am an individual registered for Income Tax purposes in Spain, and withholding tax will apply to any payments made to me."` | -| `step2_notRegistered` | `step-2_not-registered` | | `string` | `"Not registered for indirect tax"` | -| `step2_notRegisteredSubtext` | `step-2_not-registered-subtext` | Participants based in the US are considered not registered. | `string` | `"If you’ve never set up indirect tax with your tax authority, then you’re likely not considered registered."` | -| `step2_otherRegion` | `step-2_other-region` | | `string` | `"Registered for indirect tax"` | -| `step2_otherRegionSubtext` | `step-2_other-region-subtext` | Selecting this option will display fields to enter indirect tax details. | `string` | `"If you’ve registered with your tax authority, add your information to stay tax compliant."` | -| `step2_province` | `step-2_province` | | `string` | `"Province"` | -| `step2_qstNumber` | `step-2_qst-number` | Displayed to participants registered for QST. | `string` | `"QST number"` | -| `step2_selectedRegion` | `step-2_selected-region` | | `string` | `"Country / region of indirect tax"` | -| `step2_subRegion` | `step-2_sub-region` | Displayed to participants registered in Spain. | `string` | `"Sub-region"` | -| `step2_subRegionTaxNumberLabel` | `step-2_sub-region-tax-number-label` | | `string` | `"Income Tax Number"` | -| `step3_businessEntity` | `step-3_business-entity` | An option for the participant type field. Used to determine which W-8 form is required. | `string` | `"I represent a business"` | -| `step3_docusignError` | `step-3_docusign-error` | This appears inside the Docusign frame. | `string` | `"There was a problem displaying this form. Please refresh the page. If this problem continues, contact our {supportLink}."` | -| `step3_docusignExpired` | `step-3_docusign-expired` | This appears inside the Docusign frame. | `string` | `"For your security and privacy, we automatically end your session after 20 minutes of inactivity. Please refresh and re-enter your tax information to continue."` | -| `step3_docusignSessionWarning` | `step-3_docusign-session-warning` | Remind participants their session will time out after 20 minutes of inactivity. | `string` | `"For your security, we automatically end your session when you have not interacted with the form after 20 minutes."` | -| `step3_exitButton` | `step-3_exit-button` | | `string` | `"Exit"` | -| `step3_individualParticipant` | `step-3_individual-participant` | An option for the participant type field. Used to determine which W-8 form is required. | `string` | `"I am an individual participant"` | -| `step3_modalButtonText` | `step-3_modal-button-text` | | `string` | `"I understand"` | -| `step3_modalDescription` | `step-3_modal-description` | | `string` | `"Remember the name you enter in your tax form. It must exactly match the bank account holder name configured in the next step. {br}{br}Otherwise you will have to resubmit your form again and there will be delays receiving your payout."` | -| `step3_modalTitle` | `step-3_modal-title` | | `string` | `"Important Note"` | -| `step3_participantType` | `step-3_participant-type` | | `string` | `"Participant type"` | -| `step3_refreshButton` | `step-3_refresh-button` | | `string` | `"Refresh Page"` | -| `step3_taxForm` | `step-3_tax-form` | | `string` | `"Tax form"` | -| `step3_taxFormDescription` | `step-3_tax-form-description` | Displayed at the top of the page to participants based in the US. | `string` | `"Participants based in the US need to submit a {documentType} form."` | -| `step3_taxFormDescriptionBusinessEntity` | `step-3_tax-form-description-business-entity` | Displayed at the top of the page to participants representing a business. | `string` | `"Participants residing outside of the US working with a US Brand need to submit a {documentType} form."` | -| `step3_taxFormDescriptionIndividualParticipant` | `step-3_tax-form-description-individual-participant` | Displayed at the top of the page to individuals joining a US program who reside outside the country. | `string` | `"Participants residing outside of the US, joining the referral program of a US-based company, need to submit a {documentType} form."` | -| `step3_taxFormLabel` | `step-3_tax-form-label` | Display the type of tax form that the participant must submit. | `string` | `"{documentType} Tax Form"` | -| `step4_agencyCodeLabel` | `step-4_agency-code-label` | | `string` | `"Agency code"` | -| `step4_bankAccountNumberLabel` | `step-4_bank-account-number-label` | | `string` | `"Bank account number"` | -| `step4_bankAccountTypeLabel` | `step-4_bank-account-type-label` | | `string` | `"Bank account type"` | -| `step4_bankAddressLabel` | `step-4_bank-address-label` | | `string` | `"Bank address"` | -| `step4_bankCityLabel` | `step-4_bank-city-label` | | `string` | `"Bank city"` | -| `step4_bankLocationLabel` | `step-4_bank-location-label` | | `string` | `"Bank country location"` | -| `step4_bankNameLabel` | `step-4_bank-name-label` | | `string` | `"Bank name"` | -| `step4_bankPostalCodeLabel` | `step-4_bank-postal-code-label` | | `string` | `"Bank postal code"` | -| `step4_bankStateLabel` | `step-4_bank-state-label` | | `string` | `"Bank Province / State"` | -| `step4_beneficiaryAccountNameDescription` | `step-4_beneficiary-account-name-description` | | `string` | `"The beneficiary name of your bank account. Ensure this matches the name on your tax form."` | -| `step4_beneficiaryAccountNameLabel` | `step-4_beneficiary-account-name-label` | | `string` | `"Account holder name"` | -| `step4_branchCodeLabel` | `step-4_branch-code-label` | | `string` | `"Branch code"` | -| `step4_businessSelectItemLabel` | `step-4_business-select-item-label` | One of three options listed for the classification field | `string` | `"Business"` | -| `step4_checkingSelectItemLabel` | `step-4_checking-select-item-label` | | `string` | `"Checking"` | -| `step4_classificationCPFLabel` | `step-4_classification-c-p-f-label` | | `string` | `"Classification CPF"` | -| `step4_classificationEntityLabel` | `step-4_classification-entity-label` | | `string` | `"Classification entity"` | -| `step4_classificationLabel` | `step-4_classification-label` | Label text for the classification input field | `string` | `"Classification"` | -| `step4_directlyToBankAccount` | `step-4_directly-to-bank-account` | | `string` | `"Directly to my bank account"` | -| `step4_eftWithdrawalLabel` | `step-4_eft-withdrawal-label` | Default payment method to the participants’ bank account. | `string` | `"EFT Withdrawal (free)"` | -| `step4_foreignSelectItemLabel` | `step-4_foreign-select-item-label` | One of three options listed for the classification field | `string` | `"Foreign"` | -| `step4_fxWireProcessingFeeLabel` | `step-4_fx-wire-processing-fee-label` | | `string` | `"FX Wire (Processing Fee {currency}{defaultFxFee}.00)"` | -| `step4_ibanLabel` | `step-4_iban-label` | | `string` | `"IBAN"` | -| `step4_individualSelectItemLabel` | `step-4_individual-select-item-label` | One of three options listed for the classification field | `string` | `"Individual"` | -| `step4_modalButtonText` | `step-4_modal-button-text` | | `string` | `"I understand, update my information"` | -| `step4_modalDescription` | `step-4_modal-description` | | `string` | `"Updating payment information places your account and payouts on hold for up to 48 hours while we verify your change. Payments scheduled during the hold period are skipped."` | -| `step4_modalTitle` | `step-4_modal-title` | | `string` | `"Important Note"` | -| `step4_patronymicNameLabel` | `step-4_patronymic-name-label` | | `string` | `"Patronymic name"` | -| `step4_payPalInputLabel` | `step-4_pay-pal-input-label` | Displayed to participants who choose PayPal as their payout method | `string` | `"PayPal email"` | -| `step4_paymentDayFifteenthOfMonthLabelText` | `step-4_payment-day-fifteenth-of-month-label-text` | One of two payment day options | `string` | `"15th of the month"` | -| `step4_paymentDayFirstOfMonthLabelText` | `step-4_payment-day-first-of-month-label-text` | One of two payment day options | `string` | `"1st of the month"` | -| `step4_paymentDaySelectLabel` | `step-4_payment-day-select-label` | Let the participant choose what day of the month they’ll get paid | `string` | `"Payment Day"` | -| `step4_paymentMethod` | `step-4_payment-method` | | `string` | `"Payment method"` | -| `step4_paymentMethodSubtext` | `step-4_payment-method-subtext` | | `string` | `"Payouts will be sent from our referral program provider, impact.com."` | -| `step4_paymentSchedule` | `step-4_payment-schedule` | | `string` | `"Payment schedule"` | -| `step4_paymentScheduleBalanceThreshold` | `step-4_payment-schedule-balance-threshold` | | `string` | `"Pay me when my balance reaches a threshold"` | -| `step4_paymentScheduleFixedDay` | `step-4_payment-schedule-fixed-day` | | `string` | `"Pay me on a fixed day of the month"` | -| `step4_paymentThresholdSelectLabel` | `step-4_payment-threshold-select-label` | Participant use this field to select the balance at which they want to be paid | `string` | `"Payment threshold"` | -| `step4_routingCodeLabel` | `step-4_routing-code-label` | | `string` | `"{bankCountry, select, AU {BSB number} CA {Routing number} CZ {Bank code} HK {Clearing code} SG {Clearing code} US {ABA routing number} NZ {BSB number} ZA {Bank/Branch number} IN {IFSC} CNY {CNAPS} other {Routing code} }"` | -| `step4_savingsSelectItemLabel` | `step-4_savings-select-item-label` | Label text for the savings account type select item | `string` | `"Savings"` | -| `step4_swiftCodeLabel` | `step-4_swift-code-label` | | `string` | `"SWIFT code"` | -| `step4_taxAndPayouts` | `step-4_tax-and-payouts` | | `string` | `"Payouts"` | -| `step4_taxPayerIdLabel` | `step-4_tax-payer-id-label` | | `string` | `"Beneficiary INN"` | -| `step4_toPayPalAccount` | `step-4_to-pay-pal-account` | | `string` | `"PayPal (2% processing fee capped to {feeCap})"` | -| `step4_verifyEmailDescriptionText` | `step-4_verify-email-description-text` | | `string` | `"Verify your email to update your payment settings. Enter the code sent to {email} from our referral provider, impact.com."` | -| `step4_verifyEmailHeaderText` | `step-4_verify-email-header-text` | | `string` | `"Verify your email"` | -| `step4_voCodeLabel` | `step-4_vo-code-label` | | `string` | `"VO code"` | -| `supportLink` | `support-link` | Link text for contacting support team | `string` | `"support team"` | -| `taxAndPayoutsDescription` | `tax-and-payouts-description` | Displayed at the top of the page on all set up steps. | `string` | `"Submit your tax documents and add your banking information to receive your rewards."` | -| `termsAndConditions` | `terms-and-conditions` | Link text for Terms and Conditions | `string` | `"Terms and Conditions"` | +| Property | Attribute | Description | Type | Default | +| --------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `backButton` | `back-button` | | `string` | `"Back"` | +| `cancelButton` | `cancel-button` | | `string` | `"Cancel"` | +| `continueButton` | `continue-button` | | `string` | `"Continue"` | +| `dashboard_accountReviewDescription` | `dashboard_account-review-description` | | `string` | `"This process takes 48 hours, payouts are on hold until it's completed. You will receive an email from our referral provider, Impact.com, if any issues arise. It contains details on how to resolve this issue. If you need further assistance, please reach out to our {supportLink}."` | +| `dashboard_accountReviewHeader` | `dashboard_account-review-header` | | `string` | `"Your account is under review"` | +| `dashboard_accountText` | `dashboard_account-text` | Shown before the participant’s bank account information. | `string` | `"Account"` | +| `dashboard_badgeTextAwaitingReview` | `dashboard_badge-text-awaiting-review` | Additional text displayed next to the tax form's status badge. | `string` | `"Awaiting review. Submitted on {dateSubmitted}."` | +| `dashboard_badgeTextSubmittedOn` | `dashboard_badge-text-submitted-on` | Additional text displayed next to the tax form's status badge | `string` | `"Submitted on {dateSubmitted}."` | +| `dashboard_badgeTextSubmittedOnW8` | `dashboard_badge-text-submitted-on-w-8` | Additional text displayed next to the tax form's status badge. | `string` | `"Submitted on {dateSubmitted}. Valid for three years after submission."` | +| `dashboard_bankNameMismatchDescription` | `dashboard_bank-name-mismatch-description` | | `string` | `"The bank account (beneficiary) name in your payment information does not match what was submitted in your tax form. Please review and update your payment information or tax form so that they match exactly and do not include any invalid characters. Your payouts are on hold until this is resolved."` | +| `dashboard_bankNameMismatchHeader` | `dashboard_bank-name-mismatch-header` | | `string` | `"Your payment information does not match your tax form"` | +| `dashboard_bankingInformationSectionHeader` | `dashboard_banking-information-section-header` | | `string` | `"Payout Information"` | +| `dashboard_beneficiaryNameInvalidDescription` | `dashboard_beneficiary-name-invalid-description` | | `string` | `"The account holder (beneficiary) name in your payment information does not match what was submitted in your tax form. Please review and update your payment information or tax form so that they match exactly and do not include any invalid characters. Your payouts are on hold until this is resolved."` | +| `dashboard_beneficiaryNameInvalidHeader` | `dashboard_beneficiary-name-invalid-header` | | `string` | `"Your payment information does not match your tax form"` | +| `dashboard_beneficiaryNameMismatchDescription` | `dashboard_beneficiary-name-mismatch-description` | | `string` | `"The account holder (beneficiary) name in your payment information does not match what was submitted in your tax form. Please review and update your payment information or tax form so that they match exactly and do not include any invalid characters. Your payouts are on hold until this is resolved."` | +| `dashboard_beneficiaryNameMismatchHeader` | `dashboard_beneficiary-name-mismatch-header` | | `string` | `"Your payment information does not match your tax form"` | +| `dashboard_dateColumnTitle` | `dashboard_date-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Date"` | +| `dashboard_earningsAfterTaxColumnTitle` | `dashboard_earnings-after-tax-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Earnings after tax"` | +| `dashboard_earningsColumnTitle` | `dashboard_earnings-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Earnings"` | +| `dashboard_editPaymentInformationButton` | `dashboard_edit-payment-information-button` | | `string` | `"Edit payout information"` | +| `dashboard_indirectTaxColumnTitle` | `dashboard_indirect-tax-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Indirect tax"` | +| `dashboard_indirectTaxDetails` | `dashboard_indirect-tax-details` | Displayed to participants who have submitted their indirect tax information. | `string` | `"{indirectTaxType} number: {indirectTaxNumber}"` | +| `dashboard_indirectTaxInfoCanada` | `dashboard_indirect-tax-info-canada` | If the participant is registered for indirect tax in Canada, display the province they’re registered in. | `string` | `"Registered in {province}, {country}"` | +| `dashboard_indirectTaxInfoOtherCountry` | `dashboard_indirect-tax-info-other-country` | If the participant is registered for indirect tax, display the country they’re registered in. | `string` | `"Registered in {country}"` | +| `dashboard_indirectTaxInfoSectionHeader` | `dashboard_indirect-tax-info-section-header` | | `string` | `"Indirect tax"` | +| `dashboard_indirectTaxInfoSpain` | `dashboard_indirect-tax-info-spain` | If the participant is registered for indirect tax in Spain, display the region they’re registered in. | `string` | `"Registered in {country}, {subRegion}"` | +| `dashboard_indirectTaxTooltipSupport` | `dashboard_indirect-tax-tooltip-support` | | `string` | `"To make changes to your indirect tax information, please contact our {supportLink}."` | +| `dashboard_invalidForm` | `dashboard_invalid-form` | Additional text displayed next to the tax form's status badge. | `string` | `"Make sure your information is correct and submit new form."` | +| `dashboard_invoiceColumnTitle` | `dashboard_invoice-column-title` | Part of the Invoice table displayed at the bottom of the page. | `string` | `"Invoice"` | +| `dashboard_invoiceDescription` | `dashboard_invoice-description` | | `string` | `"View and download your invoices to report your earnings and stay tax compliant."` | +| `dashboard_invoiceEmptyStateHeader` | `dashboard_invoice-empty-state-header` | | `string` | `"View your invoice details"` | +| `dashboard_invoiceEmptyStateText` | `dashboard_invoice-empty-state-text` | | `string` | `"Refer a friend to view the status of your invoices and rewards earned"` | +| `dashboard_invoiceHeader` | `dashboard_invoice-header` | | `string` | `"Invoices"` | +| `dashboard_invoiceMoreLabel` | `dashboard_invoice-more-label` | | `string` | `"Next"` | +| `dashboard_invoicePrevLabel` | `dashboard_invoice-prev-label` | | `string` | `"Prev"` | +| `dashboard_newFormButton` | `dashboard_new-form-button` | | `string` | `"Submit new tax form"` | +| `dashboard_noFormNeededSubtext` | `dashboard_no-form-needed-subtext` | No other statuses or badges will be displayed in the tax form section in this case. | `string` | `"Tax documents are only required if you are based in the US or joining the referral program of a US based brand."` | +| `dashboard_notRegisteredForTax` | `dashboard_not-registered-for-tax` | | `string` | `"Not registered for indirect tax. If you’ve previously registered with your tax authority, contact our {supportLink} to add your information to stay tax compliant."` | +| `dashboard_paymentOnHoldDescription` | `dashboard_payment-on-hold-description` | | `string` | `"Your payout is temporarily on hold while we review your new payment information, this process is usually resolved within 48 hours."` | +| `dashboard_paymentOnHoldHeader` | `dashboard_payment-on-hold-header` | | `string` | `"We are reviewing your new payout settings"` | +| `dashboard_paymentReturnedDescription` | `dashboard_payment-returned-description` | | `string` | `"Our recent payment attempt for your earnings was unsuccessful. Please review your payment information and make sure it is correct."` | +| `dashboard_paymentReturnedHeader` | `dashboard_payment-returned-header` | | `string` | `"Payout unsuccessful"` | +| `dashboard_payoutFromImpact` | `dashboard_payout-from-impact` | Displayed under the payout details card. | `string` | `"Your balance may take up to 24 hours to update. Payouts will be sent from our referral program provider, impact.com."` | +| `dashboard_payoutHoldAlertDescription` | `dashboard_payout-hold-alert-description` | Part of the alert displayed at the top of the page when there’s been an issue preventing payouts. | `string` | `"Please contact our {supportLink} or check your inbox for an email from our referral program provider, impact.com."` | +| `dashboard_payoutHoldAlertHeader` | `dashboard_payout-hold-alert-header` | Part of the alert displayed at the top of the page when there’s been an issue preventing payouts. | `string` | `"Your payout is on hold"` | +| `dashboard_payoutMissingInformationText` | `dashboard_payout-missing-information-text` | Text displayed for existing publishers that do not have saved banking information. | `string` | `"Missing banking information, go to Impact.com to resolve."` | +| `dashboard_qstNumber` | `dashboard_qst-number` | Displayed to participants registered in Quebec, Canada. | `string` | `"QST number: {qstNumber}"` | +| `dashboard_replaceTaxFormModalBodyText` | `dashboard_replace-tax-form-modal-body-text` | | `string` | `"Submitting a new tax form will remove your existing form. Make sure to sign and complete your new tax form to prevent any issues with your next payout."` | +| `dashboard_replaceTaxFormModalHeader` | `dashboard_replace-tax-form-modal-header` | | `string` | `"Replace existing tax form"` | +| `dashboard_requiredTaxForm` | `dashboard_required-tax-form` | Additional text displayed next to the tax form's status badge | `string` | `"Your payouts are on hold until you submit a {taxFormType} tax form."` | +| `dashboard_statusBadgeText` | `dashboard_status-badge-text` | | `string` | `"{badgeText, select, payoutToday {Payout Today} nextPayout {Next Payout} }"` | +| `dashboard_statusTextActive` | `dashboard_status-text-active` | | `string` | `"Active"` | +| `dashboard_statusTextNotActive` | `dashboard_status-text-not-active` | | `string` | `"Invalid Tax Form"` | +| `dashboard_statusTextNotVerified` | `dashboard_status-text-not-verified` | Displayed when the participant submitted their form but it is awaiting review. | `string` | `"Not Verified"` | +| `dashboard_statusTextRequired` | `dashboard_status-text-required` | Displayed when the participant has not submitted their required tax form. | `string` | `"Required"` | +| `dashboard_subRegionTaxNumber` | `dashboard_sub-region-tax-number` | | `string` | `"Income tax number: {subRegionTaxNumber}"` | +| `dashboard_taxAlertHeaderNotActiveW8` | `dashboard_tax-alert-header-not-active-w-8` | Part of the alert displayed at the top of the page. | `string` | `"{documentType} tax form is invalid"` | +| `dashboard_taxAlertHeaderNotActiveW9` | `dashboard_tax-alert-header-not-active-w-9` | Part of the alert displayed at the top of the page. | `string` | `"Your W-9 tax form has personal information that doesn’t match your profile"` | +| `dashboard_taxAlertNotActiveMessageW8` | `dashboard_tax-alert-not-active-message-w-8` | Part of the alert displayed at the top of the page. | `string` | `"Your tax form may have expired or has personal information that doesn’t match your profile. Please submit a new {documentType} form."` | +| `dashboard_taxAlertNotActiveMessageW9` | `dashboard_tax-alert-not-active-message-w-9` | Part of the alert displayed at the top of the page. | `string` | `"Please resubmit a new {documentType} form."` | +| `dashboard_taxDocumentSectionHeader` | `dashboard_tax-document-section-header` | | `string` | `"Tax documents"` | +| `dashboard_taxDocumentSectionSubHeader` | `dashboard_tax-document-section-sub-header` | Displayed under the tax document section header. | `string` | `"{documentType} tax form"` | +| `dashboard_termsAndConditions` | `dashboard_terms-and-conditions` | | `string` | `"Terms and Conditions"` | +| `dashboard_thresholdPayoutText` | `dashboard_threshold-payout-text` | Display participants' payout preference on the payout information card, indicating the balance at which they want to get paid. | `string` | `"Next payout occurs when balance is {thresholdBalance}"` | +| `dashboard_verificationFailedInternalDescription` | `dashboard_verification-failed-internal-description` | | `string` | `"Identity verification has failed. Our team is reviewing the report and will contact you with further information. If you don't hear from us contact our {supportLink}."` | +| `dashboard_verificationFailedInternalHeader` | `dashboard_verification-failed-internal-header` | | `string` | `"Identity verification usuccessful"` | +| `dashboard_verificationRequiredButtonText` | `dashboard_verification-required-button-text` | Part of the alert displayed at the top of the page when the user needs to verify their identity. | `string` | `"Start Verification"` | +| `dashboard_verificationRequiredDescription` | `dashboard_verification-required-description` | Part of the alert displayed at the top of the page when the user needs to verify their identity | `string` | `"Complete your verification to start receiving your cash rewards. It should only take a few minutes verify. If you run in to an issue verifying your identity contact our {supportLink}."` | +| `dashboard_verificationRequiredHeader` | `dashboard_verification-required-header` | Part of the alert displayed at the top of the page when the user needs to verify their identity. | `string` | `"Verify your identity"` | +| `dashboard_verificationRequiredInternalDescription` | `dashboard_verification-required-internal-description` | | `string` | `"Identity verification submission has been received. Our system is currently performing additional checks and analyzing the results. You will be updated shortly. If you don't hear from us contact our {supportLink}."` | +| `dashboard_verificationRequiredInternalHeader` | `dashboard_verification-required-internal-header` | | `string` | `"Identity verification in progress"` | +| `dashboard_verificationReviewInternalDescription` | `dashboard_verification-review-internal-description` | | `string` | `"Identity verification requires further review due to a potential error. Our team is reviewing the information and will update you shortly. If you don't hear from us contact our {supportLink}."` | +| `dashboard_verificationReviewInternalHeader` | `dashboard_verification-review-internal-header` | | `string` | `"Identity verification under review"` | +| `dashboard_w9RequiredButtonText` | `dashboard_w-9-required-button-text` | | `string` | `"Submit W-9"` | +| `dashboard_w9RequiredDescription` | `dashboard_w-9-required-description` | | `string` | `"You have surpassed the $600 threshold requiring a W-9 form or have multiple accounts with impact.com. To remove the hold, please submit your W-9 form."` | +| `dashboard_w9RequiredHeader` | `dashboard_w-9-required-header` | | `string` | `"Your next payout is on hold"` | +| `dashboard_withdrawalSettingsInvalidDescription` | `dashboard_withdrawal-settings-invalid-description` | | `string` | `"There are missing fields or invalid characters in your payment information. Please review your information and make sure it is correct. Your payouts are on hold until this is resolved."` | +| `dashboard_withdrawalSettingsInvalidHeader` | `dashboard_withdrawal-settings-invalid-header` | | `string` | `"Your payment information is incomplete or includes invalid characters"` | +| `demoData` | -- | | `{ step1_firstName?: string; step1_lastName?: string; step1_email?: string; step1_country?: string; step1_phoneNumber?: string; step1_address?: string; step1_city?: string; step1_state?: string; step1_province?: string; step1_region?: string; step1_postalCode?: string; step1_currency?: string; step1_allowBankingCollection?: string; step1_personalInformation?: string; step1_termsAndConditionsLabel?: string; step1_termsAndConditionsLink?: string; step1_searchForCurrencyText?: string; step2_indirectTax?: string; step2_indirectTaxDescription?: string; step2_indirectTaxDetails?: string; step2_otherRegion?: string; step2_otherRegionSubtext?: string; step2_notRegistered?: string; step2_notRegisteredSubtext?: string; step2_selectedRegion?: string; step2_indirectTaxNumber?: string; step2_province?: string; step2_indirectTaxNumberError?: string; step2_qstNumber?: string; step2_isRegisteredQST?: string; step2_isRegisteredSubRegionIncomeTax?: string; step2_subRegion?: string; step2_subRegionTaxNumberLabel?: string; step2_cannotChangeInfoAlert?: string; step3_taxForm?: string; step3_taxFormLabel?: string; step3_participantType?: string; step3_businessEntity?: string; step3_individualParticipant?: string; step3_taxFormDescription?: string; step3_taxFormDescriptionIndividualParticipant?: string; step3_taxFormDescriptionBusinessEntity?: string; step3_docusignExpired?: string; step3_docusignSessionWarning?: string; step3_docusignError?: string; step3_refreshButton?: string; step3_exitButton?: string; step3_modalTitle?: string; step3_modalDescription?: string; step3_modalButtonText?: string; step4_taxAndPayouts?: string; step4_directlyToBankAccount?: string; step4_toPayPalAccount?: string; step4_paymentScheduleBalanceThreshold?: string; step4_paymentScheduleFixedDay?: string; step4_paymentDaySelectLabel?: string; step4_paymentThresholdSelectLabel?: string; step4_paymentDayFirstOfMonthLabelText?: string; step4_paymentDayFifteenthOfMonthLabelText?: string; step4_paymentMethod?: string; step4_paymentSchedule?: string; step4_paymentMethodSubtext?: string; step4_payPalInputLabel?: string; step4_bankLocationLabel?: string; step4_beneficiaryAccountNameLabel?: string; step4_beneficiaryAccountNameDescription?: string; step4_bankAccountTypeLabel?: string; step4_checkingSelectItemLabel?: string; step4_savingsSelectItemLabel?: string; step4_bankAccountNumberLabel?: string; step4_ibanLabel?: string; step4_swiftCodeLabel?: string; step4_routingCodeLabel?: string; step4_bankNameLabel?: string; step4_classificationEntityLabel?: string; step4_businessSelectItemLabel?: string; step4_individualSelectItemLabel?: string; step4_foreignSelectItemLabel?: string; step4_classificationCPFLabel?: string; step4_patronymicNameLabel?: string; step4_voCodeLabel?: string; step4_agencyCodeLabel?: string; step4_branchCodeLabel?: string; step4_classificationLabel?: string; step4_taxPayerIdLabel?: string; step4_bankAddressLabel?: string; step4_bankCityLabel?: string; step4_bankStateLabel?: string; step4_bankPostalCodeLabel?: string; step4_eftWithdrawalLabel?: string; step4_fxWireProcessingFeeLabel?: string; step4_verifyEmailHeaderText?: string; step4_verifyEmailDescriptionText?: string; step4_modalTitle?: string; step4_modalDescription?: string; step4_modalButtonText?: string; dashboard_statusTextActive?: string; dashboard_statusTextNotActive?: string; dashboard_statusTextNotVerified?: string; dashboard_statusTextRequired?: string; dashboard_requiredTaxForm?: string; dashboard_badgeTextSubmittedOn?: string; dashboard_badgeTextSubmittedOnW8?: string; dashboard_badgeTextAwaitingReview?: string; dashboard_taxAlertHeaderNotActiveW9?: string; dashboard_taxAlertHeaderNotActiveW8?: string; dashboard_taxAlertNotActiveMessageW9?: string; dashboard_taxAlertNotActiveMessageW8?: string; dashboard_invalidForm?: string; dashboard_bankingInformationSectionHeader?: string; dashboard_taxDocumentSectionHeader?: string; dashboard_taxDocumentSectionSubHeader?: string; dashboard_noFormNeededSubtext?: string; dashboard_indirectTaxInfoSectionHeader?: string; dashboard_indirectTaxInfoCanada?: string; dashboard_indirectTaxInfoOtherCountry?: string; dashboard_indirectTaxInfoSpain?: string; dashboard_indirectTaxTooltipSupport?: string; dashboard_indirectTaxDetails?: string; dashboard_newFormButton?: string; dashboard_editPaymentInformationButton?: string; dashboard_notRegisteredForTax?: string; dashboard_qstNumber?: string; dashboard_subRegionTaxNumber?: string; dashboard_statusBadgeText?: string; dashboard_thresholdPayoutText?: string; dashboard_accountText?: string; dashboard_invoiceColumnTitle?: string; dashboard_dateColumnTitle?: string; dashboard_earningsColumnTitle?: string; dashboard_indirectTaxColumnTitle?: string; dashboard_payoutFromImpact?: string; dashboard_earningsAfterTaxColumnTitle?: string; dashboard_payoutHoldAlertHeader?: string; dashboard_payoutHoldAlertDescription?: string; dashboard_payoutMissingInformationText?: string; dashboard_invoiceDescription?: string; dashboard_invoicePrevLabel?: string; dashboard_invoiceMoreLabel?: string; dashboard_invoiceHeader?: string; dashboard_invoiceEmptyStateHeader?: string; dashboard_invoiceEmptyStateText?: string; dashboard_replaceTaxFormModalHeader?: string; dashboard_replaceTaxFormModalBodyText?: string; dashboard_verificationRequiredHeader?: string; dashboard_verificationRequiredDescription?: string; dashboard_verificationRequiredInternalHeader?: string; dashboard_verificationRequiredInternalDescription?: string; dashboard_verificationReviewInternalHeader?: string; dashboard_verificationReviewInternalDescription?: string; dashboard_verificationFailedInternalHeader?: string; dashboard_verificationFailedInternalDescription?: string; dashboard_verificationRequiredButtonText?: string; dashboard_w9RequiredHeader?: string; dashboard_w9RequiredDescription?: string; dashboard_accountReviewHeader?: string; dashboard_accountReviewDescription?: string; dashboard_paymentOnHoldHeader?: string; dashboard_paymentOnHoldDescription?: string; dashboard_beneficiaryNameInvalidHeader?: string; dashboard_beneficiaryNameInvalidDescription?: string; dashboard_beneficiaryNameMismatchHeader?: string; dashboard_beneficiaryNameMismatchDescription?: string; dashboard_bankNameMismatchHeader?: string; dashboard_bankNameMismatchDescription?: string; dashboard_withdrawalSettingsInvalidHeader?: string; dashboard_withdrawalSettingsInvalidDescription?: string; dashboard_paymentReturnedHeader?: string; dashboard_paymentReturnedDescription?: string; dashboard_termsAndConditions?: string; dashboard_w9RequiredButtonText?: string; formStep?: string; generalErrorTitle?: string; generalErrorDescription?: string; fieldRequiredError?: string; invalidCharacterError?: string; fieldInvalidError?: string; continueButton?: string; backButton?: string; cancelButton?: string; isPartnerAlertHeader?: string; isPartnerAlertDescription?: string; searchForCountryText?: string; loadingErrorAlertHeader?: string; loadingErrorAlertDescription?: string; taxAndPayoutsDescription?: string; supportLink?: string; termsAndConditions?: string; stateController?: string; demoData?: Partial>; disconnectedCallback?: () => void; getGeneralStepTextProps?: (prefix: string) => PickPrefix & { generalErrorTitle: string; generalErrorDescription: string; fieldRequiredError: string; invalidCharacterError: string; fieldInvalidError: string; continueButton: string; backButton: string; cancelButton: string; isPartnerAlertHeader: string; isPartnerAlertDescription: string; loadingErrorAlertHeader: string; loadingErrorAlertDescription: string; taxAndPayoutsDescription: string; searchForCountryText: string; formStep: string; supportLink: string; }; render?: () => any; }` | `undefined` | +| `fieldInvalidError` | `field-invalid-error` | Displayed under a field when it has an invalid entry. | `string` | `"{fieldName} is invalid"` | +| `fieldRequiredError` | `field-required-error` | Displayed under a field that is missing required information. | `string` | `"{fieldName} is required"` | +| `formStep` | `form-step` | | `string` | `"Step {step} of {count}"` | +| `generalErrorDescription` | `general-error-description` | Part of the alert displayed at the top of the page. | `string` | `"Please review your information and try again. If this problem continues, contact our {supportLink}."` | +| `generalErrorTitle` | `general-error-title` | Part of the alert displayed at the top of the page. | `string` | `"There was a problem submitting your information"` | +| `invalidCharacterError` | `invalid-character-error` | Displayed under a field that includes invalid characters (non-ASCII). | `string` | `"{fieldName} includes characters that aren't supported."` | +| `isPartnerAlertDescription` | `is-partner-alert-description` | Part of the alert displayed at the top of the page if the participant is already a registered partner on impact.com. | `string` | `"If you don’t recognize this referral program provider or believe this is a mistake, please contact our {supportLink} or sign up for this referral program with a different email."` | +| `isPartnerAlertHeader` | `is-partner-alert-header` | Part of the alert displayed at the top of the page if the participant is already a registered partner on impact.com. | `string` | `"An account with this email already exists with our referral program provider, impact.com"` | +| `loadingErrorAlertDescription` | `loading-error-alert-description` | Part of the alert displayed at the top of the page. | `string` | `"Please refresh the page and try again. If this problem continues, contact our {supportLink}."` | +| `loadingErrorAlertHeader` | `loading-error-alert-header` | Part of the alert displayed at the top of the page. | `string` | `"There was a problem loading your form"` | +| `searchForCountryText` | `search-for-country-text` | Placeholder text displayed in the country search dropdown | `string` | `"Search for country.."` | +| `stateController` | `state-controller` | | `string` | `"{}"` | +| `step1_address` | `step-1_address` | | `string` | `"Address"` | +| `step1_allowBankingCollection` | `step-1_allow-banking-collection` | Edit the property called terms and conditions text to change what's displayed for {termsAndConditionsLink}. | `string` | `"I have read the {termsAndConditionsLink} and allow impact.com to collect my tax and banking information"` | +| `step1_city` | `step-1_city` | | `string` | `"City"` | +| `step1_country` | `step-1_country` | | `string` | `"Country"` | +| `step1_currency` | `step-1_currency` | | `string` | `"Currency"` | +| `step1_email` | `step-1_email` | | `string` | `"Email"` | +| `step1_firstName` | `step-1_first-name` | | `string` | `"First name"` | +| `step1_lastName` | `step-1_last-name` | | `string` | `"Last name"` | +| `step1_personalInformation` | `step-1_personal-information` | | `string` | `"Personal Information"` | +| `step1_phoneNumber` | `step-1_phone-number` | | `string` | `"Phone number"` | +| `step1_postalCode` | `step-1_postal-code` | | `string` | `"Postal code"` | +| `step1_province` | `step-1_province` | | `string` | `"Province"` | +| `step1_region` | `step-1_region` | | `string` | `"Region"` | +| `step1_searchForCurrencyText` | `step-1_search-for-currency-text` | Placeholder text displayed in the currency search dropdown | `string` | `"Search for currency.."` | +| `step1_state` | `step-1_state` | | `string` | `"State"` | +| `step1_termsAndConditionsLabel` | `step-1_terms-and-conditions-label` | The link text that appears in the terms and conditions checkbox | `string` | `"terms and conditions"` | +| `step1_termsAndConditionsLink` | `step-1_terms-and-conditions-link` | The link that appears in the terms and conditions checkbox | `string` | `"https://terms.advocate.impact.com/PayoutTermsAndConditions.html"` | +| `step2_cannotChangeInfoAlert` | `step-2_cannot-change-info-alert` | Communicate that after this step, only Support can change personal and indirect tax information. | `string` | `"Changes to your personal and indirect tax information can only be made through our {supportLink} after you complete this step. Make sure these are correct before continuing."` | +| `step2_indirectTax` | `step-2_indirect-tax` | | `string` | `"Indirect Tax"` | +| `step2_indirectTaxDescription` | `step-2_indirect-tax-description` | Displayed under the title of this step. | `string` | `"Indirect taxes (e.g. VAT, HST, GST) are transaction based taxes often applied to goods and services. Service providers are typically required to register with their tax authority and collect these taxes on behalf governments."` | +| `step2_indirectTaxDetails` | `step-2_indirect-tax-details` | Displayed with indirect tax registration options. | `string` | `"Indirect tax details"` | +| `step2_indirectTaxNumber` | `step-2_indirect-tax-number` | | `string` | `"{taxType, select, GST {GST number} HST {HST number} VAT {VAT number} CT {CT number} SST {SST number} GENERAL {Indirect tax number}}"` | +| `step2_indirectTaxNumberError` | `step-2_indirect-tax-number-error` | | `string` | `"{taxType, select, GST {GST number} HST {HST number} VAT {VAT number} CT {CT number} SST {SST number} GENERAL {Indirect tax number}} is required"` | +| `step2_isRegisteredQST` | `step-2_is-registered-q-s-t` | Displayed to participants registered for indirect tax in Quebec, Canada. | `string` | `"I am registered for QST Tax"` | +| `step2_isRegisteredSubRegionIncomeTax` | `step-2_is-registered-sub-region-income-tax` | Displayed to participants registered for indirect tax in Spain. | `string` | `"I am an individual registered for Income Tax purposes in Spain, and withholding tax will apply to any payments made to me."` | +| `step2_notRegistered` | `step-2_not-registered` | | `string` | `"Not registered for indirect tax"` | +| `step2_notRegisteredSubtext` | `step-2_not-registered-subtext` | Participants based in the US are considered not registered. | `string` | `"If you’ve never set up indirect tax with your tax authority, then you’re likely not considered registered."` | +| `step2_otherRegion` | `step-2_other-region` | | `string` | `"Registered for indirect tax"` | +| `step2_otherRegionSubtext` | `step-2_other-region-subtext` | Selecting this option will display fields to enter indirect tax details. | `string` | `"If you’ve registered with your tax authority, add your information to stay tax compliant."` | +| `step2_province` | `step-2_province` | | `string` | `"Province"` | +| `step2_qstNumber` | `step-2_qst-number` | Displayed to participants registered for QST. | `string` | `"QST number"` | +| `step2_selectedRegion` | `step-2_selected-region` | | `string` | `"Country / region of indirect tax"` | +| `step2_subRegion` | `step-2_sub-region` | Displayed to participants registered in Spain. | `string` | `"Sub-region"` | +| `step2_subRegionTaxNumberLabel` | `step-2_sub-region-tax-number-label` | | `string` | `"Income Tax Number"` | +| `step3_businessEntity` | `step-3_business-entity` | An option for the participant type field. Used to determine which W-8 form is required. | `string` | `"I represent a business"` | +| `step3_docusignError` | `step-3_docusign-error` | This appears inside the Docusign frame. | `string` | `"There was a problem displaying this form. Please refresh the page. If this problem continues, contact our {supportLink}."` | +| `step3_docusignExpired` | `step-3_docusign-expired` | This appears inside the Docusign frame. | `string` | `"For your security and privacy, we automatically end your session after 20 minutes of inactivity. Please refresh and re-enter your tax information to continue."` | +| `step3_docusignSessionWarning` | `step-3_docusign-session-warning` | Remind participants their session will time out after 20 minutes of inactivity. | `string` | `"For your security, we automatically end your session when you have not interacted with the form after 20 minutes."` | +| `step3_exitButton` | `step-3_exit-button` | | `string` | `"Exit"` | +| `step3_individualParticipant` | `step-3_individual-participant` | An option for the participant type field. Used to determine which W-8 form is required. | `string` | `"I am an individual participant"` | +| `step3_modalButtonText` | `step-3_modal-button-text` | | `string` | `"I understand"` | +| `step3_modalDescription` | `step-3_modal-description` | | `string` | `"Remember the name you enter in your tax form. It must exactly match the bank account holder name configured in the next step. {br}{br}Otherwise you will have to resubmit your form again and there will be delays receiving your payout."` | +| `step3_modalTitle` | `step-3_modal-title` | | `string` | `"Important Note"` | +| `step3_participantType` | `step-3_participant-type` | | `string` | `"Participant type"` | +| `step3_refreshButton` | `step-3_refresh-button` | | `string` | `"Refresh Page"` | +| `step3_taxForm` | `step-3_tax-form` | | `string` | `"Tax form"` | +| `step3_taxFormDescription` | `step-3_tax-form-description` | Displayed at the top of the page to participants based in the US. | `string` | `"Participants based in the US need to submit a {documentType} form."` | +| `step3_taxFormDescriptionBusinessEntity` | `step-3_tax-form-description-business-entity` | Displayed at the top of the page to participants representing a business. | `string` | `"Participants residing outside of the US working with a US Brand need to submit a {documentType} form."` | +| `step3_taxFormDescriptionIndividualParticipant` | `step-3_tax-form-description-individual-participant` | Displayed at the top of the page to individuals joining a US program who reside outside the country. | `string` | `"Participants residing outside of the US, joining the referral program of a US-based company, need to submit a {documentType} form."` | +| `step3_taxFormLabel` | `step-3_tax-form-label` | Display the type of tax form that the participant must submit. | `string` | `"{documentType} Tax Form"` | +| `step4_agencyCodeLabel` | `step-4_agency-code-label` | | `string` | `"Agency code"` | +| `step4_bankAccountNumberLabel` | `step-4_bank-account-number-label` | | `string` | `"Bank account number"` | +| `step4_bankAccountTypeLabel` | `step-4_bank-account-type-label` | | `string` | `"Bank account type"` | +| `step4_bankAddressLabel` | `step-4_bank-address-label` | | `string` | `"Bank address"` | +| `step4_bankCityLabel` | `step-4_bank-city-label` | | `string` | `"Bank city"` | +| `step4_bankLocationLabel` | `step-4_bank-location-label` | | `string` | `"Bank country location"` | +| `step4_bankNameLabel` | `step-4_bank-name-label` | | `string` | `"Bank name"` | +| `step4_bankPostalCodeLabel` | `step-4_bank-postal-code-label` | | `string` | `"Bank postal code"` | +| `step4_bankStateLabel` | `step-4_bank-state-label` | | `string` | `"Bank Province / State"` | +| `step4_beneficiaryAccountNameDescription` | `step-4_beneficiary-account-name-description` | | `string` | `"The beneficiary name of your bank account. Ensure this matches the name on your tax form."` | +| `step4_beneficiaryAccountNameLabel` | `step-4_beneficiary-account-name-label` | | `string` | `"Account holder name"` | +| `step4_branchCodeLabel` | `step-4_branch-code-label` | | `string` | `"Branch code"` | +| `step4_businessSelectItemLabel` | `step-4_business-select-item-label` | One of three options listed for the classification field | `string` | `"Business"` | +| `step4_checkingSelectItemLabel` | `step-4_checking-select-item-label` | | `string` | `"Checking"` | +| `step4_classificationCPFLabel` | `step-4_classification-c-p-f-label` | | `string` | `"Classification CPF"` | +| `step4_classificationEntityLabel` | `step-4_classification-entity-label` | | `string` | `"Classification entity"` | +| `step4_classificationLabel` | `step-4_classification-label` | Label text for the classification input field | `string` | `"Classification"` | +| `step4_directlyToBankAccount` | `step-4_directly-to-bank-account` | | `string` | `"Directly to my bank account"` | +| `step4_eftWithdrawalLabel` | `step-4_eft-withdrawal-label` | Default payment method to the participants’ bank account. | `string` | `"EFT Withdrawal (free)"` | +| `step4_foreignSelectItemLabel` | `step-4_foreign-select-item-label` | One of three options listed for the classification field | `string` | `"Foreign"` | +| `step4_fxWireProcessingFeeLabel` | `step-4_fx-wire-processing-fee-label` | | `string` | `"FX Wire (Processing Fee {currency}{defaultFxFee}.00)"` | +| `step4_ibanLabel` | `step-4_iban-label` | | `string` | `"IBAN"` | +| `step4_individualSelectItemLabel` | `step-4_individual-select-item-label` | One of three options listed for the classification field | `string` | `"Individual"` | +| `step4_modalButtonText` | `step-4_modal-button-text` | | `string` | `"I understand, update my information"` | +| `step4_modalDescription` | `step-4_modal-description` | | `string` | `"Updating payment information places your account and payouts on hold for up to 48 hours while we verify your change. Payments scheduled during the hold period are skipped."` | +| `step4_modalTitle` | `step-4_modal-title` | | `string` | `"Important Note"` | +| `step4_patronymicNameLabel` | `step-4_patronymic-name-label` | | `string` | `"Patronymic name"` | +| `step4_payPalInputLabel` | `step-4_pay-pal-input-label` | Displayed to participants who choose PayPal as their payout method | `string` | `"PayPal email"` | +| `step4_paymentDayFifteenthOfMonthLabelText` | `step-4_payment-day-fifteenth-of-month-label-text` | One of two payment day options | `string` | `"15th of the month"` | +| `step4_paymentDayFirstOfMonthLabelText` | `step-4_payment-day-first-of-month-label-text` | One of two payment day options | `string` | `"1st of the month"` | +| `step4_paymentDaySelectLabel` | `step-4_payment-day-select-label` | Let the participant choose what day of the month they’ll get paid | `string` | `"Payment Day"` | +| `step4_paymentMethod` | `step-4_payment-method` | | `string` | `"Payment method"` | +| `step4_paymentMethodSubtext` | `step-4_payment-method-subtext` | | `string` | `"Payouts will be sent from our referral program provider, impact.com."` | +| `step4_paymentSchedule` | `step-4_payment-schedule` | | `string` | `"Payment schedule"` | +| `step4_paymentScheduleBalanceThreshold` | `step-4_payment-schedule-balance-threshold` | | `string` | `"Pay me when my balance reaches a threshold"` | +| `step4_paymentScheduleFixedDay` | `step-4_payment-schedule-fixed-day` | | `string` | `"Pay me on a fixed day of the month"` | +| `step4_paymentThresholdSelectLabel` | `step-4_payment-threshold-select-label` | Participant use this field to select the balance at which they want to be paid | `string` | `"Payment threshold"` | +| `step4_routingCodeLabel` | `step-4_routing-code-label` | | `string` | `"{bankCountry, select, AU {BSB number} CA {Routing number} CZ {Bank code} HK {Clearing code} SG {Clearing code} US {ABA routing number} NZ {BSB number} ZA {Bank/Branch number} IN {IFSC} CNY {CNAPS} other {Routing code} }"` | +| `step4_savingsSelectItemLabel` | `step-4_savings-select-item-label` | Label text for the savings account type select item | `string` | `"Savings"` | +| `step4_swiftCodeLabel` | `step-4_swift-code-label` | | `string` | `"SWIFT code"` | +| `step4_taxAndPayouts` | `step-4_tax-and-payouts` | | `string` | `"Payouts"` | +| `step4_taxPayerIdLabel` | `step-4_tax-payer-id-label` | | `string` | `"Beneficiary INN"` | +| `step4_toPayPalAccount` | `step-4_to-pay-pal-account` | | `string` | `"PayPal (2% processing fee capped to {feeCap})"` | +| `step4_verifyEmailDescriptionText` | `step-4_verify-email-description-text` | | `string` | `"Verify your email to update your payment settings. Enter the code sent to {email} from our referral provider, impact.com."` | +| `step4_verifyEmailHeaderText` | `step-4_verify-email-header-text` | | `string` | `"Verify your email"` | +| `step4_voCodeLabel` | `step-4_vo-code-label` | | `string` | `"VO code"` | +| `supportLink` | `support-link` | Link text for contacting support team | `string` | `"support team"` | +| `taxAndPayoutsDescription` | `tax-and-payouts-description` | Displayed at the top of the page on all set up steps. | `string` | `"Submit your tax documents and add your banking information to receive your rewards."` | +| `termsAndConditions` | `terms-and-conditions` | Link text for Terms and Conditions | `string` | `"Terms and Conditions"` | ## Dependencies diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/sqm-tax-and-cash.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/sqm-tax-and-cash.tsx index 785612c682..4d4c3cdb84 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/sqm-tax-and-cash.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/sqm-tax-and-cash.tsx @@ -91,12 +91,6 @@ export class TaxAndCashMonolith { * @uiGroup Step 1 Properties */ @Prop() step1_currency: string = "Currency"; - /** - * @uiName Currency field help text - * @uiGroup Step 1 Properties - */ - @Prop() step1_currencyHelpText: string = - "Choose your preferred payout currency"; /** * Edit the property called terms and conditions text to change what's displayed for {termsAndConditionsLink}. * @uiName Terms and conditions checkbox @@ -1385,7 +1379,7 @@ export class TaxAndCashMonolith { {this.supportLink} ), - } + }, ) as string } /> @@ -1408,7 +1402,7 @@ function useDemoTaxAndCash(props: TaxAndCashMonolith) { key === "sqm-tax-and-cash" ? { ...prev, ...states[key] } : { ...prev, [`${key}_stateController`]: states[key] }, - {} + {}, ); return deepmerge( @@ -1417,6 +1411,6 @@ function useDemoTaxAndCash(props: TaxAndCashMonolith) { setStep, }, props.demoData || formatted || {}, - { arrayMerge: (_, a) => a } + { arrayMerge: (_, a) => a }, ); } diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/useTaxAndCash.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/useTaxAndCash.tsx index 2d3cd65de2..e545f65146 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/useTaxAndCash.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-tax-and-cash/useTaxAndCash.tsx @@ -45,6 +45,9 @@ function getCurrentStep(user: UserQuery["user"]) { brandedSignup, payoutsAccount, } = user.impactConnection.publisher; + if (user.impactConnection.connectionStatus === "STARTED") { + return "/1"; + } // If they do have a required document, look at current document if (requiredTaxDocumentType && !currentTaxDocument) { @@ -97,7 +100,7 @@ export function useTaxAndCash() { { namespace: CURRENCIES_NAMESPACE, initialValue: [], - } + }, ); const [_countriesContext, _setCountriesContext] = useParentState< @@ -158,7 +161,7 @@ export function useTaxAndCash() { financeNetworkData?.impactFinanceNetworkSettings?.data?.reduce( (agg, settings) => { const currency = currenciesData?.currencies?.data?.find( - (currency) => currency.currencyCode === settings.currency + (currency) => currency.currencyCode === settings.currency, ); // Currency not in supported list if (!currency) return agg; @@ -176,7 +179,7 @@ export function useTaxAndCash() { return [...agg, currency]; }, - [] + [], ); return allValidCurrencies; }, [financeNetworkData, countryCode]); @@ -194,9 +197,9 @@ export function useTaxAndCash() { new Set( paymentOptions ?.map((option) => option.countryCode) - .filter((value) => value) + .filter((value) => value), ), - [paymentOptions] + [paymentOptions], ); const _topCountries = ["CA", "GB", "US"]; @@ -205,7 +208,7 @@ export function useTaxAndCash() { () => Array.from(availableCountries) .map((countryCode) => - getCountryObj({ countryCode, locale: intlLocale }) + getCountryObj({ countryCode, locale: intlLocale }), ) .sort(sortByName) .reduce((prev, countryObj) => { @@ -213,7 +216,7 @@ export function useTaxAndCash() { return [countryObj, ...prev]; return [...prev, countryObj]; }, []), - [availableCountries] + [availableCountries], ); useEffect(() => { diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/UserInfoFormView.stories.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/UserInfoFormView.stories.tsx index 67fcb15ea2..467e7bb825 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/UserInfoFormView.stories.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/UserInfoFormView.stories.tsx @@ -79,7 +79,6 @@ const defaultText = { region: "Region", postalCode: "Postal Code", currency: "Currency", - currencyHelpText: "Select your preferred currency for payouts", allowBankingCollection: "I agree to the {termsAndConditionsLink}", personalInformation: "Personal Information", continueButton: "Continue", diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/readme.md b/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/readme.md index c9c8b69af4..48e355e998 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/readme.md +++ b/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/readme.md @@ -15,7 +15,6 @@ | `continueButton` | `continue-button` | | `string` | `"Continue"` | | `country` | `country` | | `string` | `"Country"` | | `currency` | `currency` | | `string` | `"Currency"` | -| `currencyHelpText` | `currency-help-text` | | `string` | `"Choose your preferred payout currency"` | | `demoData` | -- | | `{ states?: { step: string; hideState: boolean; hideSteps: boolean; disabled: boolean; loadingError: boolean; loading: boolean; isPartner: boolean; isUser: boolean; formState: { errors: {}; firstName: string; lastName: string; email: string; phoneNumberCountryCode: string; phoneNumber: string; countryCode: string; currency: string; address: string; city: string; state: string; postalCode: string; }; }; refs?: { formRef: Ref; currencyRef: Ref; phoneCountryRef: Ref; }; data?: { currencies: { displayName: string; currencyCode: string; }[]; countries: TaxCountry[]; phoneCountries: TaxCountry[]; allCurrencies: { displayName: string; currencyCode: string; }[]; allCountries: TaxCountry[]; regionLabelEnum: "STATE" \| "PROVINCE" \| "REGION"; regions: { label: string; value: string; }[]; partnerData: ImpactPublisher; userData: ImpactUser; }; setStep?: (value: string) => void; onSubmit?: (event: any) => Promise; }` | `undefined` | | `email` | `email` | | `string` | `"Email"` | | `fieldInvalidError` | `field-invalid-error` | Displayed under a field when it has an invalid entry. | `string` | `"{fieldName} is invalid"` | diff --git a/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/sqm-user-info-form-view.tsx b/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/sqm-user-info-form-view.tsx index 07897c630f..a5618bff0a 100644 --- a/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/sqm-user-info-form-view.tsx +++ b/packages/mint-components/src/components/tax-and-cash/sqm-user-info-form/sqm-user-info-form-view.tsx @@ -93,7 +93,6 @@ export interface UserInfoFormViewProps { region: string; postalCode: string; currency: string; - currencyHelpText: string; allowBankingCollection: string; personalInformation: string; continueButton: string; @@ -413,7 +412,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { {text.termsAndConditionsLabel} ), - } + }, ); let regionLabel = undefined; @@ -431,7 +430,14 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { regionLabel = text.state; } + // when creating an impact connection without sending phoneNumber data, the impactAPI defaults the value to "0000000" and the phoneNumberCountryCode to "DZ" function isDisabledPartnerInput(field: string) { + if ( + data.partnerData?.phoneNumber === "0000000" && + (field === "phoneNumber" || field === "phoneNumberCountryCode") + ) { + return false; + } return states.isPartner && !!data.partnerData?.[field]; } @@ -469,7 +475,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { {text.supportLink} ), - } + }, )}

@@ -489,7 +495,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { id: "formStep", defaultMessage: text.formStep, }, - { step: states.step, count: FORM_STEPS } + { step: states.step, count: FORM_STEPS }, )}

)} @@ -518,31 +524,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { {text.supportLink} ), - } - )} -

- - )} - - {(states.isPartner || states.isUser) && ( - -

{text.isPartnerAlertHeader}

-

- {intl.formatMessage( - { - id: "isPartnerAlertDescription", - defaultMessage: text.isPartnerAlertDescription, }, - { - supportLink: ( - - {text.supportLink} - - ), - } )}

@@ -561,7 +543,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { class: classes.ErrorInput, helpText: formatErrorMessage( text.firstName, - formState.errors.firstName + formState.errors.firstName, ), } : {})} @@ -579,7 +561,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { class: classes.ErrorInput, helpText: formatErrorMessage( text.lastName, - formState.errors.lastName + formState.errors.lastName, ), } : {})} @@ -611,7 +593,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { class: classes.ErrorInput, helpText: formatErrorMessage( text.country, - formState.errors.countryCode + formState.errors.countryCode, ), } : {})} @@ -710,7 +692,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { validateBillingField(/[a-zA-Z]+/, value) && formatErrorMessage( text.phoneNumber, - text.error.fieldInvalidError + text.error.fieldInvalidError, ); }} disabled={ @@ -721,7 +703,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { class: classes.ErrorInput, helpText: formatErrorMessage( text.phoneNumber, - formState.errors.phoneNumber + formState.errors.phoneNumber, ), } : {})} @@ -740,7 +722,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { !validateBillingField(/^[\x20-\xFF]+$/, value) && formatErrorMessage( text.address, - text.error.invalidCharacterError + text.error.invalidCharacterError, ) } disabled={ @@ -751,7 +733,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { class: classes.ErrorInput, helpText: formatErrorMessage( text.address, - formState.errors.address + formState.errors.address, ), } : {})} @@ -768,7 +750,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { !validateBillingField(/^[\x20-\xFF]+$/, value) && formatErrorMessage( text.city, - text.error.invalidCharacterError + text.error.invalidCharacterError, ) } disabled={ @@ -779,7 +761,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { class: classes.ErrorInput, helpText: formatErrorMessage( text.city, - formState.errors.city + formState.errors.city, ), } : {})} @@ -800,7 +782,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { class: classes.ErrorInput, helpText: formatErrorMessage( text.state, - formState.errors.state + formState.errors.state, ), } : {})} @@ -825,7 +807,7 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { class: classes.ErrorInput, helpText: formatErrorMessage( text.postalCode, - formState.errors.postalCode + formState.errors.postalCode, ), } : {})} @@ -839,13 +821,12 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { menu value={formState.currency} disabled={states.disabled || isDisabledPartnerInput("currency")} - helpText={text.currencyHelpText} {...(formState.errors?.currency ? { class: classes.ErrorInput, helpText: formatErrorMessage( text.currency, - formState.errors.currency + formState.errors.currency, ), } : {})} @@ -877,30 +858,6 @@ export const UserInfoFormView = (props: UserInfoFormViewProps) => { ))} - -
- { - e.target.value = e.target.checked; - }} - disabled={states.disabled} - required - value={formState.allowBankingCollection} - id="allowBankingCollection" - name="/allowBankingCollection" - > - {bankingCollectionText} - - {formState.errors?.allowBankingCollection && ( -

- {formatErrorMessage( - text.termsAndConditionsLabel, - formState.errors.allowBankingCollection - )} -

- )} -
And is input type And they see a "Continue" button + Examples: | label | inputType | | First name | text | @@ -114,7 +115,6 @@ Feature: Tax Form Step One | CAN | USD, AUD, EUR, GBP, CAN | | IND | USD, AUD, EUR, GBP, INR | - @minutia Scenario: Currency select is searchable When they press the Currency select @@ -201,19 +201,20 @@ Feature: Tax Form Step One {fieldName} contains invalid characters. """ # Note: SPACE and NUL mean the characters. Both are for documentation purposes. + Examples: | fieldName | string | may | | Address | SPACE | will not | | Address | abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ | will not | - | Address | 0123456789 | will not | - | Address | !"#$%&'()*+'-,/:;<=>?@[\]^_`~ | will not | + | Address | 0123456789 | will not | + | Address | !"#$%&'()*+'-,/:;<=>?@[\\]^_`~ | will not | | Address | æùíöêø | will not | | Address | ぁ ㍿ ・ | will | | Address | NUL | will | | City | SPACE | will not | | City | abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ | will not | - | City | 0123456789 | will not | - | City | !"#$%&'()*+'-,/:;<=>?@[\]^_`~ | will not | + | City | 0123456789 | will not | + | City | !"#$%&'()*+'-,/:;<=>?@[\\]^_`~ | will not | | City | æùíöêø | will not | | City | ぁ ㍿ ・ | will | | City | NUL | will | @@ -227,11 +228,12 @@ Feature: Tax Form Step One """ Phone number is invalid. """ + Examples: | string | may | | abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ | will | - | 0123456789 | will not | - | !"#$%&'()*+'-,/:;<=>?@[\]^_`~ | will not | + | 0123456789 | will not | + | !"#$%&'()*+'-,/:;<=>?@[\\]^_`~ | will not | @minutia Scenario Outline: "State" field changes based on country selected @@ -239,6 +241,7 @@ Feature: Tax Form Step One When is selected via the dropdown Then the "State" select menu updates to the valid states of that country And the "State" field's label changes to