<section class="org-travel-time-calculator-block" data-component="travel-time-calculator" data-location="">
    <div class="vebego-container">

        <div class="calculator-content">
            <svg class="ambient absolute -z-10 h-full w-full" preserveAspectRatio="xMidYMid slice" viewBox="0 0 1401 561" fill="none" xmlns="http://www.w3.org/2000/svg">
                <g clip-path="url(#clip0_732_31)">
                    <path class="animate-wiggle" d="M-2050.14 -204.345L1538.67 -2276.34L3610.67 1312.46L21.8563 3384.46L-2050.14 -204.345Z" fill="url(#paint0_linear_732_31)" />
                    <path class="animate-wiggle" opacity="0.35" d="M-235.763 -1021.04C184.007 -844.351 514.379 -368.568 498.964 32.3718C481.557 487.334 63.3508 859.84 -256.582 932.059C-576.515 1004.28 -869.519 656.538 -468.412 471.643C-67.3055 286.749 116.195 264.613 302.527 -1.01921C259.546 -168.006 -47.7195 -422.581 -483.652 -646.742C-845.528 -833.228 -639.19 -1190.84 -235.763 -1021.04ZM743.374 -403.471C551.089 -574.814 489.961 -1069.37 661.244 -1309.44C793.684 -1495.02 1076.36 -1333.68 1004.04 -1160.87C858.856 -813.25 857.106 -584.44 881.882 -502.563C1123.47 -371.494 1565.15 -600.068 1652.51 -628.004C1865.35 -695.764 2057.55 -489.499 1784.38 -336.284C1318.25 -75.0371 933.111 -234.594 743.374 -403.471ZM2441.76 28.8834C2740.56 160.667 2742.79 590.227 2272.6 525.9C1818.24 463.679 1215.21 334.868 855.28 500.489C776.87 717.311 898.58 1141.45 1223.94 1711.81C1463.93 2132.35 883.395 2305.53 644.6 1988.36C335.85 1578.27 206.665 902.528 641.102 364.285C870.363 79.4919 1630.36 -328.355 2441.76 28.8834Z" fill="#562081" />
                    <path class="animate-wiggle" d="M619.906 283.605C1040.16 304.998 1934.43 736.16 2151.54 1733.93C2231.54 2101.51 1833.08 2394.62 1574.58 1912.78C1324.5 1447.48 1036.08 798.822 638.144 575.386C382.987 648.953 70.9201 1049.81 -239.065 1738.82C-468.239 2247.19 -1022.52 1824.1 -889.306 1386.33C-717.037 821.296 -175.264 243.348 619.906 283.605Z" fill="url(#paint2_linear_732_31)" />
                    <path class="animate-wiggle-2" d="M831.823 -74.8587C396.739 216.832 -233.363 80.0584 -517.676 -168.618C-801.989 -417.294 -676.358 -925.148 -232.682 -677.367C210.995 -429.586 356.12 -273.778 730.026 -280.429C856.731 -433.447 885.528 -891.581 799.415 -1449.29C728.136 -1912.07 1201.02 -1961.81 1315.63 -1471.74C1435.17 -961.448 1215.23 -332.216 831.823 -74.8587Z" fill="url(#paint3_linear_732_31)" />
                </g>
                <defs>
                    <linearGradient id="paint0_linear_732_31" x1="3569.5" y1="1265.2" x2="-2038.5" y2="-164.605" gradientUnits="userSpaceOnUse">
                        <stop stop-color="#501D79" />
                        <stop offset="0.1001" stop-color="#562081" />
                        <stop offset="0.4029" stop-color="#980D7F" />
                        <stop offset="0.5587" stop-color="#871280" />
                        <stop offset="0.8653" stop-color="#5C1E81" />
                        <stop offset="0.9028" stop-color="#562081" />
                        <stop offset="1" stop-color="#501D79" />
                    </linearGradient>
                    <linearGradient id="paint1_linear_732_31" x1="1940.44" y1="-897.473" x2="1576.67" y2="1225.63" gradientUnits="userSpaceOnUse">
                        <stop stop-color="#B92D85" stop-opacity="0.7" />
                        <stop offset="0.2185" stop-color="#C44072" stop-opacity="0.7655" />
                        <stop offset="0.6611" stop-color="#DF703F" stop-opacity="0.8983" />
                        <stop offset="1" stop-color="#F69915" />
                    </linearGradient>
                    <linearGradient id="paint2_linear_732_31" x1="1683.94" y1="1213.25" x2="-473.832" y2="1087.84" gradientUnits="userSpaceOnUse">
                        <stop stop-color="#D62B87" stop-opacity="0.7" />
                        <stop offset="0.2013" stop-color="#C02084" stop-opacity="0.7" />
                        <stop offset="0.505" stop-color="#980D7F" stop-opacity="0.7" />
                        <stop offset="0.9013" stop-color="#3F2584" stop-opacity="0.7" />
                        <stop offset="1" stop-color="#282B85" stop-opacity="0.7" />
                    </linearGradient>
                    <linearGradient id="paint3_linear_732_31" x1="-150.413" y1="-274.39" x2="1381.97" y2="-1527.36" gradientUnits="userSpaceOnUse">
                        <stop stop-color="#651B82" />
                        <stop offset="0.9974" stop-color="#901080" />
                    </linearGradient>
                    <clipPath id="clip0_732_31">
                        <rect width="1401" height="561" fill="white" />
                    </clipPath>
                </defs>
            </svg>

            <h2 class="atm-heading ">Hoe reis je naar je werk?</h2>

            <div class="atm-form-input  ">
                <input class="form-input" type="text" id="input" name="input">
                <label class="atm-form-label form-label " for="input">Label</label>

                <i class="atm-icon form-input-error-icon far fa-times   "></i>

                <i class="atm-icon form-input-valid-icon far fa-check   "></i>

            </div>

            <div class="transport-options">
                <div class="atm-form-radiobutton icon">
                    <input type="radio" id="transport-bus" name="transport" value="bus" class="peer hidden" checked>
                    <label for="transport-bus" class="radiobutton-icon-wrapper">
                        <i class="atm-icon  far fa-external-link   "></i>

                    </label>
                </div>

                <div class="atm-form-radiobutton icon">
                    <input type="radio" id="transport-train" name="transport" value="train" class="peer hidden">
                    <label for="transport-train" class="radiobutton-icon-wrapper">
                        <i class="atm-icon  far fa-external-link   "></i>

                    </label>
                </div>

                <div class="atm-form-radiobutton icon">
                    <input type="radio" id="transport-bicycle" name="transport" value="bicycle" class="peer hidden">
                    <label for="transport-bicycle" class="radiobutton-icon-wrapper">
                        <i class="atm-icon  far fa-external-link   "></i>

                    </label>
                </div>

                <div class="atm-form-radiobutton icon">
                    <input type="radio" id="transport-walking" name="transport" value="walking" class="peer hidden">
                    <label for="transport-walking" class="radiobutton-icon-wrapper">
                        <i class="atm-icon  far fa-external-link   "></i>

                    </label>
                </div>

            </div>

            <a class="atm-button atm-button-primary  button-md no-icon  ">
                <div class="button-content-wrapper">
                    <span class="button-content">
                        <span>Button</span>
                        <i class="atm-icon  fal fa-arrow-right   "></i>

                    </span>
                </div>
                <span class="button-triangle"></span>
            </a>

        </div>
