


{"id":83,"date":"2025-03-07T13:14:04","date_gmt":"2025-03-07T12:14:04","guid":{"rendered":"https:\/\/www.educasede.com\/app\/?page_id=83"},"modified":"2025-05-11T09:47:17","modified_gmt":"2025-05-11T08:47:17","slug":"externo","status":"publish","type":"page","link":"https:\/\/www.educasede.com\/app\/externo\/","title":{"rendered":"Externo"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n    <form id=\"registro-form\" class=\"pure-form pure-form-stacked\">\n        <fieldset>\n        <div style=\"display: flex; flex-direction: column; align-items: center; text-align: center;\">\n    <label for=\"dni\">Introduce tu c\u00f3digo:<\/label>\n    <small style=\"color: gray; display: block; margin-top: 2px;\">DNI sin la letra<\/small>\n<input\n  type=\"text\"\n  name=\"dni\"\n  id=\"dni\"\n  inputmode=\"numeric\"\n  pattern=\"[0-9]{6,8}\"\n  minlength=\"6\"\n  maxlength=\"8\"\n  required\n  style=\"width: 200px; text-align: center;\"\n  placeholder=\"6-8 d\u00edgitos\"\n\/>\n\n    <!-- Enlace para limpiar -->\n    <span id=\"limpiarDni\" \n          style=\"color: #aaa; font-size: 12px; margin-top: 5px; cursor: pointer; text-decoration: underline;\">\n        Limpiar\n    <\/span>\n<\/div>\n\n\n            <br>\n<div style=\"display: flex; justify-content: center; gap: 20px; margin-top: 10px;\">\n    <!-- Bot\u00f3n de Entrada (Principal) -->\n    <button type=\"button\" id=\"btnEntrada\" class=\"pure-button pure-button-primary\"\n            style=\"font-size: 20px; padding: 15px 40px; width: 180px; height: 60px;\">\n        Entrada\n    <\/button>\n\n    <!-- Bot\u00f3n de Salida (Peligro) -->\n    <button type=\"button\" id=\"btnSalida\" class=\"pure-button pure-button-danger\"\n            style=\"font-size: 20px; padding: 15px 40px; width: 180px; height: 60px;\">\n        Salida\n    <\/button>\n<\/div>\n\n            <br>\n            <div style=\"display: flex; gap: 10px; justify-content: center; align-items: center;\">\n               \n                <div style=\"display: flex; gap: 20px; justify-content: center;\">\n                <br>\n    <div style=\"display: flex; flex-direction: column; align-items: center; text-align: center;\">\n <br>\n        <label for=\"latitud\">Latitud:<\/label>\n        <input type=\"text\" name=\"latitud\" id=\"latitud\" readonly required style=\"text-align: center; width: 170px;\">\n    <\/div>\n    <div style=\"display: flex; flex-direction: column; align-items: center; text-align: center;\">\n    <br>\n        <label for=\"longitud\">Longitud:<\/label>\n        <input type=\"text\" name=\"longitud\" id=\"longitud\" readonly required style=\"text-align: center; width: 170px;\">\n    <\/div>\n<\/div>\n\n            <\/div>\n\n            <br>\n\n            \n        <\/fieldset>\n    <\/form>\n\n    <p id=\"mensaje\"><\/p>\n\n    <div id=\"ubicacion-error\" style=\"display: none; text-align: center; margin-top: 10px;\">\n    <p style=\"color: red;\">\n        <img decoding=\"async\" src=\"https:\/\/cdn-icons-png.flaticon.com\/512\/61\/61183.png\" alt=\"Ubicaci\u00f3n bloqueada\" width=\"20\" style=\"vertical-align: middle; margin-right: 5px;\">\n        La ubicaci\u00f3n est\u00e1 bloqueada. Por favor, act\u00edvala para registrar tu entrada o salida.\n    <\/p>\n    <button id=\"retryUbicacion\" class=\"pure-button pure-button-secondary\">Intentar otra vez<\/button>\n<\/div>\n\n\n    <script>\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n    obtenerUbicacion();\n\n    document.getElementById(\"btnEntrada\").addEventListener(\"click\", function() {\n        validarRegistro(\"entrada\");\n    });\n\n    document.getElementById(\"btnSalida\").addEventListener(\"click\", function() {\n        validarRegistro(\"salida\");\n    });\n\n        \/\/ Bot\u00f3n \"Limpiar\" debajo del DNI\n    document.getElementById(\"limpiarDni\").addEventListener(\"click\", function() {\n        document.getElementById(\"dni\").value = \"\";\n        document.getElementById(\"dni\").focus();\n        document.getElementById(\"mensaje\").innerHTML = \"\"; \/\/ opcional, limpia mensajes\n    });\n\n\n                    function obtenerUbicacion() {\n                        \/\/ Limpiamos campos por si quedaron valores anteriores\n                        document.getElementById('latitud').value = \"\";\n                        document.getElementById('longitud').value = \"\";\n\n                        if (navigator.geolocation) {\n                            navigator.geolocation.getCurrentPosition(\n                                function (position) {\n                                    document.getElementById('latitud').value = position.coords.latitude.toFixed(8);\n                                    document.getElementById('longitud').value = position.coords.longitude.toFixed(8);\n                                    document.getElementById('ubicacion-error').style.display = \"none\";\n                                },\n                                function (error) {\n                                    console.warn(\"Error de geolocalizaci\u00f3n:\", error.message);\n                                    \n                                    let mensajeError = \"Error al obtener la ubicaci\u00f3n.\";\n\n                                    switch (error.code) {\n                                        case error.PERMISSION_DENIED:\n                                            mensajeError = \"Has bloqueado la ubicaci\u00f3n. Si quieres activar el fichaje, ve a la configuraci\u00f3n del navegador y permite el acceso.\";\n                                            break;\n                                        case error.POSITION_UNAVAILABLE:\n                                            mensajeError = \"La ubicaci\u00f3n no est\u00e1 disponible.\";\n                                            break;\n                                        case error.TIMEOUT:\n                                            mensajeError = \"Tiempo de espera excedido al intentar obtener la ubicaci\u00f3n.\";\n                                            break;\n                                    }\n\n                                    document.getElementById('ubicacion-error').style.display = \"block\";\n                                    document.getElementById('ubicacion-error').querySelector('p').innerHTML = `\n                                        <img decoding=\"async\" src=\"https:\/\/cdn-icons-png.flaticon.com\/512\/61\/61183.png\" alt=\"Ubicaci\u00f3n bloqueada\" width=\"20\" style=\"vertical-align: middle; margin-right: 5px;\">\n                                        ${mensajeError}\n                                    `;\n                                }\n                            );\n                        } else {\n                            alert(\"La geolocalizaci\u00f3n no est\u00e1 soportada en este navegador.\");\n                        }\n                    }\n\n\n\n\n    function validarRegistro(tipo) {\n        let dni = document.getElementById(\"dni\").value.trim();\n        if (!dni) {\ndocument.getElementById(\"mensaje\").innerHTML = '<p style=\"color: red; background:#ffecec; border:2px solid red; padding:10px; font-size:18px; font-weight:bold; text-align:center;\">\u26a0\ufe0f Error inesperado en el servidor.<\/p>';\n    return;\n}\n\n\n        fetch('https:\/\/www.educasede.com\/app\/wp-admin\/admin-ajax.php', {\n            method: 'POST',\n            headers: { 'Content-Type': 'application\/x-www-form-urlencoded' },\n            body: `action=validar_fichaje&dni=${dni}&tipo=${tipo}`\n        })\n        .then(response => response.json())\n.then(data => {\n    \/\/ Soporta tanto {mensaje,...} como {success:true, data:{mensaje,...}}\n    const payload = (data && data.data) ? data.data : data;\n\n    const msg = (payload && payload.mensaje) ? payload.mensaje : '';\n    document.getElementById(\"mensaje\").innerHTML = msg;\n\n    if (payload && payload.registro_permitido) {\n        registrar(tipo);\n    }\n})\n\n        .catch(error => {\n            console.error(\"Error al procesar la respuesta JSON:\", error);\n            document.getElementById(\"mensaje\").innerHTML = \"<p style='color: red; text-align: center;'>Error inesperado en el servidor.<\/p>\";\n        });\n    }\n\n    function registrar(tipo) {\n        let dni = document.getElementById(\"dni\").value.trim();\n        let latitud = document.getElementById(\"latitud\").value;\n        let longitud = document.getElementById(\"longitud\").value;\n\n       if (!latitud || !longitud) {\n    const continuar = confirm(\n        \"\u26a0\ufe0f Est\u00e1s a punto de fichar sin geolocalizaci\u00f3n.\\n\\n\" +\n        \"Si esto es un error, revisa los permisos del navegador:\\n\\n\" +\n        \"\ud83d\udd39 Chrome: haz clic en el icono del candado (\ud83d\udd12) junto a la URL y permite la ubicaci\u00f3n.\\n\" +\n        \"\ud83d\udd39 Firefox: Ajustes > Privacidad y Seguridad > Permisos > Ubicaci\u00f3n.\\n\" +\n        \"\ud83d\udd39 Safari: Preferencias > Seguridad > Permitir servicios de localizaci\u00f3n.\\n\\n\" +\n        \"\u00bfQuieres continuar de todas formas?\"\n    );\n\n    if (!continuar) {\n        return; \/\/ el usuario cancel\u00f3\n    }\n}\n\n\n\n\n        fetch('https:\/\/www.educasede.com\/app\/wp-admin\/admin-ajax.php', {\n            method: 'POST',\n            headers: { 'Content-Type': 'application\/x-www-form-urlencoded' },\n            body: `action=registrar_fichaje&dni=${dni}&tipo=${tipo}&latitud=${latitud}&longitud=${longitud}`\n        })\n        .then(response => response.json())\n.then(data => {\n    const payload = (data && data.data) ? data.data : data;\n    const msg = (payload && payload.mensaje) ? payload.mensaje : '';\n    document.getElementById(\"mensaje\").innerHTML = msg;\n\n    document.getElementById(\"dni\").value = \"\";\n    setTimeout(() => { location.reload(); }, 1500);\n})\n\n        .catch(error => {\n            console.error(\"Error en registro de fichaje:\", error);\ndocument.getElementById(\"mensaje\").innerHTML = '<p style=\"color: red; background:#ffecec; border:2px solid red; padding:10px; font-size:18px; font-weight:bold; text-align:center;\">\u274c Error al registrar el fichaje.<\/p>';\n        });\n    }\n});\n\n\n\n\n\/\/\/\/\/\/\/\/\/\/\/COMPROBAR SI TIENE INSTALADO AL APP\n\n\n\/\/ Bot\u00f3n flotante para instalar la app (solo en \/externo y si es instalable)\nlet deferredPrompt;\n\nwindow.addEventListener('beforeinstallprompt', (e) => {\n    const enExterno = window.location.pathname.includes('\/externo');\n    if (!enExterno) return;\n\n    e.preventDefault();\n    deferredPrompt = e;\n\n    const installBtn = document.createElement('button');\n    installBtn.innerText = '\ud83d\udcf2 Instalar App';\n    installBtn.style.position = 'fixed';\n    installBtn.style.bottom = '20px';\n    installBtn.style.right = '20px';\n    installBtn.style.zIndex = '10000';\n    installBtn.style.padding = '12px 20px';\n    installBtn.style.background = '#0073aa';\n    installBtn.style.color = '#fff';\n    installBtn.style.border = 'none';\n    installBtn.style.borderRadius = '5px';\n    installBtn.style.boxShadow = '0 2px 6px rgba(0,0,0,0.2)';\n    installBtn.style.cursor = 'pointer';\n    installBtn.style.fontSize = '16px';\n\n    document.body.appendChild(installBtn);\n\n    installBtn.addEventListener('click', () => {\n        installBtn.remove();\n        deferredPrompt.prompt();\n\n        deferredPrompt.userChoice.then((choiceResult) => {\n            if (choiceResult.outcome === 'accepted') {\n                console.log('\u2705 Usuario acept\u00f3 la instalaci\u00f3n');\n            } else {\n                console.log('\u274c Usuario rechaz\u00f3 la instalaci\u00f3n');\n            }\n            deferredPrompt = null;\n        });\n    });\n});\n\n\n\n\n<\/script>\n\n\n    <style>\n        .pure-button-secondary {\n            background: #555;\n            color: white;\n        }\n        input[readonly] {\n            background: #f4f4f4;\n            border: 1px solid #ccc;\n        }\n        div > input {\n            width: 120px;\n        }\n    <\/style>\n\n    \n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"canvas","meta":{"footnotes":""},"class_list":["post-83","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.educasede.com\/app\/wp-json\/wp\/v2\/pages\/83","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.educasede.com\/app\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.educasede.com\/app\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.educasede.com\/app\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.educasede.com\/app\/wp-json\/wp\/v2\/comments?post=83"}],"version-history":[{"count":4,"href":"https:\/\/www.educasede.com\/app\/wp-json\/wp\/v2\/pages\/83\/revisions"}],"predecessor-version":[{"id":175,"href":"https:\/\/www.educasede.com\/app\/wp-json\/wp\/v2\/pages\/83\/revisions\/175"}],"wp:attachment":[{"href":"https:\/\/www.educasede.com\/app\/wp-json\/wp\/v2\/media?parent=83"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}