<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Preview Layout</title>
    <link media="all" rel="stylesheet" href="../../css/styles.css">
    <script>
        window.APP = {
            modules: {},
            addModule: function(name, config) {
                this.modules[name] = this.modules[name] || [];
                this.modules[name].push(config);
            },
            DEBUG: 1,
            CONFIG: {},
        };
    </script>

    <style>
        body {
            margin: 25px !important;
        }
    </style>
</head>

<body class="antialiased text-body-base font-roboto">
    <script>
        'use strict';
        (function(hyva, undefined) {
            function lifetimeToExpires(options, defaults) {
                const lifetime = options.lifetime || defaults.lifetime;
                if (lifetime) {
                    const date = new Date;
                    date.setTime(date.getTime() + lifetime * 1000);
                    return date;
                }
                return null;
            }

            function generateRandomString() {
                const allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
                    length = 16;
                let formKey = '',
                    charactersLength = allowedCharacters.length;
                for (let i = 0; i < length; i++) {
                    formKey += allowedCharacters[Math.round(Math.random() * (charactersLength - 1))]
                }
                return formKey;
            }
            const sessionCookieMarker = {
                noLifetime: true
            }
            const cookieTempStorage = {};
            const internalCookie = {
                get(name) {
                    const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
                    return v ? v[2] : null;
                },
                set(name, value, days, skipSetDomain) {
                    let expires,
                        path,
                        domain,
                        secure,
                        samesite;
                    const defaultCookieConfig = {
                        expires: null,
                        path: '/',
                        domain: null,
                        secure: false,
                        lifetime: null,
                        samesite: 'lax'
                    };
                    const cookieConfig = window.COOKIE_CONFIG || {};
                    expires = days && days !== sessionCookieMarker ?
                        lifetimeToExpires({
                            lifetime: 24 * 60 * 60 * days,
                            expires: null
                        }, defaultCookieConfig) :
                        lifetimeToExpires(window.COOKIE_CONFIG, defaultCookieConfig) || defaultCookieConfig.expires;
                    path = cookieConfig.path || defaultCookieConfig.path;
                    domain = !skipSetDomain && (cookieConfig.domain || defaultCookieConfig.domain);
                    secure = cookieConfig.secure || defaultCookieConfig.secure;
                    samesite = cookieConfig.samesite || defaultCookieConfig.samesite;
                    document.cookie = name + "=" + encodeURIComponent(value) +
                        (expires && days !== sessionCookieMarker ? '; expires=' + expires.toGMTString() : '') +
                        (path ? '; path=' + path : '') +
                        (domain ? '; domain=' + domain : '') +
                        (secure ? '; secure' : '') +
                        (samesite ? '; samesite=' + samesite : 'lax');
                },
                isWebsiteAllowedToSaveCookie() {
                    const allowedCookies = this.get('user_allowed_save_cookie');
                    if (allowedCookies) {
                        const allowedWebsites = JSON.parse(unescape(allowedCookies));
                        return allowedWebsites[CURRENT_WEBSITE_ID] === 1;
                    }
                    return false;
                },
                getGroupByCookieName(name) {
                    const cookieConsentConfig = window.cookie_consent_config || {};
                    let group = null;
                    for (let prop in cookieConsentConfig) {
                        if (!cookieConsentConfig.hasOwnProperty(prop)) continue;
                        if (cookieConsentConfig[prop].includes(name)) {
                            group = prop;
                            break;
                        }
                    }
                    return group;
                },
                isCookieAllowed(name) {
                    const cookieGroup = this.getGroupByCookieName(name);
                    return cookieGroup ?
                        window.cookie_consent_groups[cookieGroup] :
                        this.isWebsiteAllowedToSaveCookie();
                },
                saveTempStorageCookies() {
                    for (const [name, data] of Object.entries(cookieTempStorage)) {
                        if (this.isCookieAllowed(name)) {
                            this.set(name, data['value'], data['days'], data['skipSetDomain']);
                            delete cookieTempStorage[name];
                        }
                    }
                }
            };
            hyva.getCookie = (name) => {
                const cookieConfig = window.COOKIE_CONFIG || {};
                if (cookieConfig.cookie_restriction_enabled && !internalCookie.isCookieAllowed(name)) {
                    return cookieTempStorage[name] ? cookieTempStorage[name]['value'] : null;
                }
                return internalCookie.get(name);
            }
            hyva.setCookie = (name, value, days, skipSetDomain) => {
                const cookieConfig = window.COOKIE_CONFIG || {};
                if (cookieConfig.cookie_restriction_enabled && !internalCookie.isCookieAllowed(name)) {
                    cookieTempStorage[name] = {
                        value,
                        days,
                        skipSetDomain
                    };
                    return;
                }
                return internalCookie.set(name, value, days, skipSetDomain);
            }
            hyva.setSessionCookie = (name, value, skipSetDomain) => {
                return hyva.setCookie(name, value, sessionCookieMarker, skipSetDomain)
            }
            hyva.getBrowserStorage = () => {
                const browserStorage = window.localStorage || window.sessionStorage;
                if (!browserStorage) {
                    console.warn('Browser Storage is unavailable');
                    return false;
                }
                try {
                    browserStorage.setItem('storage_test', '1');
                    browserStorage.removeItem('storage_test');
                } catch (error) {
                    console.warn('Browser Storage is not accessible', error);
                    return false;
                }
                return browserStorage;
            }
            hyva.postForm = (postParams) => {
                const form = document.createElement("form");
                let data = postParams.data;
                if (!postParams.skipUenc && !data.uenc) {
                    data.uenc = btoa(window.location.href);
                }
                form.method = "POST";
                form.action = postParams.action;
                Object.keys(postParams.data).map(key => {
                    const field = document.createElement("input");
                    field.type = 'hidden'
                    field.value = postParams.data[key];
                    field.name = key;
                    form.appendChild(field);
                });
                const form_key = document.createElement("input");
                form_key.type = 'hidden';
                form_key.value = hyva.getFormKey();
                form_key.name = "form_key";
                form.appendChild(form_key);
                document.body.appendChild(form);
                form.submit();
            }
            hyva.getFormKey = function() {
                let formKey = hyva.getCookie('form_key');
                if (!formKey) {
                    formKey = generateRandomString();
                    hyva.setCookie('form_key', formKey);
                }
                return formKey;
            }
            hyva.formatPrice = (value, showSign, options = {}) => {
                const formatter = new Intl.NumberFormat(
                    'en-US',
                    Object.assign({
                        style: 'currency',
                        currency: 'EUR',
                        signDisplay: showSign ? 'always' : 'auto'
                    }, options)
                );
                return (typeof Intl.NumberFormat.prototype.formatToParts === 'function') ?
                    formatter.formatToParts(value).map(({
                        type,
                        value
                    }) => {
                        switch (type) {
                            case 'currency':
                                return '€' || value;
                            case 'minusSign':
                                return '- ';
                            case 'plusSign':
                                return '+ ';
                            default:
                                return value;
                        }
                    }).reduce((string, part) => string + part) :
                    formatter.format(value);
            }
            /**
             * Internal string replacement function implementation, see hyva.str() for usage details.
             *
             * @param string str Template string with optional placeholders
             * @param int nStart Offset for placeholders, 0 means %0 is replaced with args[0], 1 means %1 is replaced with args[0]
             * @param array ...args Positional replacement arguments. Rest arguments support isn't at 97% yet, so Array.from(arguments).slice() is used instead.
             */
            const formatStr = function(str, nStart) {
                const args = Array.from(arguments).slice(2);
                return str.replace(/(%+)([0-9]+)/g, (m, p, n) => {
                    const idx = parseInt(n) - nStart;
                    if (args[idx] === null || args[idx] === void 0) {
                        return m;
                    }
                    return p.length % 2 ?
                        p.slice(0, -1).replace('%%', '%') + args[idx] :
                        p.replace('%%', '%') + n;
                })
            }
            /**
             * Replace positional parameters like %1 in string with the rest argument in the matching position.
             * The first rest argument replaces %1, the second %2 and so on.
             *
             * Example: hyva.str('%3 %2 %1', 'a', 'b', 'c') => "c b a"
             *
             * To insert a literal % symbol followed by a number, duplicate the %, for example %%2 is returned as %2.
             */
            hyva.str = function(string) {
                const args = Array.from(arguments);
                args.splice(1, 0, 1);
                return formatStr.apply(undefined, args);
            }
            /**
             * Zero based version of hyva.str(): the first rest argument replaces %0, the second %1 and so on.
             *
             * Example: hyva.strf('%2 %1 %0', 'a', 'b', 'c') => "c b a"
             *
             * If in doubt whether to use hyva.str() or hyva.strf(), prefer hyva.str() because it is more similar to __()
             * and it might be possible to reuse existing phrase translations with placeholders.
             */
            hyva.strf = function() {
                const args = Array.from(arguments);
                args.splice(1, 0, 0);
                return formatStr.apply(undefined, args);
            }
            /**
             * Take a html string as `content` parameter and
             * extract an element from the DOM to replace in
             * the current page under the same selector,
             * defined by `targetSelector`
             */
            hyva.replaceDomElement = (targetSelector, content) => {
                // Parse the content and extract the DOM node using the `targetSelector`
                const parser = new DOMParser();
                const doc = parser.parseFromString(content, 'text/html');
                const contentNode = doc.querySelector(targetSelector);
                // Bail if content can't be found
                if (!contentNode) {
                    return;
                }
                hyva.activateScripts(contentNode)
                // Replace the old DOM node with the new content
                document.querySelector(targetSelector).replaceWith(contentNode);
                // Reload customerSectionData and display cookie-messages if present
                window.dispatchEvent(new CustomEvent("reload-customer-section-data"));
                hyva.initMessages();
            }
            hyva.activateScripts = (contentNode) => {
                // Extract all the script tags from the content.
                // Script tags won't execute when inserted into a dom-element directly,
                // therefore we need to inject them to the head of the document.
                const tmpScripts = contentNode.getElementsByTagName('script');
                if (tmpScripts.length > 0) {
                    // Push all script tags into an array
                    // (to prevent dom manipulation while iterating over dom nodes)
                    const scripts = [];
                    for (let i = 0; i < tmpScripts.length; i++) {
                        scripts.push(tmpScripts[i]);
                    }
                    // Iterate over all script tags and duplicate+inject each into the head
                    for (let i = 0; i < scripts.length; i++) {
                        let script = document.createElement('script');
                        script.innerHTML = scripts[i].innerHTML;
                        document.head.appendChild(script);
                        // Remove the original (non-executing) node from the content
                        scripts[i].parentNode.removeChild(scripts[i]);
                    }
                }
                return contentNode;
            }
            /**
             * Return base64 encoded current URL that can be used by Magento to redirect the visitor back to the current page.
             * The func hyva.getUenc handles additional encoding of +, / and = like \Magento\Framework\Url\Encoder::encode().
             */
            const replace = {
                ['+']: '-',
                ['/']: '_',
                ['=']: ','
            };
            hyva.getUenc = () => btoa(window.location.href).replace(/[+/=]/g, match => replace[match]);
            let currentTrap;
            const focusableElements = (rootElement) => {
                const selector = 'button, [href], input, select, textarea, details, [tabindex]:not([tabindex="-1"]';
                return Array.from(rootElement.querySelectorAll(selector))
                    .filter(el => {
                        return el.style.display !== 'none' &&
                            !el.disabled &&
                            el.tabIndex !== -1 &&
                            (el.offsetWidth || el.offsetHeight || el.getClientRects().length)
                    })
            }
            const focusTrap = (e) => {
                const isTabPressed = e.key === 'Tab' || e.keyCode === 9;
                if (!isTabPressed) return;
                const focusable = focusableElements(currentTrap)
                const firstFocusableElement = focusable[0]
                const lastFocusableElement = focusable[focusable.length - 1]
                e.shiftKey ?
                    document.activeElement === firstFocusableElement && (lastFocusableElement.focus(), e.preventDefault()) :
                    document.activeElement === lastFocusableElement && (firstFocusableElement.focus(), e.preventDefault())
            };
            hyva.releaseFocus = (rootElement) => {
                if (currentTrap && (!rootElement || rootElement === currentTrap)) {
                    currentTrap.removeEventListener('keydown', focusTrap)
                    currentTrap = null
                }
            }
            hyva.trapFocus = (rootElement) => {
                if (!rootElement) return;
                hyva.releaseFocus()
                currentTrap = rootElement
                rootElement.addEventListener('keydown', focusTrap)
                const firstElement = focusableElements(rootElement)[0]
                firstElement && firstElement.focus()
            }
            hyva.alpineInitialized = (fn) => window.addEventListener('alpine:initialized', fn, {
                once: true
            })
            window.addEventListener('alpine:initialized', () => {
                console.log('Alpine.js initialized')
            })
            window.addEventListener('user-allowed-save-cookie', () => internalCookie.saveTempStorageCookies())
        }(window.hyva = window.hyva || {}));
    </script>
    <script>
        'use strict';
        (function(hyva) {
            const formValidationRules = {
                required(value, options, field, context) {
                    const el = field.element.type === 'hidden' ? createTextInputFrom(field.element) : field.element,
                        msg = 'This\u0020is\u0020a\u0020required\u0020field.';
                    if (el.type === 'radio' || el.type === 'checkbox') {
                        return (value === undefined || value.length === 0) ? msg : true;
                    }
                    el.setAttribute('required', '');
                    el.checkValidity();
                    return el.validity.valueMissing ? msg : true;
                },
                maxlength(value, options, field, context) {
                    const n = Number(options)
                    if (value.length > n) {
                        return n === 1 ?
                            hyva.strf('Please\u0020enter\u0020no\u0020more\u0020than\u00201\u0020character.') :
                            hyva.strf('Please\u0020enter\u0020no\u0020more\u0020than\u0020\u00250\u0020characters.', options)
                    }
                    return true;
                },
                minlength(value, options, field, context) {
                    const n = Number(options)
                    if (value.length > 0 && value.length < n) {
                        return n === 1 ?
                            hyva.strf('Please\u0020enter\u0020at\u0020least\u00201\u0020character.') :
                            hyva.strf('Please\u0020enter\u0020at\u0020least\u0020\u00250\u0020characters.', options)
                    }
                    return true;
                },
                max(value, options, field, context) {
                    field.element.setAttribute('max', options);
                    field.element.checkValidity();
                    if (field.element.validity.rangeOverflow) {
                        return hyva.strf('Please\u0020enter\u0020a\u0020value\u0020less\u0020than\u0020or\u0020equal\u0020to\u0020\u0022\u00250\u0022.', options);
                    }
                    return true;
                },
                min(value, options, field, context) {
                    field.element.setAttribute('min', options);
                    field.element.checkValidity();
                    if (field.element.validity.rangeUnderflow) {
                        return hyva.strf('Please\u0020enter\u0020a\u0020value\u0020greater\u0020than\u0020or\u0020equal\u0020to\u0020\u0022\u00250\u0022.', options);
                    }
                    return true;
                },
                step(value, options, field, context) {
                    field.element.setAttribute('step', options);
                    field.element.checkValidity();
                    if (field.element.validity.stepMismatch) {
                        const val = Number(value);
                        const step = Number(options);
                        const msg = 'Please\u0020enter\u0020a\u0020valid\u0020value.\u0020The\u0020two\u0020nearest\u0020valid\u0020values\u0020are\u0020\u0022\u00250\u0022\u0020and\u0020\u0022\u00251\u0022.';
                        return hyva.strf(msg, Math.floor(val / step) * step, Math.ceil(val / step) * step);
                    }
                    return true;
                },
                pattern(value, options, field, context) {
                    field.element.setAttribute('pattern', options);
                    field.element.checkValidity();
                    if (field.element.validity.patternMismatch) {
                        return field.element.title ?
                            hyva.strf('Please\u0020match\u0020the\u0020requested\u0020format\u003A\u0020\u00250.', field.element.title) :
                            'Please\u0020match\u0020the\u0020requested\u0020format.'
                    }
                    return true;
                },
                email(value, options, field, context) {
                    const rule = /^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i;
                    if (value.length > 0 && !rule.test(value)) {
                        return 'Please\u0020enter\u0020a\u0020valid\u0020email\u0020address.';
                    }
                    return true;
                },
                password(value, options, field, context) {
                    const rule = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/;
                    if (value.length > 0 && !rule.test(value)) {
                        return 'Please\u0020provide\u0020at\u0020least\u0020one\u0020upper\u0020case,\u0020one\u0020lower\u0020case,\u0020one\u0020digit\u0020and\u0020one\u0020special\u0020character\u0020\u0028\u0023\u003F\u0021\u0040\u0024\u0025\u005E\u0026\u002A\u002D\u0029';
                    }
                    return true;
                },
                equalTo(value, options, field, context) {
                    const dependencyField = context.fields[options].element;
                    if (value !== dependencyField.value) {
                        const dependencyFieldName =
                            dependencyField.label ||
                            dependencyField.title ||
                            (dependencyField.labels && dependencyField.labels[0] && dependencyField.labels[0].innerText) ||
                            dependencyField.name;
                        return hyva.strf('This\u0020field\u0020value\u0020must\u0020be\u0020the\u0020same\u0020as\u0020\u0022\u00250\u0022.', dependencyFieldName);
                    }
                    return true;
                }
            };

            function raceSome(promises, pred) {
                return new Promise((resolve, reject) => {
                    if (promises.length === 0) {
                        return resolve();
                    }
                    let settled = false,
                        nDone = 0;
                    const resolveIf = v => {
                        if (!settled && (pred(v) || ++nDone === promises.length)) {
                            settled = true;
                            resolve(v);
                        }
                        return v;
                    }
                    promises.map(promise => {
                        promise.then(resolveIf).catch(reason => {
                            settled = true;
                            reject(reason)
                        });
                        return promise;
                    });
                });
            }
            const INPUT_ATTRIBUTE_RULES = {
                min: 'min',
                max: 'max',
                required: 'required',
                minlength: 'minlength',
                maxlength: 'maxlength',
                step: 'step',
                pattern: 'pattern'
            }
            const INPUT_TYPE_RULES = {
                email: 'email'
            }

            function getRules(element) {
                let rules = {};
                Object.keys(INPUT_ATTRIBUTE_RULES).forEach(attrName => {
                    if (element.hasAttribute(attrName)) {
                        rules[INPUT_ATTRIBUTE_RULES[attrName]] = element.getAttribute(attrName);
                    }
                })
                if (INPUT_TYPE_RULES[element.type]) {
                    rules[INPUT_TYPE_RULES[element.type]] = true;
                }
                if (element.dataset.validate) {
                    try {
                        Object.assign(rules, JSON.parse(element.dataset.validate));
                    } catch (error) {
                        console.error('Validator error. Cannot parse data-validate attribute of element:\n', element);
                    }
                }
                return rules;
            }

            function isInvalidRuleResult(ruleState) {
                return typeof ruleState === 'string' || !ruleState || (ruleState.type && ruleState.content);
            }
            async function runValidateFn(rule, options, value, field) {
                return formValidationRules[rule](value, options, field, this);
            }

            function generateId() {
                let id;
                do {
                    id = `${this.idPrefix}-${++this.idSeq}`;
                } while (document.getElementById(id));
                return id;
            }

            function isVisible(element) {
                const el = element.type !== 'hidden' ? element : (element.parentElement || {});
                return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length)
            }

            function elementWillValidate(element) {
                return (element.willValidate || element.type === 'hidden') &&
                    element.tagName !== 'BUTTON' &&
                    element.disabled === false &&
                    !(element.tagName === 'INPUT' && element.type === 'submit') &&
                    (element.hasAttribute('data-validate-hidden') || isVisible(element))
            }

            function createMessageContainer(el, fieldWrapperClassName) {
                if (!el.parentElement) {
                    return;
                }
                const refocus = document.activeElement === el;
                const wrapper = document.createElement('div');
                wrapper.classList.add.apply(wrapper.classList, fieldWrapperClassName.split(' '));
                el.parentElement.insertBefore(wrapper, el);
                wrapper.appendChild(el);
                refocus && document.activeElement !== el && el.focus();
                return wrapper;
            }

            function containerNotFound(selector, el) {
                const msg = `Cannot find message container element ${selector} of ${el.name}`;
                console.error(msg, el);
                throw msg;
            }

            function createTextInputFrom(el) {
                const text = document.createElement('INPUT');
                text.type = 'text';
                text.value = el.value;
                return text;
            }

            function classNamesToSelector(classNames) {
                return classNames.split(' ')
                    .filter(className => className.length > 0)
                    .map(className => `.${className}`)
                    .join('')
            }

            function hasMessagesWrapper(field, messagesWrapperClassName) {
                return this.getMessageContainer(field).querySelector(classNamesToSelector(messagesWrapperClassName));
            }

            function getMessagesWrapper(field, messagesWrapperClassName) {
                if (hasMessagesWrapper.call(this, field, messagesWrapperClassName)) {
                    return this.getMessageContainer(field).querySelector(classNamesToSelector(messagesWrapperClassName));
                }
                const msgWrapper = document.createElement('ul');
                const msgId = generateId.call(this);
                msgWrapper.id = msgId;
                field.element.setAttribute('aria-errormessage', msgId);
                field.element.setAttribute('aria-describedby', msgId);
                msgWrapper.classList.add.apply(msgWrapper.classList, messagesWrapperClassName.split(' '));
                if (field.validateOnChange) {
                    msgWrapper.setAttribute('aria-live', 'polite');
                }
                this.getMessageContainer(field).appendChild(msgWrapper);
                return msgWrapper;
            }

            function getCheckedValues(field) {
                const name = field.element.name.replace(/([\\"])/g, '\\$1');
                const elements = field.element.form.querySelectorAll('input[name="' + name + '"]:checked');
                return Array.from(elements).map(el => el.value);
            }

            function escapeHtml(s) {
                const div = document.createElement('div')
                div.innerText = s;
                return div.innerHTML;
            }

            function formValidation(formElement, options) {
                // Disable browser default validation
                if (formElement.tagName === 'FORM') {
                    formElement.setAttribute('novalidate', '');
                } else {
                    console.error('formValidation can be initialized only on FORM element', formElement);
                    return;
                }
                options = Object.assign({
                    fieldWrapperClassName: 'field field-reserved',
                    messagesWrapperClassName: 'messages',
                    validClassName: 'field-success',
                    invalidClassName: 'field-error',
                    pageMessagesWrapperSelector: null,
                    scrollToFirstError: true,
                }, options || {});
                return {
                    state: {
                        valid: false,
                    },
                    fields: {},
                    idSeq: 0,
                    idPrefix: formElement.id || 'vld-msg',
                    setupFields(elements) {
                        this.fields = {};
                        Array.from(elements).forEach(element => {
                            if (elementWillValidate(element)) {
                                this.setupField(element);
                            }
                        });
                    },
                    setupField(element) {
                        if (!element) return;
                        const onChange = !!element.dataset.onChange;
                        if (elementWillValidate(element)) {
                            const rules = getRules(element);
                            if (Object.keys(rules).length > 0) {
                                if (this.fields[element.name]) {
                                    Object.assign(this.fields[element.name].rules, rules);
                                } else {
                                    this.fields[element.name] = {
                                        element,
                                        rules: rules,
                                        validateOnChange: onChange,
                                        state: {
                                            valid: null,
                                            rules: {}
                                        }
                                    }
                                }
                            }
                        } else {
                            console.error('Element will not validate', element);
                        }
                    },
                    onSubmit(event) {
                        if (event.target.tagName === 'FORM') {
                            event.preventDefault();
                            this.validate()
                                .then(() => event.target.submit())
                                .catch(invalidElements => {});
                        }
                    },
                    onChange(event) {
                        event.target.dataset.onChange = 'true';
                        if (!Object.keys(this.fields).length) {
                            this.setupFields(formElement.elements);
                        }
                        if (!Object.keys(this.fields).includes(event.target.name)) {
                            this.setupField(event.target);
                        }
                        const field = this.fields[event.target.name];
                        this.validateField(field);
                        field && field.element.removeAttribute('data-on-change')
                    },
                    validateSafe() {
                        return new Promise(resolve => this.validate().then(() => resolve(true)).catch(() => {}))
                    },
                    validate() {
                        if (!Object.keys(this.fields).length || !Object.keys(this.fields).length !== formElement.elements.length) {
                            this.setupFields(formElement.elements);
                        }
                        return new Promise(async (resolve, reject) => {
                            if (formElement.elements) {
                                await raceSome(this.validateFields(), result => result !== true)
                                const invalidFields = Object.values(this.fields).filter(field => !field.state.valid);
                                this.state.valid = invalidFields.length === 0;
                                if (this.state.valid) {
                                    resolve();
                                } else {
                                    if (options.scrollToFirstError && invalidFields.length > 0) {
                                        invalidFields[0].element.focus()
                                        invalidFields[0].element.select && invalidFields[0].element.select();
                                    }
                                    reject(invalidFields.map(field => field.element));
                                }
                            }
                        });
                    },
                    validateFields() {
                        const fields = Object.values(this.fields);
                        fields.forEach(field => {
                            this.getMessageContainer(field).classList.remove(options.validClassName, options.invalidClassName)
                        });
                        return fields.map(field => this.validateField(field))
                    },
                    validateField(field) {
                        if (!field || !elementWillValidate(field.element)) {
                            return new Promise(resolve => resolve(true))
                        }
                        let value;
                        if (field.element.type === 'checkbox') {
                            value = getCheckedValues(field);
                        } else if (field.element.type === 'radio') {
                            value = getCheckedValues(field)[0] || undefined;
                        } else if (field.element.tagName === 'SELECT' && field.element.multiple) {
                            value = Array.from(field.element.selectedOptions).map(opt => opt.value);
                        } else {
                            value = field.element.value;
                        }
                        const rules = field.rules || {};
                        field.state.valid = true;
                        this.showFieldState(field);
                        const fieldValidations = Object.keys(rules).filter(rule => formValidationRules[rule]).map(async rule => {
                            return runValidateFn.call(this, rule, rules[rule], value, field).then(result => {
                                field.state.rules[rule] = result;
                                return result;
                            })
                        });
                        return new Promise(resolve => {
                            Promise.all(fieldValidations).then(results => {
                                field.state.valid = !elementWillValidate(field.element) || rules.length === 0 || !results.some(isInvalidRuleResult)
                                this.showFieldState(field);
                                resolve(field.state.valid);
                            })
                        });
                    },
                    getMessagesByField(field) {
                        const messages = [];
                        const invalidRules = Object.keys(field.state.rules).filter(rule => isInvalidRuleResult(field.state.rules[rule]));
                        field.rules && Object.keys(field.rules).forEach((rule) => {
                            if (invalidRules.includes(rule)) {
                                const customMessage = field.element.getAttribute('data-msg-' + rule);
                                const message = customMessage ? customMessage : field.state.rules[rule];
                                const ruleOptions = JSON.parse(JSON.stringify(field.rules[rule]));
                                if (typeof message === 'undefined' || message === null || (typeof message !== 'string' && !message.type)) {
                                    messages.push(hyva.strf('Validation rule "%0" failed.', rule));
                                } else if (Array.isArray(ruleOptions)) {
                                    ruleOptions.unshift(message.type ? message.content : message);
                                    const content = hyva.strf.apply(null, ruleOptions);
                                    messages.push(message.type ? {
                                        type: message.type,
                                        content
                                    } : content);
                                } else {
                                    const content = hyva.strf(message.type ? message.content : message, ruleOptions)
                                    messages.push(message.type ? {
                                        type: message.type,
                                        content
                                    } : content);
                                }
                            }
                        });
                        return messages;
                    },
                    /** @deprecated */
                    getFieldWrapper(field) {
                        return this.getMessageContainer(field)
                    },
                    getMessageContainer(field) {
                        let container;
                        const pageSelector = field.element.getAttribute('data-validation-container') || options.pageMessagesContainerSelector;
                        if (pageSelector) {
                            container = document.querySelector(pageSelector) ||
                                containerNotFound(pageSelector, field.element)
                        } else {
                            const containerSelector = classNamesToSelector(options.fieldWrapperClassName);
                            container = field.element.closest(containerSelector) ||
                                createMessageContainer(field.element, options.fieldWrapperClassName) ||
                                containerNotFound(containerSelector, field.element);
                        }
                        return container;
                    },
                    showFieldState(field) {
                        const container = this.getMessageContainer(field),
                            hasErrorMessages = hasMessagesWrapper.call(this, field, options.messagesWrapperClassName),
                            messages = this.getMessagesByField(field).map(m => {
                                return m.type !== 'html' ? escapeHtml(m.type ? m.content : m) : m.content;
                            });
                        container.classList.toggle(options.validClassName, field.state.valid && !hasErrorMessages);
                        container.classList.toggle(options.invalidClassName, !field.state.valid || hasErrorMessages);
                        this.createHtmlErrorMessage(field, messages);
                        if (field.state.valid) {
                            field.element.removeAttribute('aria-invalid');
                        } else {
                            field.element.setAttribute('aria-invalid', 'true');
                            if (!document.activeElement) {
                                field.element.focus();
                            }
                        }
                    },
                    removeMessages(field, messagesClass) {
                        if (!hasMessagesWrapper.call(this, field, messagesClass || options.messagesWrapperClassName)) {
                            return;
                        }
                        const msgWrapper = getMessagesWrapper.call(this, field, messagesClass || options.messagesWrapperClassName);
                        const messages = msgWrapper.querySelectorAll(`[data-msg-field='${field.element.name}']`);
                        Array.from(messages).forEach(msg => msg.remove());
                        if (msgWrapper && msgWrapper.childElementCount === 0) {
                            field.element.removeAttribute('aria-errormessage');
                            field.element.removeAttribute('aria-describedby');
                            msgWrapper.remove();
                        }
                    },
                    createErrorMessage(field, messages) {
                        const htmlMessages = (Array.isArray(messages) ? messages : [messages]).map(escapeHtml)
                        this.createHtmlErrorMessage(field, htmlMessages);
                    },
                    createHtmlErrorMessage(field, messages) {
                        this.removeMessages(field, options.messagesWrapperClassName);
                        field.element.removeAttribute('aria-errormessage');
                        field.element.removeAttribute('aria-describedby');
                        if (!field.state.valid) {
                            const msgWrapper = this.addHtmlMessages(field, options.messagesWrapperClassName, messages);
                            field.element.setAttribute('aria-errormessage', msgWrapper.id);
                            field.element.setAttribute('aria-describedby', msgWrapper.id);
                        }
                    },
                    /** @deprecated */
                    createMessage(field, message) {
                        return this.addMessages(field, options.messagesWrapperClassName, message);
                    },
                    addMessages(field, messagesClass, messages) {
                        const htmlMessages = (Array.isArray(messages) ? messages : [messages]).map(escapeHtml)
                        return this.addHtmlMessages(field, messagesClass, htmlMessages);
                    },
                    addHtmlMessages(field, messagesClass, htmlMessages) {
                        const msgWrapper = getMessagesWrapper.call(this, field, messagesClass);
                        (Array.isArray(htmlMessages) ? htmlMessages : [htmlMessages]).forEach((htmlMessage) => {
                            const li = document.createElement('li');
                            li.innerHTML = htmlMessage;
                            li.setAttribute('data-msg-field', field.element.name);
                            msgWrapper.appendChild(li);
                        });
                        return msgWrapper;
                    },
                    setField(name, value) {
                        this.fields[name].element.value = value;
                        this.fields[name].element.dispatchEvent((new Event('input')));
                        this.validateField(this.fields[name]);
                    }
                }
            }
            hyva.formValidation = formValidation;
            hyva.formValidation.rules = formValidationRules;
            hyva.formValidation.setInputAttributeRuleName = (attrName, ruleName) => INPUT_ATTRIBUTE_RULES[attrName] = ruleName || attrName;
            hyva.formValidation.setInputTypeRuleName = (typeName, ruleName) => INPUT_TYPE_RULES[typeName] = ruleName || typeName;
            hyva.formValidation.addRule = (name, validator) => formValidationRules[name] = validator;
        }(window.hyva = window.hyva || {}));
    </script>

    <button type="button" x-data x-init="$store.asideBlocs.addAside('')" @click="$store.asideBlocs.toggleAside('')" class=" btn  btn-dark  btn-solid  btn-size-lg">
        Open side panel

    </button>

    <script type="module" src="../../js/anchor.min.js" defer crossorigin></script>
    <script type="module" src="../../js/intersect.min.js" defer crossorigin></script>
    <script type="module" src="../../js/collapse.min.js" defer crossorigin></script>
    <script type="module" src="../../js/alpine3.min.js" defer crossorigin></script>

    <script>
        (g => {
            var h, a, k, p = "The Google Maps JavaScript API",
                c = "google",
                l = "importLibrary",
                q = "__ib__",
                m = document,
                b = window;
            b = b[c] || (b[c] = {});
            var d = b.maps || (b.maps = {}),
                r = new Set,
                e = new URLSearchParams,
                u = () => h || (h = new Promise(async (f, n) => {
                    await (a = m.createElement("script"));
                    e.set("libraries", [...r] + "");
                    for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]);
                    e.set("callback", c + ".maps." + q);
                    a.src = `https://maps.${c}apis.com/maps/api/js?` + e;
                    d[q] = f;
                    a.onerror = () => h = n(Error(p + " could not load."));
                    a.nonce = m.querySelector("script[nonce]")?.nonce || "";
                    m.head.append(a)
                }));
            d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n))
        })({
            key: "AIzaSyDR6ZEfRdQeGl40JZj1jYumFJ_xZS2z1Gg",
            v: "weekly",
            // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
            // Add other bootstrap parameters as needed, using camel case.
        });
    </script>
    <script src="../../js/markerclusterer.min.js" defer crossorigin></script>

    <script>
        window.addEventListener('alpine:init', () => {
            console.log('Alpine.js has been initialized');
            Alpine.store('screen', {
                isSmall: window.matchMedia('(max-width: 639px)').matches,
                isMobile: window.matchMedia('(max-width: 767px)').matches,
                isTablet: window.matchMedia('(max-width: 1023px)').matches,
                init() {
                    const smallMedia = window.matchMedia('(max-width: 639px)');
                    const mobileMedia = window.matchMedia('(max-width: 767px)');
                    const tabletMedia = window.matchMedia('(max-width: 1023px)');
                    this.isSmall = smallMedia.matches;
                    this.isMobile = mobileMedia.matches;
                    this.isTablet = tabletMedia.matches;
                    const updateScreen = (event, type) => {
                        if (type === 'small') this.isSmall = event.matches;
                        if (type === 'mobile') this.isMobile = event.matches;
                        if (type === 'tablet') this.isTablet = event.matches;
                    };
                    [{
                            media: smallMedia,
                            type: 'small'
                        },
                        {
                            media: mobileMedia,
                            type: 'mobile'
                        },
                        {
                            media: tabletMedia,
                            type: 'tablet'
                        }
                    ].forEach(({
                        media,
                        type
                    }) => {
                        if (typeof media.onchange !== 'object') {
                            media.addListener((e) => updateScreen(e, type));
                        } else {
                            media.addEventListener('change', (e) => updateScreen(e, type));
                        }
                    });
                }
            });
            Alpine.store('asideBlocs', {
                asides: [],
                // Add new aside block
                addAside(name, customProperties = {}) {
                    if (!this.asides.find(aside => aside.name === name)) {
                        this.asides.push({
                            name,
                            open: false,
                            ...customProperties,
                        });
                    }
                },
                removeAside(name) {
                    this.asides = this.asides.filter(aside => aside.name !== name);
                },
                toggleAside(name) {
                    const aside = this.asides.find(aside => aside.name === name);
                    if (aside) {
                        aside.open = !aside.open;
                        document.body.classList.toggle('overflow-hidden', aside.open);
                    }
                },
                closeAside(name) {
                    const aside = this.asides.find(aside => aside.name === name);
                    if (aside) {
                        aside.open = false;
                        document.body.classList.remove('overflow-hidden');
                    }
                },
                openAside(name) {
                    const aside = this.asides.find(aside => aside.name === name);
                    if (aside) {
                        aside.open = true;
                        document.body.classList.add('overflow-hidden');
                    }
                }
            });
            Alpine.store('locator', {
                days: [{
                        key: 'monday',
                        label: 'Lundi'
                    },
                    {
                        key: 'tuesday',
                        label: 'Mardi'
                    },
                    {
                        key: 'wednesday',
                        label: 'Mercredi'
                    },
                    {
                        key: 'thursday',
                        label: 'Jeudi'
                    },
                    {
                        key: 'friday',
                        label: 'Vendredi'
                    },
                    {
                        key: 'saturday',
                        label: 'Samedi'
                    },
                    {
                        key: 'sunday',
                        label: 'Dimanche'
                    },
                ],
                allStores: [],
                countStore: "",
                filteredDistanceStores: null,
                selectedStore: null,
                loading: true,
                mapCenter: null,
                mapInstance: null,
                async init() {
                    try {
                        await this.loadLibraries();
                        await this.loadStores();
                    } finally {
                        this.loading = false;
                    }
                },
                async loadLibraries() {
                    const [geometry] = await Promise.all([
                        google.maps.importLibrary("geometry"),
                    ]);
                },
                async loadStores() {
                    try {
                        const response = await fetch(`${window.location.origin}/js/json/getList.json`);
                        const data = await response.json();
                        if (data) {
                            this.countStore = data.length;
                            this.allStores = data;
                        }
                    } catch (error) {
                        console.error('Erreur lors du chargement des magasins:', error);
                        this.allStores = [];
                    }
                },
                selectStore(store) {
                    this.selectedStore = store;
                    if (typeof this.onSelectStore === 'function') {
                        this.onSelectStore(store);
                    }
                },
                updateDistances(minZoom = 12) {
                    if (!this.mapInstance) return;
                    const zoom = this.mapInstance.getZoom();
                    if (zoom < minZoom) {
                        return this.filteredDistanceStores = []
                    }
                    const center = this.mapInstance.getCenter();
                    if (!center) return;
                    this.filteredDistanceStores = this.allStores
                        .filter(store => this.validateCoordinates(store.lat, store.lng).isValid)
                        .map(store => {
                            const position = new google.maps.LatLng(parseFloat(store.lat), parseFloat(store.lng));
                            const distanceInMeters = google.maps.geometry.spherical.computeDistanceBetween(center, position);
                            const distanceInKm = distanceInMeters / 1000;
                            return {
                                ...store,
                                distanceInKm,
                                distance: `${distanceInKm.toFixed(1)} km`
                            };
                        })
                        .sort((a, b) => a.distanceInKm - b.distanceInKm);
                },
                validateCoordinates(lat, lng) {
                    const isEmpty = (v) => v === '' || v === null || v === undefined;
                    if (isEmpty(lat) || isEmpty(lng)) {
                        return {
                            isValid: false,
                            error: 'Les coordonnées ne peuvent pas être null, undefined ou vides'
                        };
                    }
                    const latitude = parseFloat(lat);
                    const longitude = parseFloat(lng);
                    if (isNaN(latitude) || isNaN(longitude)) {
                        return {
                            isValid: false,
                            error: 'Les coordonnées doivent être des nombres valides'
                        };
                    }
                    if (latitude < -90 || latitude > 90) {
                        return {
                            isValid: false,
                            error: 'La latitude doit être comprise entre -90 et 90'
                        };
                    }
                    if (longitude < -180 || longitude > 180) {
                        return {
                            isValid: false,
                            error: 'La longitude doit être comprise entre -180 et 180'
                        };
                    }
                    return {
                        isValid: true,
                        coordinates: {
                            lat: latitude,
                            lng: longitude
                        }
                    };
                },
                setMapCenter(lat, lng, zoom) {
                    const parsedLat = parseFloat(lat);
                    const parsedLng = parseFloat(lng);
                    if (!isNaN(parsedLat) && !isNaN(parsedLng)) {
                        this.mapInstance.panTo({
                            lat: parsedLat,
                            lng: parsedLng
                        })
                    }
                    if (zoom) {
                        this.mapInstance.setZoom(zoom)
                    }
                },
                goToStore(store) {
                    if (!this.mapInstance || !store) return;
                    const lat = parseFloat(store.lat);
                    const lng = parseFloat(store.lng);
                    if (isNaN(lat) || isNaN(lng)) return;
                    this.setMapCenter(lat, lng, 15)
                    this.selectStore(store);
                },
                getOpeningStatus(store) {
                    const now = new Date();
                    const days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
                    const currentDayKey = days[now.getDay()];
                    const schedule = store[currentDayKey];
                    if (!schedule || schedule.toLowerCase().includes('fermé')) {
                        return {
                            status: 'Fermé',
                            end: null
                        };
                    }
                    const [start, end] = schedule.split(' - ');
                    if (!start || !end) {
                        return {
                            status: 'Fermé',
                            end: null
                        };
                    }
                    const [startHour, startMin] = start.split(':').map(Number);
                    const [endHour, endMin] = end.split(':').map(Number);
                    const startTime = new Date();
                    startTime.setHours(startHour, startMin, 0);
                    const endTime = new Date();
                    endTime.setHours(endHour, endMin, 0);
                    if (now >= startTime && now <= endTime) {
                        return {
                            status: 'Ouvert',
                            end
                        };
                    }
                    return {
                        status: 'Fermé',
                        end: null
                    };
                }
            });
        });
    </script>

</body>

</html>
{% extends '@layout' %}

{% block yield %}
    {% render "@template-button" with {
        label:'Open side panel',
        color: colorType|default('dark'),
        button_attribute: ('x-data x-init="$store.asideBlocs.addAside(\'' ~ _target.meta.name ~ '\')" @click="$store.asideBlocs.toggleAside(\'' ~ _target.meta.name ~ '\')"')|replace({"\'": "'"}),
    } %}
    {{ yield }}
{% endblock %}
/* No context defined. */

No notes defined.