</section>
<section class="org-travel-time-calculator-block" data-component="travel-time-calculator" data-location="{{location}}">
  <div class="vebego-container">

    <div class="calculator-content">
    {{render "@ambient"}}

    {{#if title}}
      {{render '@heading' title merge=true}}
    {{/if}}

    {{ render '@input' input merge=true }}

    <div class="transport-options">
        {{#each transportOptions}}
                {{render '@radiobutton' this merge=true icon=true}}
        {{/each}}
    </div>

  {{ render '@button-primary' }}
                    
  </div>
</section>
{
  "title": {
    "text": "Hoe reis je naar je werk?",
    "tag": "h2"
  },
  "transportOptions": [
    {
      "name": "transport",
      "value": "bus",
      "checked": true,
      "modifier": "icon",
      "icon": {
        "class": "fa-solid fa-bus"
      }
    },
    {
      "name": "transport",
      "value": "train",
      "modifier": "icon",
      "icon": {
        "class": "fa-solid fa-train"
      }
    },
    {
      "name": "transport",
      "value": "bicycle",
      "modifier": "icon",
      "icon": {
        "class": "fa-solid fa-bicycle"
      }
    },
    {
      "name": "transport",
      "value": "walking",
      "modifier": "icon",
      "icon": {
        "class": "fa-solid fa-person-walking"
      }
    }
  ]
}
  • Content:
    .org-travel-time-calculator-block {
        @apply relative overflow-hidden rounded-lg;
    
        .vebego-container {
            @apply relative z-10;
        }
    
        .ambient {
            @apply top-0 left-0;
        }
    
        .travel-time-block {
            @apply flex gap-6 flex-col transition;
        }
    
        .atm-form-input {
            @apply w-full;
    
            .form-input {
                @apply rounded-md py-8 w-full;
            }
    
            .atm-form-label {
                @apply font-display text-primary;
            }
        }
    
        .calculator-content {
            @apply flex flex-col gap-4 lg:gap-8 p-8 lg:p-10 rounded-lg overflow-hidden relative transition min-h-[400px] justify-center;
        }
    
        .atm-heading {
            @apply text-white;
        }
    
        .transport-options {
            @apply flex justify-between gap-2 md:gap-3;
        }
    
        .results {
            @apply text-white;
    
            .result-description {
                @apply mb-2 text-lg;
            }
    
            .result-amount {
                @apply text-h1 font-semibold my-8 font-display;
            }
        }
    
        .disclaimer {
            @apply mt-8 text-white;
        }
    }
    
  • URL: /components/raw/travel-time-calculation-block/travel-time-calculation-block.css
  • Filesystem Path: src\components\04-organisms\travel-time-calculation-block\travel-time-calculation-block.css
  • Size: 1.1 KB
  • Content:
    document.addEventListener('DOMContentLoaded', function () {
        const calculatorBlock = document.querySelector(
            '.org-travel-time-calculator-block'
        );
        const travelTimeBlock = document.querySelector('.travel-time-block');
        const calculatorContent = document.querySelector(
            '.org-travel-time-calculator-block .calculator-content'
        );
        const form = calculatorBlock?.querySelector('form') || calculatorBlock;
        const postalCodeInput = calculatorBlock?.querySelector(
            'input[type="search"]'
        );
        const transportRadios = calculatorBlock?.querySelectorAll(
            'input[type="radio"]'
        );
        const submitButton = calculatorBlock?.querySelector(
            'button[type="submit"]'
        );
    
        let resultContainer = calculatorContent?.querySelector(
            '.travel-time-result'
        );
        if (!resultContainer && calculatorContent) {
            resultContainer = document.createElement('div');
            resultContainer.className = 'travel-time-result hidden font-display';
            calculatorContent.appendChild(resultContainer);
        }
    
        if (submitButton) {
            submitButton.addEventListener('click', handleSubmit);
        } else if (form) {
            form.addEventListener('submit', handleSubmit);
        }
    
        async function handleSubmit(e) {
            e?.preventDefault();
    
            const selectedTransport = Array.from(transportRadios || []).find(
                (radio) => radio.checked
            )?.value;
            const postalCode = postalCodeInput?.value.trim();
    
            const postalCodeRegex = /^[1-9][0-9]{3}\s?[A-Z]{2}$/i;
    
            if (!postalCode) {
                showError('Vul een postcode in');
                postalCodeInput?.focus();
                return;
            }
    
            if (!postalCodeRegex.test(postalCode)) {
                showError(
                    'Vul een geldige Nederlandse postcode in (bijv. 1234 AB)'
                );
                postalCodeInput?.focus();
                return;
            }
    
            if (!selectedTransport) {
                showError('Selecteer een vervoersmiddel');
                return;
            }
    
            try {
                const postalCodeClean = postalCode.replace(/\s/g, '');
    
                const vacancyPostcode = calculatorBlock?.dataset.vacancyPostcode;
                const vacancyPostcodeClean = vacancyPostcode.replace(/\s/g, '');
    
                const apiUrl = `/umbraco/surface/TravelTimeSurface/GetTravelTime?postalCode=${encodeURIComponent(
                    postalCodeClean
                )}&travelMethod=${encodeURIComponent(
                    selectedTransport
                )}&location=${encodeURIComponent(vacancyPostcodeClean)}`;
    
                const response = await fetch(apiUrl, {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json',
                        Accept: 'application/json',
                    },
                });
    
                if (!response.ok) {
                    if (response.status === 404) {
                        throw new Error('Reistijd calculator niet beschikbaar');
                    } else if (response.status === 400) {
                        throw new Error('Ongeldige invoer');
                    } else {
                        throw new Error(
                            `Gebruik een bestaande postcode`
                        );
                    }
                }
                
                // Only hide travel time block after successful response
                travelTimeBlock?.classList.add('!hidden');
    
                const responseText = await response.text();
    
                let data;
                try {
                    const parsedResponse = JSON.parse(responseText);
                    data =
                        typeof parsedResponse === 'string'
                            ? JSON.parse(parsedResponse)
                            : parsedResponse;
                } catch (parseError) {
                    throw new Error('Ongeldige JSON response ontvangen');
                }
    
                if (
                    !data ||
                    typeof data.distance === 'undefined' ||
                    typeof data.duration === 'undefined'
                ) {
                    throw new Error('Ongeldige data ontvangen');
                }
    
                showResult(data, selectedTransport);
            } catch (error) {
                console.error('Fout bij ophalen reistijd:', error);
                showError(error.message || 'Er is een fout opgetreden');
            }
        }
    
        function showResult(data, selectedTransport) {
            if (!resultContainer) return;
    
            const distance = data.distance
                ? `${data.distance.toFixed(1)} km`
                : 'Onbekend';
            const duration = data.duration
                ? `${Math.round(data.duration)} minuten`
                : 'Onbekend';
    
            const transportMethods = {
                transit: 'met het openbaar vervoer',
                train: 'met de trein',
                bicycle: 'met de fiets',
                walking: 'te voet',
            };
    
            const transportText =
                transportMethods[selectedTransport] || 'met de auto';
    
            resultContainer.innerHTML = `
                <div>
                    <div class="mb-6">
                        <h1 class="text-h2 text-white mb-2">Je reisafstand is <span class="font-bold">${distance}</span>, je bent <span class="font-bold">${duration}</span> onderweg</h1>
                        <p class="text-md text-white">wanneer je <span class="font-bold">${transportText}</span> reist.</p>
                    </div>
                    <a class="atm-link !text-white mt-6" href="#">Terug</a>
                    ${
                        data.route
                            ? `<div class="mt-4 text-sm text-white"><strong>Route:</strong> ${data.route}</div>`
                            : ''
                    }
                </div>
            `;
            resultContainer.classList.remove('hidden', 'bg-red-50', 'text-red-700');
    
            const backLink = resultContainer.querySelector('a[href="#"]');
            if (backLink) {
                backLink.addEventListener('click', (e) => {
                    e.preventDefault();
                    travelTimeBlock?.classList.remove('!hidden');
                    resultContainer.classList.add('hidden');
                });
            }
        }
    
        function showError(message) {
            if (!resultContainer) return;
    
            resultContainer.innerHTML = `
                    <label class="text-white">${message}</label>
            `;
            resultContainer.classList.remove('hidden');
        }
    });
    
  • URL: /components/raw/travel-time-calculation-block/travel-time-calculation-block.js
  • Filesystem Path: src\components\04-organisms\travel-time-calculation-block\travel-time-calculation-block.js
  • Size: 6.5 KB

No notes defined.