diff --git a/packages/scripts/dist/interfaces/options.d.ts b/packages/scripts/dist/interfaces/options.d.ts index d3c93525..b479209e 100644 --- a/packages/scripts/dist/interfaces/options.d.ts +++ b/packages/scripts/dist/interfaces/options.d.ts @@ -15,6 +15,7 @@ export interface Options { MaxAmount?: number; MinAmountMessage?: string; MaxAmountMessage?: string; + UseAmountValidatorFromEN?: boolean; SkipToMainContentLink?: boolean; SrcDefer?: boolean; NeverBounceAPI?: string | null; diff --git a/packages/scripts/dist/interfaces/options.js b/packages/scripts/dist/interfaces/options.js index 93f7dc6d..12ac46a9 100644 --- a/packages/scripts/dist/interfaces/options.js +++ b/packages/scripts/dist/interfaces/options.js @@ -14,6 +14,7 @@ export const OptionsDefaults = { MaxAmount: 100000, MinAmountMessage: "Amount must be at least $1", MaxAmountMessage: "Amount must be less than $100,000", + UseAmountValidatorFromEN: false, SkipToMainContentLink: true, SrcDefer: true, NeverBounceAPI: null, diff --git a/packages/scripts/dist/min-max-amount.d.ts b/packages/scripts/dist/min-max-amount.d.ts index f05bd2c9..7fd35173 100644 --- a/packages/scripts/dist/min-max-amount.d.ts +++ b/packages/scripts/dist/min-max-amount.d.ts @@ -1,13 +1,16 @@ export declare class MinMaxAmount { private _form; private _amount; + private _frequency; private minAmount; private maxAmount; private minAmountMessage; private maxAmountMessage; + private enAmountValidator; private logger; constructor(); shouldRun(): boolean; enOnValidate(): void; liveValidate(): void; + private setValidationConfigFromEN; } diff --git a/packages/scripts/dist/min-max-amount.js b/packages/scripts/dist/min-max-amount.js index 4953f812..e5962226 100644 --- a/packages/scripts/dist/min-max-amount.js +++ b/packages/scripts/dist/min-max-amount.js @@ -1,19 +1,22 @@ // This script adds an erros message to the page if the amount is greater than the max amount or less than the min amount. -import { DonationAmount, EnForm, ENGrid, EngridLogger } from "."; +import { DonationAmount, DonationFrequency, EnForm, ENGrid, EngridLogger, } from "."; export class MinMaxAmount { constructor() { var _a, _b; this._form = EnForm.getInstance(); this._amount = DonationAmount.getInstance(); + this._frequency = DonationFrequency.getInstance(); this.minAmount = (_a = ENGrid.getOption("MinAmount")) !== null && _a !== void 0 ? _a : 1; this.maxAmount = (_b = ENGrid.getOption("MaxAmount")) !== null && _b !== void 0 ? _b : 100000; this.minAmountMessage = ENGrid.getOption("MinAmountMessage"); this.maxAmountMessage = ENGrid.getOption("MaxAmountMessage"); + this.enAmountValidator = null; this.logger = new EngridLogger("MinMaxAmount", "white", "purple", "🔢"); if (!this.shouldRun()) { // If we're not on a Donation Page, get out return; } + this.setValidationConfigFromEN(); this._amount.onAmountChange.subscribe((s) => window.setTimeout(this.liveValidate.bind(this), 1000) // Wait 1 second for the amount to be updated ); this._form.onValidate.subscribe(this.enOnValidate.bind(this)); @@ -68,4 +71,56 @@ export class MinMaxAmount { ENGrid.removeError(".en__field--withOther"); } } + setValidationConfigFromEN() { + if (!ENGrid.getOption("UseAmountValidatorFromEN") || + !window.EngagingNetworks.validators) { + this.logger.log("Not setting validation config from EN."); + return; + } + // Find the amount validator for the donation amount field + // It should be of type "AMNT" or "FAMNT" and have + // a componentId that matches the donation amount field. + this.enAmountValidator = window.EngagingNetworks.validators.find((validator) => { + var _a; + return ((validator.type === "FAMNT" || validator.type === "AMNT") && + ((_a = document + .querySelector(".en__field--" + validator.componentId)) === null || _a === void 0 ? void 0 : _a.classList.contains("en__field--donationAmt"))); + }); + if (!this.enAmountValidator || !this.enAmountValidator.format) { + return; + } + this.logger.log(`Detected an amount validator for donation amount on the page:`, this.enAmountValidator); + // Static amount validator + if (this.enAmountValidator.type === "AMNT") { + this.minAmount = Number(this.enAmountValidator.format.split("~")[0]); + this.maxAmount = Number(this.enAmountValidator.format.split("~")[1]); + this.minAmountMessage = this.enAmountValidator.errorMessage; + this.maxAmountMessage = this.enAmountValidator.errorMessage; + this.logger.log(`Setting new values - Min Amount: ${this.minAmount}, Max Amount: ${this.maxAmount}, Error Message: ${this.minAmountMessage}`); + } + // Frequency-based amount validator + if (this.enAmountValidator.type === "FAMNT") { + this._frequency.onFrequencyChange.subscribe((freq) => { + if (!this.enAmountValidator || !this.enAmountValidator.format) + return; + // In the validator, "onetime" is written as "SINGLE" + // Validator format for FAMNT is like SINGLE:10~100000|MONTHLY:5~100000|QUARTERLY:25~100000|ANNUAL:25~100000 + const frequency = freq === "onetime" ? "SINGLE" : freq.toUpperCase(); + const validationRange = this.enAmountValidator.format + .split("|") + .find((range) => range.startsWith(frequency)); + if (!validationRange) { + this.logger.log(`No validation range found for frequency: ${frequency}`); + return; + } + const amounts = validationRange.split(":")[1].split("~"); + this.minAmount = Number(amounts[0]); + this.maxAmount = Number(amounts[1]); + this.minAmountMessage = this.enAmountValidator.errorMessage; + this.maxAmountMessage = this.enAmountValidator.errorMessage; + this.logger.log(`Frequency changed to ${frequency}, updating min and max amounts`, validationRange); + this.logger.log(`Setting new values - Min Amount: ${this.minAmount}, Max Amount: ${this.maxAmount}, Error Message: ${this.minAmountMessage}`); + }); + } + } } diff --git a/packages/scripts/src/interfaces/options.ts b/packages/scripts/src/interfaces/options.ts index e37639bc..dd67912c 100644 --- a/packages/scripts/src/interfaces/options.ts +++ b/packages/scripts/src/interfaces/options.ts @@ -15,6 +15,7 @@ export interface Options { MaxAmount?: number; MinAmountMessage?: string; MaxAmountMessage?: string; + UseAmountValidatorFromEN?: boolean; SkipToMainContentLink?: boolean; SrcDefer?: boolean; NeverBounceAPI?: string | null; @@ -178,6 +179,7 @@ export const OptionsDefaults: Options = { MaxAmount: 100000, MinAmountMessage: "Amount must be at least $1", MaxAmountMessage: "Amount must be less than $100,000", + UseAmountValidatorFromEN: false, SkipToMainContentLink: true, SrcDefer: true, NeverBounceAPI: null, diff --git a/packages/scripts/src/min-max-amount.ts b/packages/scripts/src/min-max-amount.ts index 36aee06a..aa0b888c 100644 --- a/packages/scripts/src/min-max-amount.ts +++ b/packages/scripts/src/min-max-amount.ts @@ -1,12 +1,28 @@ // This script adds an erros message to the page if the amount is greater than the max amount or less than the min amount. -import { DonationAmount, EnForm, ENGrid, EngridLogger } from "."; +import { + DonationAmount, + DonationFrequency, + EnForm, + ENGrid, + EngridLogger, +} from "."; + +type Validator = { + componentId: number; + type: string; + format?: string; + errorMessage: string; +}; + export class MinMaxAmount { private _form: EnForm = EnForm.getInstance(); private _amount: DonationAmount = DonationAmount.getInstance(); + private _frequency: DonationFrequency = DonationFrequency.getInstance(); private minAmount: number = ENGrid.getOption("MinAmount") ?? 1; private maxAmount: number = ENGrid.getOption("MaxAmount") ?? 100000; private minAmountMessage = ENGrid.getOption("MinAmountMessage"); private maxAmountMessage = ENGrid.getOption("MaxAmountMessage"); + private enAmountValidator: Validator | null = null; private logger: EngridLogger = new EngridLogger( "MinMaxAmount", "white", @@ -18,6 +34,7 @@ export class MinMaxAmount { // If we're not on a Donation Page, get out return; } + this.setValidationConfigFromEN(); this._amount.onAmountChange.subscribe( (s) => window.setTimeout(this.liveValidate.bind(this), 1000) // Wait 1 second for the amount to be updated ); @@ -81,4 +98,83 @@ export class MinMaxAmount { ENGrid.removeError(".en__field--withOther"); } } + + private setValidationConfigFromEN() { + if ( + !ENGrid.getOption("UseAmountValidatorFromEN") || + !window.EngagingNetworks.validators + ) { + this.logger.log("Not setting validation config from EN."); + return; + } + + // Find the amount validator for the donation amount field + // It should be of type "AMNT" or "FAMNT" and have + // a componentId that matches the donation amount field. + this.enAmountValidator = window.EngagingNetworks.validators.find( + (validator: Validator) => { + return ( + (validator.type === "FAMNT" || validator.type === "AMNT") && + document + .querySelector(".en__field--" + validator.componentId) + ?.classList.contains("en__field--donationAmt") + ); + } + ); + + if (!this.enAmountValidator || !this.enAmountValidator.format) { + return; + } + + this.logger.log( + `Detected an amount validator for donation amount on the page:`, + this.enAmountValidator + ); + + // Static amount validator + if (this.enAmountValidator.type === "AMNT") { + this.minAmount = Number(this.enAmountValidator.format.split("~")[0]); + this.maxAmount = Number(this.enAmountValidator.format.split("~")[1]); + this.minAmountMessage = this.enAmountValidator.errorMessage; + this.maxAmountMessage = this.enAmountValidator.errorMessage; + this.logger.log( + `Setting new values - Min Amount: ${this.minAmount}, Max Amount: ${this.maxAmount}, Error Message: ${this.minAmountMessage}` + ); + } + + // Frequency-based amount validator + if (this.enAmountValidator.type === "FAMNT") { + this._frequency.onFrequencyChange.subscribe((freq) => { + if (!this.enAmountValidator || !this.enAmountValidator.format) return; + // In the validator, "onetime" is written as "SINGLE" + // Validator format for FAMNT is like SINGLE:10~100000|MONTHLY:5~100000|QUARTERLY:25~100000|ANNUAL:25~100000 + const frequency = freq === "onetime" ? "SINGLE" : freq.toUpperCase(); + const validationRange = this.enAmountValidator.format + .split("|") + .find((range) => range.startsWith(frequency)); + + if (!validationRange) { + this.logger.log( + `No validation range found for frequency: ${frequency}` + ); + return; + } + + const amounts = validationRange.split(":")[1].split("~"); + + this.minAmount = Number(amounts[0]); + this.maxAmount = Number(amounts[1]); + this.minAmountMessage = this.enAmountValidator.errorMessage; + this.maxAmountMessage = this.enAmountValidator.errorMessage; + + this.logger.log( + `Frequency changed to ${frequency}, updating min and max amounts`, + validationRange + ); + this.logger.log( + `Setting new values - Min Amount: ${this.minAmount}, Max Amount: ${this.maxAmount}, Error Message: ${this.minAmountMessage}` + ); + }); + } + } }