{"id":11356,"date":"2024-12-12T13:30:16","date_gmt":"2024-12-12T12:30:16","guid":{"rendered":"https:\/\/tastemallorca.es\/mapa-restaurantes\/"},"modified":"2024-12-12T13:30:16","modified_gmt":"2024-12-12T12:30:16","slug":"mapa-restaurantes","status":"publish","type":"page","link":"https:\/\/tastemallorca.es\/en\/mapa-restaurantes\/","title":{"rendered":"Mapa Restaurantes"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"11356\" class=\"elementor elementor-11356 elementor-772\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5ec34cd e-con-full e-flex e-con e-parent\" data-id=\"5ec34cd\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div data-dce-background-color=\"#FAFAFA\" class=\"elementor-element elementor-element-7224f72 e-con-full e-flex e-con e-child\" data-id=\"7224f72\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-91d3c59 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"91d3c59\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Cerca de t\u00ed:<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-68bc6eb elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"68bc6eb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9d107ee elementor-widget__width-initial elementor-widget elementor-widget-html\" data-id=\"9d107ee\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!-- Selector de gastronom\u00eda -->\n<label for=\"gastronomia-filter\">\u00bfQu\u00e9 quieres comer?<\/label>\n<select id=\"gastronomia-filter\">\n    <option value=\"all\">Elige que te apetece...<\/option>\n<\/select>\n\n<!-- Contenedor con scroll separado (sin borde) -->\n<!-- Contenedor con scroll en desktop, sin scroll en m\u00f3vil -->\n<div class=\"restaurant-scroll-container\">\n    <div id=\"restaurant-list\" style=\"display: grid; gap: 10px;\"><\/div>\n<\/div>\n\n\n<p id=\"location-error\" style=\"color: red; display: none;\">No se pudo obtener tu ubicaci\u00f3n.<\/p>\n\n<!-- Cargador -->\n<div id=\"loading\" style=\"display: flex; justify-content: center; align-items: center; height: 100%; flex-direction: column;\">\n    <div style=\"border: 4px solid #f3f3f3; border-top: 4px solid #F8B233; border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite;\"><\/div>\n    <p style=\"margin-top: 10px; font-family: Arial, sans-serif; color: #555;\">Cargando restaurantes...<\/p>\n<\/div>\n\n<script>\nfunction calculateDistance(lat1, lng1, lat2, lng2) {\n    const R = 6371;\n    const dLat = (lat2 - lat1) * (Math.PI \/ 180);\n    const dLng = (lng2 - lng1) * (Math.PI \/ 180);\n    const a =\n        Math.sin(dLat \/ 2) * Math.sin(dLat \/ 2) +\n        Math.cos(lat1 * (Math.PI \/ 180)) *\n            Math.cos(lat2 * (Math.PI \/ 180)) *\n            Math.sin(dLng \/ 2) *\n            Math.sin(dLng \/ 2);\n    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n    return R * c;\n}\n\nasync function loadRestaurants() {\n    const loadingElement = document.getElementById(\"loading\");\n    const listContainer = document.getElementById(\"restaurant-list\");\n    const gastronomyFilter = document.getElementById(\"gastronomia-filter\");\n\n    try {\n        loadingElement.style.display = \"flex\";\n\n        const response = await fetch(\"https:\/\/tastemallorca.es\/wp-json\/wp\/v2\/restaurante\/?per_page=100\");\n        if (!response.ok) throw new Error(\"Error en la API de restaurantes\");\n        const restaurantes = await response.json();\n\n        const gastronomyResponse = await fetch(\"https:\/\/tastemallorca.es\/wp-json\/wp\/v2\/gastronomia?per_page=100&hide_empty=true\");\n        if (!gastronomyResponse.ok) throw new Error(\"Error en la API de gastronom\u00eda\");\n        const gastronomias = await gastronomyResponse.json();\n\n        const gastronomyMap = {};\n        gastronomias.forEach(gastro => {\n            gastronomyMap[gastro.id] = gastro.name;\n            const option = document.createElement(\"option\");\n            option.value = gastro.id;\n            option.textContent = gastro.name;\n            gastronomyFilter.appendChild(option);\n        });\n\n        if (navigator.geolocation) {\n            navigator.geolocation.getCurrentPosition((position) => {\n                const userLat = position.coords.latitude;\n                const userLng = position.coords.longitude;\n\n                let sortedRestaurants = restaurantes\n                    .filter(r => r.acf && r.acf.ubicacion_exacta)\n                    .map(r => ({\n                        nombre: r.title.rendered,\n                        direccion: r.acf.ubicacion_exacta.address || \"Direcci\u00f3n no disponible\",\n                        lat: parseFloat(r.acf.ubicacion_exacta.lat),\n                        lng: parseFloat(r.acf.ubicacion_exacta.lng),\n                        logo: (r.acf.Logo && r.acf.Logo.url) ? r.acf.Logo.url : 'https:\/\/tastemallorca.es\/wp-content\/uploads\/2024\/12\/LOGO_NO_DISPONIBLE.jpg',\n                        url: r.link || '#',\n                        distancia: calculateDistance(userLat, userLng, parseFloat(r.acf.ubicacion_exacta.lat), parseFloat(r.acf.ubicacion_exacta.lng)),\n                        gastronomia_ids: r.gastronomia || [],\n                        gastronomia: r.gastronomia ? r.gastronomia.map(id => gastronomyMap[id]).join(', ') : 'No especificado'\n                    }))\n                    .sort((a, b) => a.distancia - b.distancia);\n\n                const PAGE_SIZE = 8;\n                let currentPage = 1;\n\n                const renderRestaurants = (filterId = \"all\", reset = false) => {\n    if (reset) {\n        listContainer.innerHTML = \"\";\n        currentPage = 1;\n    }\n\n    const filteredRestaurants = filterId === \"all\"\n        ? sortedRestaurants\n        : sortedRestaurants.filter(r => r.gastronomia_ids.includes(parseInt(filterId)));\n\n    const start = (currentPage - 1) * PAGE_SIZE;\n    const end = currentPage * PAGE_SIZE;\n    const visibleRestaurants = filteredRestaurants.slice(start, end);\n\n    const fragment = document.createDocumentFragment();\n\n    visibleRestaurants.forEach(restaurante => {\n        const restaurantItem = document.createElement('div');\n        restaurantItem.style = \"text-align: left; width:100%; padding: 10px; font-family: Arial, sans-serif; border: 1px solid #ccc; border-radius: 8px; background-color:white; margin:0px auto;\";\n        restaurantItem.innerHTML = `\n            <div style=\"display: flex; align-items: center; margin-bottom: 10px;\">\n                <div style=\"border:1px solid lightgrey; min-width: 70px; height: 70px; background-image: url('${restaurante.logo}'); background-size: cover; background-position: center; border-radius: 50%; margin-right: 15px;\"><\/div>\n                <div>\n                    <h3 style=\"margin: 0; font-size: 20px; font-weight: bold;\">${restaurante.nombre}<\/h3>\n                    <p style=\"margin: 5px 0 0; font-size: 18px; color: #888;\">${restaurante.distancia.toFixed(2)} km<\/p>\n                <\/div>\n            <\/div>\n            <div style=\"display: flex; gap: 10px;\" class=\"buttonslist\">\n                <a href=\"${restaurante.url}\" target=\"\" style=\"flex: 1; text-align: center; padding: 5px 10px; background-color: #F8B233; color: white; font-weight: bold; text-decoration: none; border-radius: 25px; font-size:15px;\">Ver Restaurante<\/a>\n                <a href=\"https:\/\/www.google.com\/maps\/search\/?api=1&query=${encodeURIComponent(restaurante.direccion)}\" target=\"_blank\" style=\"flex: 1; text-align: center; padding: 5px 10px; background-color: #4285F4; color: white; font-weight: bold; text-decoration: none; border-radius: 25px; font-size:15px;\">Google Maps<\/a>\n            <\/div>\n        `;\n        fragment.appendChild(restaurantItem);\n    });\n\n    \/\/ Eliminar bot\u00f3n anterior si existe\n    const prevLoadMore = document.getElementById('load-more-btn-inline');\n    if (prevLoadMore) {\n        prevLoadMore.remove();\n    }\n\n    \/\/ Agregar bot\u00f3n si quedan m\u00e1s por cargar\n    if (filteredRestaurants.length > currentPage * PAGE_SIZE) {\n        const loadMoreItem = document.createElement('div');\n        loadMoreItem.id = 'load-more-btn-inline';\n        loadMoreItem.style = \"text-align: center;\";\n        const btn = document.createElement('button');\n        btn.textContent = \"Cargar m\u00e1s\";\n        btn.style = \"padding: 10px 20px; background-color: #F8B233; color: white; font-weight: bold; border: none; border-radius: 25px; cursor: pointer; font-family: Arial, sans-serif;\";\n        btn.addEventListener(\"click\", () => {\n            currentPage++;\n            renderRestaurants(filterId, false);\n        });\n        loadMoreItem.appendChild(btn);\n        fragment.appendChild(loadMoreItem);\n    }\n\n    listContainer.appendChild(fragment);\n};\n\n\n                gastronomyFilter.addEventListener(\"change\", (e) => {\n                    renderRestaurants(e.target.value, true);\n                });\n\n                renderRestaurants(\"all\", true);\n                loadingElement.style.display = \"none\";\n            });\n        }\n    } catch (error) {\n        console.error(\"Error cargando restaurantes:\", error);\n        loadingElement.style.display = \"none\";\n    }\n}\n\nloadRestaurants();\n<\/script>\n\n<style>\n.restaurant-scroll-container {\n    max-height: 70vh;\n    overflow-y: auto;\n    padding: 10px;\n    border-radius: 10px;\n}\n\n@media (max-width: 600px) {\n    .restaurant-scroll-container {\n        max-height: none;\n        overflow-y: visible;\n        padding: 0;\n    }\n}\n\nlabel {\n    font-family: 'Arial', sans-serif;\n    font-size: 18px;\n    font-weight: bold;\n    color: #333;\n    display: block;\n    margin-bottom: 8px;\n}\n\nselect#gastronomia-filter {\n    margin-bottom: 15px;\n    width: 100%;\n    max-width: 300px;\n    padding: 12px 15px;\n    font-size: 16px;\n    font-family: 'Arial', sans-serif;\n    color: #333;\n    background-color: #fff;\n    border-radius: 8px;\n    border: 1px solid #ccc;\n    cursor: pointer;\n    transition: all 0.3s ease;\n    box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);\n    overflow-y: auto;\n    max-height: 200px;\n}\n\nselect#gastronomia-filter option {\n    font-size: 16px;\n    padding: 10px;\n    background-color: #fff;\n    color: #333;\n}\n\nselect#gastronomia-filter:focus {\n    outline: none;\n    border-color: #F8B233;\n    box-shadow: 0 0 5px rgba(248, 178, 51, 0.5);\n}\n\n@media (max-width: 600px) {\n    select#gastronomia-filter {\n        width: 100%;\n        font-size: 21px;\n        padding: 25px;\n    }\n}\n<\/style>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-81747f5 e-con-full e-flex e-con e-child\" data-id=\"81747f5\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-249fa41 elementor-widget elementor-widget-html\" data-id=\"249fa41\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<div id=\"map\" style=\"width: 100%; height: 85vh; margin-top: 0px;\"><\/div>\n<p id=\"location-error\" style=\"color: red; display: none;\">No se pudo obtener tu ubicaci\u00f3n.<\/p>\n\n<script>\n    \/\/ Variables globales\n    let map;\n    let markers = [];\n    let restaurantsData = [];\n    let userLocation = null;\n    let userMarker = null;\n    let pulseDiv = null; \/\/ Elemento para la onda pulsante\n    let openInfoWindow = null;\n\n    \/\/ Funci\u00f3n para inicializar el mapa\n    async function initMap() {\n        const center = { lat: 39.578078, lng: 2.651597 }; \/\/ Palma de Mallorca\n\n        \/\/ Estilo personalizado del mapa\n        const mapStyles = [\n            { featureType: \"poi\", stylers: [{ visibility: \"off\" }] },\n            { featureType: \"transit\", stylers: [{ visibility: \"off\" }] },\n            { featureType: \"road\", elementType: \"labels\", stylers: [{ visibility: \"off\" }] }\n        ];\n\n        \/\/ Crear el mapa\n        map = new google.maps.Map(document.getElementById(\"map\"), {\n            zoom: 13,\n            center: center,\n            zoomControl: true,\n            streetViewControl: false,    \/\/ \u274c oculta el icono del \"mu\u00f1equito\"\n  fullscreenControl: false,    \/\/ \u274c oculta el bot\u00f3n de pantalla completa\n  \n            styles: mapStyles\n        });\n\n        \/\/ Intentar obtener la ubicaci\u00f3n del usuario\n        if (navigator.geolocation) {\n            navigator.geolocation.getCurrentPosition(\n                (position) => {\n                    userLocation = {\n                        lat: position.coords.latitude,\n                        lng: position.coords.longitude\n                    };\n\n                    setUserLocation(userLocation); \/\/ Marcar ubicaci\u00f3n del usuario\n                    loadRestaurants(); \/\/ Cargar restaurantes despu\u00e9s de obtener ubicaci\u00f3n\n                },\n                (error) => {\n                    document.getElementById(\"location-error\").style.display = \"block\";\n                    console.error(\"Error obteniendo ubicaci\u00f3n:\", error.message);\n                    loadRestaurants(); \/\/ Cargar restaurantes aunque no haya ubicaci\u00f3n\n                }\n            );\n        } else {\n            document.getElementById(\"location-error\").style.display = \"block\";\n            loadRestaurants();\n        }\n    }\n\n    \/\/ Funci\u00f3n para agregar el marcador del usuario con efecto pulsante\n    function setUserLocation(location) {\n        if (!map) return;\n\n        \/\/ A\u00f1adir marcador del usuario\n        userMarker = new google.maps.Marker({\n            position: location,\n            map: map,\n            title: \"Tu ubicaci\u00f3n\",\n            icon: {\n                url: \"https:\/\/tastemallorca.es\/wp-content\/uploads\/2024\/12\/user-location.png\",\n                scaledSize: new google.maps.Size(40, 40)\n            }\n        });\n\n        \/\/ Crear onda pulsante\n        pulseDiv = document.createElement(\"div\");\n        pulseDiv.classList.add(\"pulse-wave\");\n\n        const overlay = new google.maps.OverlayView();\n        overlay.onAdd = function () {\n            const layer = this.getPanes().overlayMouseTarget;\n            layer.appendChild(pulseDiv);\n        };\n\n        overlay.draw = function () {\n            const projection = this.getProjection();\n            if (!projection) return;\n\n            const position = projection.fromLatLngToDivPixel(location);\n            pulseDiv.style.left = `${position.x - 25}px`;\n            pulseDiv.style.top = `${position.y - 25}px`;\n        };\n\n        overlay.setMap(map);\n\n        map.setCenter(location);\n    }\n\n    \/\/ Funci\u00f3n para cargar restaurantes y actualizar mapa y lista\n    async function loadRestaurants() {\n        const gastronomyFilter = document.getElementById(\"gastronomia-filter\");\n\n        try {\n            const response = await fetch(\"https:\/\/tastemallorca.es\/wp-json\/wp\/v2\/restaurante\/?per_page=100\");\n            const restaurantes = await response.json();\n\n            \/\/ Guardar datos originales para filtrar din\u00e1micamente\n            restaurantsData = restaurantes\n                .filter(r => r.acf && r.acf.ubicacion_exacta) \/\/ Validar que tenga ubicaci\u00f3n\n                .map(r => ({\n                    id: r.id,\n                    nombre: r.title.rendered,\n                    direccion: r.acf.ubicacion_exacta.address || \"Direcci\u00f3n no disponible\",\n                    lat: parseFloat(r.acf.ubicacion_exacta.lat),\n                    lng: parseFloat(r.acf.ubicacion_exacta.lng),\n                    logo: r.acf.Logo?.url || 'https:\/\/tastemallorca.es\/wp-content\/uploads\/2024\/12\/Recurso-4ICON.svg',\n                    url: r.link || '#',\n                    gastronomia_ids: r.gastronomia || []\n                }));\n\n            \/\/ Actualizar el mapa y la lista cuando se cambia el selector\n            gastronomyFilter.addEventListener(\"change\", () => {\n                updateRestaurantsOnMap(gastronomyFilter.value);\n            });\n\n            updateRestaurantsOnMap(\"all\"); \/\/ Cargar todos por defecto\n        } catch (error) {\n            console.error(\"Error cargando restaurantes:\", error);\n        }\n    }\n\n    \/\/ Funci\u00f3n para actualizar el mapa y la lista con los restaurantes filtrados\n    function updateRestaurantsOnMap(filterId) {\n    \/\/ Limpiar marcadores previos\n    markers.forEach(marker => marker.setMap(null));\n    markers = [];\n\n    const filteredRestaurants = filterId === \"all\"\n        ? restaurantsData\n        : restaurantsData.filter(r => r.gastronomia_ids.includes(parseInt(filterId)));\n\n    \/\/ Calcular distancia si tenemos ubicaci\u00f3n del usuario\n    filteredRestaurants.forEach(restaurante => {\n        let distancia = 'No disponible';\n        if (userLocation) {\n            distancia = calculateDistance(userLocation.lat, userLocation.lng, restaurante.lat, restaurante.lng).toFixed(2) + ' km';\n        }\n\n        const marker = new google.maps.Marker({\n            position: { lat: restaurante.lat, lng: restaurante.lng },\n            map: map,\n            title: restaurante.nombre,\n            icon: {\n                url: \"https:\/\/tastemallorca.es\/wp-content\/uploads\/2024\/12\/iconrestauratnte.png\"\n            }\n        });\n\n        \/\/ Crear ventana de informaci\u00f3n\n        const infowindow = new google.maps.InfoWindow({\n            content: `\n                <div style=\"text-align: left; min-width: 200px; max-width: 300px; padding: 10px; font-family: Arial, sans-serif;\">\n                    <div style=\"display: flex; align-items: center; margin-bottom: 10px;\">\n                        <div style=\"width: 50px; height: 50px; background-image: url('${restaurante.logo}'); background-size: cover; background-position: center; border-radius: 50%; margin-right: 10px;\"><\/div>\n                        <div style=\"align-content:left;\">\n                            <h3 style=\"margin: 0; font-size: 18px;\">${restaurante.nombre}<\/h3>\n                            <p style=\"margin: 5px 0 0; font-size: 18px; color: #888; text-align:center;\">${distancia}<\/p>\n                        <\/div>\n                    <\/div>\n                    <a href=\"${restaurante.url}\" target=\"_blank\" style=\"display: block; width: 100%; text-align: center; padding: 10px 20px; background-color: #F8B233; color: white; font-weight: bold; text-decoration: none; border-radius: 5px; margin-bottom: 10px;\">Ver Restaurante<\/a>\n                    <a href=\"https:\/\/www.google.com\/maps\/search\/?api=1&query=${encodeURIComponent(restaurante.direccion)}\" target=\"_blank\" style=\"display: block; width: 100%; text-align: center; padding: 10px 20px; background-color: #4285F4; color: white; font-weight: bold; text-decoration: none; border-radius: 5px;\">Abrir en Google Maps<\/a>\n                <\/div>\n            `\n        });\n\n        \/\/ Mostrar infowindow al hacer clic\n        marker.addListener(\"click\", () => {\n            \/\/ Cerrar la InfoWindow abierta previamente, si existe\n            if (openInfoWindow) {\n                openInfoWindow.close();\n            }\n\n            \/\/ Abrir la nueva InfoWindow\n            infowindow.open(map, marker);\n            openInfoWindow = infowindow;\n        });\n\n        markers.push(marker);\n    });\n\n    \/\/ Si hay restaurantes, centrar el mapa en el primero\n   \/\/ if (filteredRestaurants.length > 0) {\n   \/\/     map.setCenter({ lat: filteredRestaurants[0].lat, lng: \/\/filteredRestaurants[0].lng });\n   \/\/ }\n}\n\n<\/script>\n\n<!-- Cargar Google Maps -->\n<script async defer src=\"https:\/\/maps.googleapis.com\/maps\/api\/js?key=AIzaSyBB6JG_AmOChcyDJ5KX0r8vlkwVHp1gjp8&callback=initMap\"><\/script>\n\n<style>\n\/* Efecto de onda pulsante *\/\n.pulse-wave {\n    position: absolute;\n    width: 50px;\n    height: 50px;\n    background: rgba(66, 133, 244, 0.4);\n    border-radius: 50%;\n    animation: pulse 3s infinite;\n}\n\n@keyframes pulse {\n    0% {\n        transform: scale(0.3);\n        opacity: 0.7;\n    }\n    100% {\n        transform: scale(2);\n        opacity: 0;\n    }\n}\n<\/style>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Cerca de t\u00ed: \u00bfQu\u00e9 quieres comer? Elige que te apetece&#8230; No se pudo obtener tu ubicaci\u00f3n. Cargando restaurantes&#8230; No se pudo obtener tu ubicaci\u00f3n.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_acf_changed":false,"pmpro_default_level":"","footnotes":""},"class_list":["post-11356","page","type-page","status-publish","hentry","pmpro-has-access"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/tastemallorca.es\/en\/wp-json\/wp\/v2\/pages\/11356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tastemallorca.es\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/tastemallorca.es\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/tastemallorca.es\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tastemallorca.es\/en\/wp-json\/wp\/v2\/comments?post=11356"}],"version-history":[{"count":0,"href":"https:\/\/tastemallorca.es\/en\/wp-json\/wp\/v2\/pages\/11356\/revisions"}],"wp:attachment":[{"href":"https:\/\/tastemallorca.es\/en\/wp-json\/wp\/v2\/media?parent=11356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}