import { Repeater } from "./Repeater"; if (!window.SequraFE) { window.SequraFE = {}; } (function () { /** * @typedef WidgetLabels * @property {string|null} message * @property {string|null} messageBelowLimit */ /** * @typedef WidgetLocation * @property {string|null} selForTarget * @property {string|null} product * @property {string|null} country * @property {string|null} campaign */ /** * @typedef MiniWidget * @property {string|null} selForPrice * @property {string|null} selForLocation * @property {string} message * @property {string|null} messageBelowLimit * @property {string|null} product * @property {string|null} country * @property {string|null} campaign */ /** * @typedef CountryPaymentMethod * @property {string|null} countryCode * @property {string|null} product * @property {string|null} campaign * @property {string|null} title */ /** * @typedef WidgetSettings * @property {boolean} useWidgets * @property {string|null} assetsKey * @property {boolean} displayWidgetOnProductPage * @property {boolean} showInstallmentAmountInProductListing * @property {boolean} showInstallmentAmountInCartPage * @property {WidgetLabels|null} widgetLabels * @property {string|null} widgetStyles * @property {string|null} selForPrice * @property {string|null} selForAltPrice * @property {string|null} selForAltPriceTrigger * @property {string|null} selForDefaultLocation * @property {WidgetLocation[]} customLocations * * @property {string|null} selForCartPrice * @property {string|null} selForCartLocation * * @property {string|null} selForListingPrice * @property {string|null} selForListingLocation */ /** * Handles widgets settings form logic. * * @param {{ * widgetSettings: WidgetSettings, * connectionSettings: ConnectionSettings, * countrySettings: CountrySettings[], * paymentMethods: PaymentMethod[], * allPaymentMethods: CountryPaymentMethod[], * }} data * @param {{ * saveWidgetSettingsUrl: string, * getPaymentMethodsUrl: string, * getAllPaymentMethodsUrl: string, * page: string, * appState: string, * }} configuration * @constructor */ function WidgetSettingsForm(data, configuration) { /** @type AjaxServiceType */ const api = SequraFE.ajaxService; let allPaymentMethods = data.allPaymentMethods; const { elementGenerator: generator, validationService: validator, utilities } = SequraFE; /** @type WidgetSettings */ let activeSettings; /** @type WidgetSettings */ let changedSettings; /** @type string[] */ let paymentMethodIds; /** @type boolean */ let isAssetKeyValid = false; /** @type WidgetSettings */ const defaultFormData = { useWidgets: false, assetsKey: '', displayWidgetOnProductPage: false, widgetLabels: { message: SequraFE.miniWidgetLabels.messages['ES'], messageBelowLimit: SequraFE.miniWidgetLabels.messagesBelowLimit['ES'] }, widgetStyles: '{"alignment":"center","amount-font-bold":"true","amount-font-color":"#1C1C1C","amount-font-size":"15","background-color":"white","border-color":"#B1AEBA","border-radius":"","class":"","font-color":"#1C1C1C","link-font-color":"#1C1C1C","link-underline":"true","no-costs-claim":"","size":"M","starting-text":"only","type":"banner"}', showInstallmentAmountInProductListing: false, showInstallmentAmountInCartPage: false, selForPrice: '.summary .price>.amount,.summary .price ins .amount', selForAltPrice: '.woocommerce-variation-price .price>.amount,.woocommerce-variation-price .price ins .amount', selForAltPriceTrigger: '.variations', selForDefaultLocation: '.summary>.price', customLocations: [], selForCartPrice: '.order-total .amount', selForCartLocation: '.order-total', selForListingPrice: '.product .price>.amount:first-child,.product .price ins .amount', selForListingLocation: '.product .price', }; /** * Handles form rendering. */ this.render = () => { if (!activeSettings) { activeSettings = utilities.cloneObject(defaultFormData); for (let key in activeSettings) { activeSettings[key] = data?.widgetSettings?.[key] ?? defaultFormData[key]; } } paymentMethodIds = data.paymentMethods?.map((paymentMethod) => paymentMethod.product); isAssetKeyValid = activeSettings.assetsKey && activeSettings.assetsKey.length !== 0; changedSettings = utilities.cloneObject(activeSettings) initForm(); disableFooter(true); utilities.hideLoader(); } /** * Initializes the form structure. */ const initForm = () => { const pageContent = document.querySelector('.sq-content'); pageContent?.append( generator.createElement('div', 'sq-content-inner', '', null, [ generator.createElement('div', 'sqp-flash-message-wrapper'), generator.createPageHeading({ title: `widgets.title.${configuration.appState}`, text: 'widgets.description' }), generator.createRadioGroupField({ value: changedSettings.useWidgets, label: 'widgets.usePromotionalComponents.label', options: [ { label: 'widgets.usePromotionalComponents.options.yes', value: true }, { label: 'widgets.usePromotionalComponents.options.no', value: false } ], onChange: (value) => handleChange('useWidgets', value) }) ]) ); renderAssetsKeyField(); renderAdditionalSettings(); renderControls(); // maybeShowProductRelatedFields(); maybeShowRelatedFields('.sq-product-related-field', changedSettings.displayWidgetOnProductPage); maybeShowRelatedFields('.sq-cart-related-field', changedSettings.showInstallmentAmountInCartPage); maybeShowRelatedFields('.sq-listing-related-field', changedSettings.showInstallmentAmountInProductListing); } /** * Renders the assets key field. */ const renderAssetsKeyField = () => { const pageInnerContent = document.querySelector('.sq-content-inner'); if (changedSettings.useWidgets) { pageInnerContent?.append( generator.createTextField({ name: 'assets-key-input', value: changedSettings.assetsKey, className: 'sq-text-input', label: 'widgets.assetKey.label', description: 'widgets.assetKey.description', onChange: (value) => handleChange('assetsKey', value) }) ); if (changedSettings.assetsKey?.length !== 0) { validator.validateField( document.querySelector('[name="assets-key-input"]'), !isAssetKeyValid, 'validation.invalidField' ); } } } /** * Renders additional widget settings. */ const renderAdditionalSettings = () => { if (!changedSettings.useWidgets || !isAssetKeyValid) { return; } const pageInnerContent = document.querySelector('.sq-content-inner'); pageInnerContent?.append( generator.createTextArea( { className: 'sq-text-input sq-text-area', name: 'widget-styles', label: 'widgets.configurator.label', description: 'widgets.configurator.description.start', value: changedSettings.widgetStyles, onChange: (value) => handleChange('widgetStyles', value), rows: 10 } ), generator.createToggleField({ value: changedSettings.displayWidgetOnProductPage, label: 'widgets.displayOnProductPage.label', description: 'widgets.displayOnProductPage.description', onChange: (value) => handleChange('displayWidgetOnProductPage', value) }), // Product widget related fields generator.createTextField({ value: changedSettings.selForPrice, name: 'selForPrice', className: 'sq-text-input sq-product-related-field', label: 'widgets.selForPrice.label', description: 'widgets.selForPrice.description', onChange: (value) => handleChange('selForPrice', value) }), generator.createTextField({ value: changedSettings.selForAltPrice, name: 'selForAltPrice', className: 'sq-text-input sq-product-related-field', label: 'widgets.selForAltPrice.label', description: 'widgets.selForAltPrice.description', onChange: (value) => handleChange('selForAltPrice', value) }), generator.createTextField({ value: changedSettings.selForAltPriceTrigger, name: 'selForAltPriceTrigger', className: 'sq-text-input sq-product-related-field', label: 'widgets.selForAltPriceTrigger.label', description: 'widgets.selForAltPriceTrigger.description', onChange: (value) => handleChange('selForAltPriceTrigger', value) }), generator.createTextField({ value: changedSettings.selForDefaultLocation, name: 'selForDefaultLocation', className: 'sq-text-input sq-product-related-field', label: 'widgets.defaultLocationSel.label', description: 'widgets.defaultLocationSel.description', onChange: (value) => handleChange('selForDefaultLocation', value) }), generator.createElement('div', 'sq-field-wrapper sq-locations-container sq-product-related-field'), // End of product widget related fields generator.createToggleField({ value: changedSettings.showInstallmentAmountInCartPage, label: 'widgets.showInCartPage.label', description: 'widgets.showInCartPage.description', onChange: (value) => handleChange('showInstallmentAmountInCartPage', value) }), generator.createTextField({ value: changedSettings.selForCartPrice, name: 'selForCartPrice', className: 'sq-text-input sq-cart-related-field', label: 'widgets.selForCartPrice.label', description: 'widgets.selForCartPrice.description', onChange: (value) => handleChange('selForCartPrice', value) }), generator.createTextField({ value: changedSettings.selForCartLocation, name: 'selForCartLocation', className: 'sq-text-input sq-cart-related-field', label: 'widgets.cartDefaultLocationSel.label', description: 'widgets.cartDefaultLocationSel.description', onChange: (value) => handleChange('selForCartLocation', value) }), // End of cart widget related fields generator.createToggleField({ value: changedSettings.showInstallmentAmountInProductListing, label: 'widgets.showInProductListing.label', description: 'widgets.showInProductListing.description', onChange: (value) => handleChange('showInstallmentAmountInProductListing', value) }), generator.createTextField({ value: changedSettings.selForListingPrice, name: 'selForListingPrice', className: 'sq-text-input sq-listing-related-field', label: 'widgets.selForListingPrice.label', description: 'widgets.selForListingPrice.description', onChange: (value) => handleChange('selForListingPrice', value) }), generator.createTextField({ value: changedSettings.selForListingLocation, name: 'selForListingLocation', className: 'sq-text-input sq-listing-related-field', label: 'widgets.selForListingLocation.label', description: 'widgets.selForListingLocation.description', onChange: (value) => handleChange('selForListingLocation', value) }) ) document.querySelector('.sqp-textarea-field .sqp-field-subtitle').append( generator.createButtonLink({ className: 'sq-link-button', text: 'widgets.configurator.description.link', href: 'https://live.sequracdn.com/assets/static/simulator.html', openInNewTab: true }), generator.createElement('span', '', 'widgets.configurator.description.end'), ) // renderLabelsConfiguration(); renderLocations(); } const maybeShowRelatedFields = (relatedFieldClass, show) => { const selector = `.sq-field-wrapper:has(${relatedFieldClass}),.sq-field-wrapper${relatedFieldClass}`; const hiddenClass = 'sqs--hidden'; document.querySelectorAll(selector).forEach((el) => { if (show) { el.classList.remove(hiddenClass) } else { el.classList.add(hiddenClass) } }); } const renderLocations = () => { new Repeater({ containerSelector: '.sq-locations-container', data: changedSettings.customLocations, getHeaders: () => [ { title: SequraFE.translationService.translate('widgets.locations.headerTitle'), description: SequraFE.translationService.translate('widgets.locations.headerDescription') }, ], getRowContent: (data) => { let displayWidget = true; if (data && 'undefined' !== typeof data.displayWidget) { displayWidget = data.displayWidget; } return `