TFO.html 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. <!DOCTYPE html>
  2. <html lang="it">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Mappa con Bootstrap Italia e Overlay Edifici</title>
  7. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
  8. integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg=="
  9. crossorigin="anonymous" referrerpolicy="no-referrer" />
  10. <link href="https://cdn.jsdelivr.net/npm/bootstrap-italia@2.13.4/dist/css/bootstrap-italia.min.css" rel="stylesheet">
  11. <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
  12. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css" />
  13. <style>
  14. /* Stile per la riga blu scuro */
  15. .top-bar {
  16. background-color: #004080; /* Blu scuro */
  17. color: white;
  18. padding: 0.5rem 0;
  19. text-align: left; /* Allineamento a sinistra */
  20. font-size: 0.9rem;
  21. }
  22. .table-responsive {
  23. overflow-x: auto;
  24. /* Aggiungi scroll orizzontale se la tabella è troppo larga */
  25. }
  26. .header, .footer {
  27. background-color: #0066CC; /* Blu istituzionale */
  28. color: white;
  29. padding: 1rem 0;
  30. }
  31. .main-content {
  32. background-color: #f8f9fa; /* Grigio chiaro */
  33. padding: 2rem 0;
  34. }
  35. /* Stile per il logo "PW" dentro un cerchio */
  36. .logo {
  37. font-family: 'Georgia', serif;
  38. font-size: 1.5rem;
  39. width: 50px; height: 50px;
  40. background-color: white;
  41. color: #0066CC;
  42. border-radius: 50%;
  43. margin-right: 10px;
  44. display: inline-flex;
  45. align-items: center;
  46. justify-content: center;
  47. }
  48. #map { height: 500px; width: 100%; }
  49. #coordinate-inputs { margin-top: 10px; width: 50%; }
  50. /* Stile per i link con sottolineatura solo al passaggio del mouse */
  51. .link-underline-hover {
  52. text-decoration: none; /* Rimuove la sottolineatura di base */
  53. }
  54. .link-underline-hover:hover {
  55. text-decoration: underline; /* Aggiunge la sottolineatura solo al passaggio del mouse */
  56. }
  57. /* Aggiusta l'allineamento del logo e titolo */
  58. .header-title {
  59. font-size: 1.5rem;
  60. display: inline-block;
  61. margin-left: 10px;
  62. }
  63. .header-content {
  64. display: flex;
  65. align-items: center;
  66. }
  67. /* Stili per la tabella dei dati */
  68. .data-table {
  69. display: flex;
  70. flex-direction: column;
  71. }
  72. .table th, .table td {
  73. font-size: 16px; /* Riduce la dimensione del testo */
  74. }
  75. h2 {
  76. font-size: 22px; /* Riduce la dimensione della scritta "Dati Inseriti" */
  77. }
  78. .d-flex {
  79. display: flex;
  80. }
  81. .justify-content-end {
  82. justify-content: flex-end;
  83. }
  84. .mt-2 {
  85. margin-top: 0.5rem;
  86. }
  87. .mt-3 {
  88. margin-top: 1rem;
  89. }
  90. .social-icons a {
  91. color: white;
  92. font-size: 24px;
  93. margin-right: 10px;
  94. }
  95. </style>
  96. </head>
  97. <body>
  98. <!-- Riga blu scuro con scritto "Project Work" allineata a sinistra -->
  99. <div class="top-bar">
  100. <div class="container">
  101. Project Work
  102. </div>
  103. </div>
  104. <header class="header">
  105. <div class="container">
  106. <div class="row align-items-center">
  107. <div class="col">
  108. <!-- Logo "PW" dentro un cerchio e titolo accanto -->
  109. <div class="col d-flex">
  110. <!-- Logo "PW" dentro un cerchio, ora cliccabile -->
  111. <a href="/callback" class="logo-link">
  112. <div class="logo">PW</div>
  113. </a>
  114. <h1 class="header-title">TFO - Terminazioni Fibra Ottica</h1>
  115. </div>
  116. </div>
  117. <div class="col-auto d-flex align-items-center">
  118. <a href="/admin" class="text-white me-3 link-underline-hover">Gestione Dati Immobiliari</a>
  119. <a href="/tfo" class="text-white me-3 link-underline-hover">TFO</a>
  120. <a href="/buildings" class="text-white me-3 link-underline-hover">Registrazione degli Edifici</a>
  121. <a href="/mappa_login" class="btn btn-light">Logout</a>
  122. </div>
  123. </div>
  124. </div>
  125. </header>
  126. <main>
  127. <div class="container mt-4">
  128. <h1 style="font-size: 1.5rem;">Registrazione delle terminazioni di fibra ottica</h1>
  129. <!-- Barra di ricerca -->
  130. <div class="row">
  131. <div class="col-md-9">
  132. <div class="mb-3">
  133. <label for="addressInput" class="form-label">Indirizzo:</label>
  134. <input type="text" class="form-control" id="addressInput">
  135. </div>
  136. </div>
  137. <div class="col-md-3">
  138. <button type="button" class="btn btn-primary mt-4" id="searchButton">Cerca</button>
  139. </div>
  140. </div>
  141. <div class="main-content">
  142. <div class="container">
  143. <div class="row justify-content-center">
  144. <div class="col-md-12">
  145. <div id="map"></div>
  146. </div>
  147. </div>
  148. </div>
  149. </div>
  150. <p class="mt-4">Compila il modulo sottostante per registrare una nuova terminazione di fibra ottica:</p>
  151. <fo class="container-fluid">
  152. <div class="row justify-content-center">
  153. <div class="col-md-12">
  154. <div class="card">
  155. <div class="card-body">
  156. <div class="row">
  157. <div class="col-md-9">
  158. <div class="mb-3">
  159. <label for="addressInputForm" class="form-label">Indirizzo:</label>
  160. <input type="text" class="form-control" id="addressInputForm">
  161. </div>
  162. </div>
  163. </div>
  164. <div class="col-md-9">
  165. <div class="mb-3">
  166. <label for="latInput" class="form-label">Latitudine:</label>
  167. <input type="number" class="form-control" id="latInput" min="-90" max="90"/>
  168. </div>
  169. </div>
  170. <div class="col-md-9">
  171. <div class="ms-md-6 mb-3">
  172. <label for="lngInput" class="form-label">Longitudine:</label>
  173. <input type="number" class="form-control" id="lngInput" min="-180" max="180"/>
  174. </div>
  175. </div>
  176. <div class="col-md-9">
  177. <div class="ms-md-6 mb-3">
  178. <label for="codiceCatastaleInput" class="form-label">Codice Catastale:</label>
  179. <input type="text" class="form-control" id="codiceCatastaleInput">
  180. </div>
  181. </div>
  182. <div class="col-md-9">
  183. <div class="mb-3">
  184. <label for="dataPredisposizione" class="form-label">Data Predisposizione</label>
  185. <input type="date" class="form-control" id="dataPredisposizione">
  186. </div>
  187. </div>
  188. <div class="col-md-9">
  189. <div class="mb-3">
  190. <label for="scala" class="form-label">Scala</label>
  191. <input type="text" class="form-control" id="scala">
  192. </div>
  193. </div>
  194. <div class="col-md-9">
  195. <div class="mb-3">
  196. <label for="piano" class="form-label">Piano</label>
  197. <input type="text" class="form-control" id="piano">
  198. </div>
  199. </div>
  200. <div class="col-md-9">
  201. <div class="mb-3">
  202. <label for="interno" class="form-label">Interno</label>
  203. <input type="text" class="form-control" id="interno">
  204. </div>
  205. </div>
  206. </div>
  207. <div class="row">
  208. <div class="col-md-9">
  209. <div class="mb-3">
  210. <label for="operatore" class="form-label">Identificativo Operatore</label>
  211. <select class="form-select" id="operatore">
  212. <option value="1">Operatore 1</option>
  213. <option value="2">Operatore 2</option>
  214. </select>
  215. </div>
  216. </div>
  217. <div class="col-md-9">
  218. <div class="mb-3">
  219. <label for="terminazione" class="form-label">Codice Terminazione</label>
  220. <input type="text" class="form-control" id="terminazione">
  221. </div>
  222. </div>
  223. <div class="col-md-9">
  224. <div class="mb-3">
  225. <label for="nota" class="form-label">Note</label>
  226. <input type="text" class="form-control" id="nota">
  227. </div>
  228. </div>
  229. </div>
  230. <div class="row">
  231. <div class="col-md-2">
  232. <button class="btn btn-primary w-100" onclick="aggiungiRiga()">Aggiungi</button>
  233. </div>
  234. <div class="col-md-2">
  235. <button class="btn btn-secondary w-100" type="button" onclick="resettaForm()">Annulla</button>
  236. </div>
  237. </div>
  238. </div>
  239. </div>
  240. </div>
  241. <div class="col-md-12 mt-4">
  242. <div class="data-table">
  243. <h2>Dati Inseriti</h2>
  244. <div class="table-responsive">
  245. <table class="table">
  246. <thead>
  247. <tr>
  248. <th>Indirizzo</th>
  249. <th>Latitudine</th>
  250. <th>Longitudine</th>
  251. <th>Codice Catastale</th>
  252. <th>Data Predisposizione</th>
  253. <th>Scala</th>
  254. <th>Piano</th>
  255. <th>Interno</th>
  256. <th>Operatore</th>
  257. <th>Terminazione</th>
  258. <th>Note</th>
  259. <th>Azioni</th>
  260. </tr>
  261. </thead>
  262. <tbody id="buildingTableBody">
  263. <!-- Le righe della tabella saranno aggiunte dinamicamente -->
  264. </tbody>
  265. </table>
  266. </div>
  267. <!-- Contenitore per il pulsante "Invia" -->
  268. <div class="d-flex justify-content-end mt-3">
  269. <button class="btn btn-success">Invia</button>
  270. </div>
  271. </div>
  272. </div>
  273. </div>
  274. </div>
  275. </div>
  276. <!-- Widget ElevenLabs ConvAI -->
  277. <elevenlabs-convai agent-id="GlBWa9xJ6GdD7bAve6Yq"></elevenlabs-convai>
  278. <script src="https://elevenlabs.io/convai-widget/index.js" async type="text/javascript"></script>
  279. </main>
  280. <script>
  281. document.addEventListener('DOMContentLoaded', function() {
  282. // Ottieni l'URL corrente
  283. const urlParams = new URLSearchParams(window.location.search);
  284. // Estrai il token dal parametro di query "token"
  285. const ruolo = urlParams.get('ruolo');
  286. const codice_fiscale = urlParams.get('codice_fiscale');
  287. // Salva il token in localStorage
  288. if (ruolo && codice_fiscale) {
  289. localStorage.setItem('ruolo', ruolo);
  290. localStorage.setItem('codice_fiscale', codice_fiscale);
  291. // Rimuovi il token dall'URL per sicurezza (opzionale)
  292. window.history.replaceState({}, document.title, window.location.pathname);
  293. //window.location.href = window.location.pathname;
  294. //Puoi anche reindirizzare ad una pagina pulita.
  295. //window.location.href = '/altra-pagina';
  296. }
  297. });
  298. </script>
  299. <footer id="footer" class="it-footer bg-black mt-5" role="contentinfo">
  300. <div class="it-footer-main py-3">
  301. <div class="container">
  302. <section class="py-4">
  303. <div class="row">
  304. <div class="col-lg-3 col-md-3 col-sm-6 pb-2">
  305. <div class="link-list-wrapper">
  306. <h2 class="h5">Esplora SINFI</h2>
  307. <ul id="footer-menu-col-1" class="link-list">
  308. <li id="menu-item-sinfi-1" class="menu-item">
  309. <a class="list-item" href="https://sinfi.it/portal/sinfi-menu/che-cose/">Cos'è SINFI</a>
  310. </li>
  311. <li id="menu-item-sinfi-2" class="menu-item">
  312. <a class="list-item" href="https://sinfi.it/realms/master/protocol/openid-connect/auth?client_id=sinfi_user_service&response_type=code&redirect_uri=https://sinfi.it/sinfi_gateway/labs_keycloak/post_login/&scope=email&state=">Infrastrutture Registrate</a>
  313. </li>
  314. <li id="menu-item-sinfi-3" class="menu-item">
  315. <a class="list-item" href="https://sinfi.it/portal/sinfi-menu/riferimenti-normativi/">Normative di Riferimento</a>
  316. </li>
  317. <li id="menu-item-sinfi-4" class="menu-item">
  318. <a class="list-item" href="https://sinfi.it/realms/master/protocol/openid-connect/auth?client_id=sinfi_user_service&response_type=code&redirect_uri=https://sinfi.it/sinfi_gateway/labs_keycloak/post_login/&scope=email&state=">Open Data SINFI</a>
  319. </li>
  320. </ul>
  321. </div>
  322. </div>
  323. <div class="col-lg-3 col-md-3 col-sm-6 pb-2">
  324. <div class="link-list-wrapper">
  325. <h2 class="h5">Aiuto e Supporto</h2>
  326. <ul id="footer-menu-col-2" class="link-list">
  327. <li id="menu-item-aiuto-1" class="menu-item">
  328. <a class="list-item" href="/instructions">Istruzioni</a>
  329. </li>
  330. <li id="menu-item-aiuto-2" class="menu-item">
  331. <a class="list-item" href="/faq">FAQ - Domande Frequenti</a>
  332. </li>
  333. <li id="menu-item-aiuto-3" class="menu-item">
  334. <a class="list-item" href="/techsup">Segnalazioni e Supporto Tecnico</a>
  335. </li>
  336. </ul>
  337. </div>
  338. </div>
  339. <!-- Colonna "Community" con i loghi dei social -->
  340. <div class="col-lg-3 col-md-3 col-sm-6 pb-2">
  341. <div class="link-list-wrapper">
  342. <h2 class="h5">Community</h2>
  343. <div class="social-icons">
  344. <a href="https://www.linkedin.com" target="_blank" class="me-3"><i class="fab fa-linkedin"></i></a>
  345. <a href="https://www.youtube.com" target="_blank" class="me-3"><i class="fab fa-youtube"></i></a>
  346. <a href="https://www.facebook.com" target="_blank" class="me-3"><i class="fab fa-facebook"></i></a>
  347. <a href="https://www.instagram.com" target="_blank" class="me-3"><i class="fab fa-instagram"></i></a>
  348. </div>
  349. </div>
  350. </div>
  351. <div class="col-lg-3 col-md-3 col-sm-6 pb-2">
  352. <div class="link-list-wrapper">
  353. <h2 class="h5">SINFI</h2>
  354. <ul id="footer-menu-col-4" class="link-list">
  355. <li id="menu-item-377" class="menu-item">
  356. <a target="_blank" href="https://sinfi.it/portal/">Vai al sito ufficiale SINFI</a>
  357. </li>
  358. </ul>
  359. </div>
  360. </div>
  361. </div>
  362. </section>
  363. </div>
  364. </div>
  365. <div class="it-footer-small-prints clearfix">
  366. <div class="container">
  367. <nav class="menu-footer-menu-ita-container" aria-label="link utili">
  368. <ul id="menu-footer-menu-ita" class="it-footer-small-prints-list list-inline mb-0 d-flex flex-column flex-md-row">
  369. <li id="menu-item-413" class="menu-item list-inline-item"><a href="/media-policy/">Media Policy</a></li>
  370. <li id="menu-item-453" class="menu-item list-inline-item"><a href="/note-legali/">Privacy Policy &amp; Note Legali</a></li>
  371. <li id="menu-item-1310" class="menu-item list-inline-item"><a target="_blank" href="https://form.agid.gov.it/view/9df3de50-7a42-11ef-8989-9dcab5eaa914">Dichiarazione di accessibilità</a></li>
  372. <li id="menu-item-411" class="menu-item list-inline-item"><a href="/mappa-del-sito/">Mappa del sito</a></li>
  373. <li id="menu-item-1277" class="menu-item list-inline-item"><a href="/open-data-spid/">Open Data SPID</a></li>
  374. </ul>
  375. </nav>
  376. </div>
  377. </div>
  378. </footer>
  379. <!-- Scripts -->
  380. <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  381. <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
  382. <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
  383. <script src="https://cdn.jsdelivr.net/npm/bootstrap-italia@2.8.1/dist/js/bootstrap-italia.bundle.min.js"></script>
  384. <script>
  385. // Inizializzazione Mappa
  386. var map = L.map('map').setView([41.9028, 12.4964], 13);
  387. L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  388. attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  389. }).addTo(map);
  390. // Variabile per memorizzare il marker corrente
  391. let marker;
  392. var lastModifiedField = document.getElementById('addressInput');
  393. var buildings = [];
  394. var edificiLayer = L.layerGroup().addTo(map);
  395. var zoomLivello = 16;
  396. // Listener per il tasto Invio nel campo di ricerca
  397. document.getElementById('addressInput').addEventListener('keydown', function (event) {
  398. if (event.keyCode === 13) {
  399. event.preventDefault();
  400. document.getElementById('searchButton').click();
  401. }
  402. });
  403. document.getElementById('searchButton').addEventListener('click', function () {
  404. const address = document.getElementById('addressInput').value;
  405. if (address) {
  406. fetch(`https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(address)}&format=json`)
  407. .then(response => response.json())
  408. .then(data => {
  409. if (data && data.length > 0) {
  410. const lat = parseFloat(data[0].lat);
  411. const lon = parseFloat(data[0].lon);
  412. if (marker) {
  413. map.removeLayer(marker);
  414. }
  415. marker = L.marker([lat, lon]).addTo(map)
  416. .bindPopup(`Indirizzo: ${data[0].display_name}`)
  417. .openPopup();
  418. map.setView([lat, lon], 18);
  419. document.getElementById('latInput').value = lat;
  420. document.getElementById('lngInput').value = lon;
  421. // Copia l'indirizzo trovato nel campo sotto la mappa
  422. document.getElementById('addressInputForm').value = data[0].display_name;
  423. } else {
  424. alert('Indirizzo non trovato.');
  425. }
  426. })
  427. .catch(error => {
  428. console.error('Errore durante la geocodifica:', error);
  429. alert('Si è verificato un errore durante la ricerca dell\'indirizzo.');
  430. });
  431. } else {
  432. alert('Inserisci un indirizzo.');
  433. }
  434. });
  435. // Gestione del click sulla mappa
  436. map.on('click', function (e) {
  437. const lat = e.latlng.lat;
  438. const lng = e.latlng.lng;
  439. // Rimuovi il marker precedente (se esiste)
  440. if (marker) {
  441. map.removeLayer(marker);
  442. }
  443. // Aggiungi un nuovo marker sulla mappa
  444. marker = L.marker([lat, lng]).addTo(map)
  445. .bindPopup(`Coordinate: ${lat}, ${lng}`)
  446. .openPopup();
  447. // Riempie i campi di input per latitudine e longitudine
  448. document.getElementById('latInput').value = lat;
  449. document.getElementById('lngInput').value = lng;
  450. // Ottieni l'indirizzo dalle coordinate
  451. getAddress(lat, lng);
  452. });
  453. async function caricaEdifici() {
  454. if (map.getZoom() >= 16) {
  455. var bounds = map.getBounds();
  456. var bbox = bounds.getSouthWest().lat + ',' + bounds.getSouthWest().lng + ',' + bounds.getNorthEast().lat + ',' + bounds.getNorthEast().lng;
  457. var query = `
  458. [out:json];
  459. (
  460. way["building"](${bbox});
  461. relation["building"](${bbox});
  462. );
  463. out geom;
  464. out tags;
  465. `;
  466. try {
  467. const data = await $.ajax({
  468. url: 'https://overpass-api.de/api/interpreter',
  469. data: { data: query },
  470. dataType: 'json'
  471. });
  472. edificiLayer.clearLayers();
  473. data.elements.forEach(function(element) {
  474. if (element.type === 'way' && element.geometry) {
  475. var latlngs = element.geometry.map(function(coord) {
  476. return [coord.lat, coord.lon];
  477. });
  478. var polygon = L.polygon(latlngs).addTo(edificiLayer);
  479. // Genera un numero casuale tra 0 e 3
  480. var statoEdificio = true;
  481. // Assegna il colore in base allo stato
  482. var colorePoligono;
  483. switch (statoEdificio) {
  484. case false:
  485. colorePoligono = 'yellow';
  486. break;
  487. case true:
  488. colorePoligono = 'green';
  489. break;
  490. }
  491. // Applica lo stile al poligono
  492. polygon.setStyle({ fillColor: colorePoligono, color: colorePoligono });
  493. polygon.on('click', async function() {
  494. var buildingType = element.tags && element.tags.building ? element.tags.building : 'Sconosciuto';
  495. try {
  496. await getAddress(latlngs[0][0], latlngs[0][1]);
  497. var popupContent = 'Coordinate: ' + latlngs[0][0] + ', ' + latlngs[0][1] + '<br>' +
  498. 'Tipo edificio: ' + buildingType + '<br>' +
  499. 'Indirizzo: ' + document.getElementById('addressInput').value + '<br>' +
  500. 'Stato: ' + statoEdificio + '<br>' +
  501. 'Codice Catastale: nessuno';
  502. polygon.bindPopup(popupContent).openPopup();
  503. } catch (error) {
  504. console.error("Errore nel recupero dell'indirizzo:", error);
  505. var popupContent = 'Coordinate: ' + latlngs[0][0] + ', ' + latlngs[0][1] + '<br>' +
  506. 'Tipo edificio: ' + buildingType + '<br>' +
  507. 'Indirizzo: Indirizzo non disponibile<br>' +
  508. 'Stato: ' + statoEdificio + '<br>' +
  509. 'Codice Catastale: nessuno';
  510. polygon.bindPopup(popupContent).openPopup();
  511. }
  512. var codiceCatasto = element.tags && element.tags.codice_catasto ? element.tags.codice_catasto : "nessuno";
  513. document.getElementById('codiceCatastaleInput').value = codiceCatasto;
  514. });
  515. } else if (element.type === 'relation' && element.members) {
  516. // Gestione delle relazioni (edifici complessi)
  517. // Da implementare
  518. }
  519. });
  520. } catch (error) {
  521. console.error('Errore durante il caricamento degli edifici:', error);
  522. // Gestisci l'errore (ad esempio, mostra un messaggio all'utente)
  523. }
  524. } else {
  525. edificiLayer.clearLayers();
  526. }
  527. }
  528. // Funzione per ottenere l'indirizzo dalle coordinate
  529. async function getAddress(lat, lng) {
  530. try {
  531. const response = await fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lng}`);
  532. const data = await response.json();
  533. if (data.address) {
  534. const displayName = data.display_name;
  535. document.getElementById('addressInput').value = displayName;
  536. document.getElementById('addressInputForm').value = displayName; // Aggiorna anche il campo del form
  537. } else {
  538. document.getElementById('addressInput').value = "Indirizzo non trovato";
  539. document.getElementById('addressInputForm').value = "Indirizzo non trovato"; // Aggiorna anche il campo del form
  540. }
  541. } catch (error) {
  542. console.error("Errore nel geocoding inverso:", error);
  543. document.getElementById('addressInput').value = "Errore nel geocoding inverso";
  544. document.getElementById('addressInputForm').value = "Errore nel geocoding inverso"; // Aggiorna anche il campo del form
  545. }
  546. }
  547. async function prendiIndirizzo(lat, lng) {
  548. try {
  549. const response = await fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lng}`);
  550. const data = await response.json();
  551. if (data.address) {
  552. return data.display_name;
  553. } else {
  554. return "Indirizzo non trovato";
  555. }
  556. } catch (error) {
  557. console.error("Errore nel geocoding inverso:", error);
  558. return "Indirizzo non disponibile";
  559. }
  560. }
  561. function debounce(func, delay) {
  562. let timeoutId;
  563. return function(...args) {
  564. clearTimeout(timeoutId);
  565. timeoutId = setTimeout(() => {
  566. func.apply(this, args);
  567. }, delay);
  568. };
  569. }
  570. const debouncedCaricaEdifici = debounce(caricaEdifici, 300);
  571. // Gestione dell'input manuale delle coordinate
  572. document.getElementById('latInput').addEventListener('blur', function () {
  573. const lat = parseFloat(this.value);
  574. const lng = parseFloat(document.getElementById('lngInput').value);
  575. if (!isNaN(lat) && !isNaN(lng)) {
  576. map.setView([lat, lng], 16);
  577. if (marker) {
  578. map.removeLayer(marker);
  579. }
  580. marker = L.marker([lat, lng]).addTo(map)
  581. .bindPopup(`Coordinate: ${lat}, ${lng}`)
  582. .openPopup();
  583. getAddress(lat, lng);
  584. }
  585. });
  586. document.getElementById('lngInput').addEventListener('blur', function () {
  587. const lat = parseFloat(document.getElementById('latInput').value);
  588. const lng = parseFloat(this.value);
  589. if (!isNaN(lat) && !isNaN(lng)) {
  590. map.setView([lat, lng], 16);
  591. if (marker) {
  592. map.removeLayer(marker);
  593. }
  594. marker = L.marker([lat, lng]).addTo(map)
  595. .bindPopup(`Coordinate: ${lat}, ${lng}`)
  596. .openPopup();
  597. getAddress(lat, lng);
  598. }
  599. });
  600. // Funzione per aggiungere una riga alla tabella
  601. function aggiungiRiga() {
  602. const indirizzo = document.getElementById('addressInput').value;
  603. const latitudine = document.getElementById('latInput').value;
  604. const longitudine = document.getElementById('lngInput').value;
  605. const codiceCatastale = document.getElementById('codiceCatastaleInput').value;
  606. const dataPredisposizione = document.getElementById('dataPredisposizione').value;
  607. const scala = document.getElementById('scala').value;
  608. const piano = document.getElementById('piano').value;
  609. const interno = document.getElementById('interno').value;
  610. const operatore = document.getElementById('operatore').value;
  611. const terminazione = document.getElementById('terminazione').value;
  612. const nota = document.getElementById('nota').value;
  613. // Controllo se tutti i campi sono compilati
  614. if (!indirizzo || !latitudine || !longitudine || !dataPredisposizione ||
  615. !codiceCatastale || !scala || !piano || !interno || !operatore || !terminazione ) {
  616. alert("Compila tutti i campi prima di aggiungere la TFO!");
  617. return; // Blocca l'inserimento
  618. }
  619. // Crea una nuova riga nella tabella
  620. const tabella = document.querySelector(".table tbody");
  621. const nuovaRiga = tabella.insertRow();
  622. // Crea le celle della riga e inserisci i valori
  623. const celle = [];
  624. for (let i = 0; i < 11; i++) {
  625. celle.push(nuovaRiga.insertCell());
  626. }
  627. celle[0].textContent = indirizzo;
  628. celle[1].textContent = latitudine;
  629. celle[2].textContent = longitudine;
  630. celle[3].textContent = codiceCatastale;
  631. celle[4].textContent = dataPredisposizione;
  632. celle[5].textContent = scala;
  633. celle[6].textContent = piano;
  634. celle[7].textContent = interno;
  635. celle[8].textContent = operatore;
  636. celle[9].textContent = terminazione;
  637. celle[10].textContent = nota;
  638. // Aggiungi i pulsanti di modifica e cancellazione
  639. const azioniCell = nuovaRiga.insertCell();
  640. azioniCell.innerHTML = `
  641. <div class="d-flex gap-2">
  642. <button class="btn btn-sm btn-primary" onclick="modificaRiga(this)"><i class="fas fa-edit"></i></button>
  643. <button class="btn btn-sm btn-danger" onclick="cancellaDato(this)"><i class="fas fa-trash"></i></button>
  644. </div>
  645. `;
  646. // Resetta i campi del form dopo l'inserimento
  647. resettaForm();
  648. }
  649. // Funzione per modificare una riga
  650. function modificaRiga(button) {
  651. const riga = button.closest('tr'); // Trova la riga più vicina al pulsante
  652. const celle = riga.cells;
  653. // Popola i campi del form con i dati della riga
  654. document.getElementById("addressInput").value = celle[0].textContent;
  655. document.getElementById("latInput").value = celle[1].textContent;
  656. document.getElementById("lngInput").value = celle[2].textContent;
  657. document.getElementById("codiceCatastaleInput").value = celle[3].textContent;
  658. document.getElementById("dataPredisposizione").value = celle[4].textContent;
  659. document.getElementById("scala").value = celle[5].textContent;
  660. document.getElementById("piano").value = celle[6].textContent;
  661. document.getElementById("interno").value = celle[7].textContent;
  662. document.getElementById("operatore").value = celle[8].textContent;
  663. document.getElementById("terminazione").value = celle[9].textContent;
  664. document.getElementById("nota").value = celle[10].textContent;
  665. // Rimuovi la riga dalla tabella
  666. riga.remove();
  667. }
  668. // Funzione per cancellare una riga
  669. function cancellaDato(button) {
  670. // Chiedi conferma all'utente
  671. if (confirm("Sei sicuro di voler eliminare questo dato?")) {
  672. // L'utente ha confermato, procedi con l'eliminazione
  673. const riga = button.closest("tr");
  674. if (riga) {
  675. riga.remove();
  676. alert("Dato eliminato con successo.");
  677. }
  678. } else {
  679. // L'utente ha annullato l'eliminazione
  680. alert("Eliminazione annullata.");
  681. }
  682. }
  683. // Funzione per resettare il form
  684. function resettaForm() {
  685. document.getElementById('addressInputForm').value = '';
  686. document.getElementById('addressInput').value = '';
  687. document.getElementById('latInput').value = '';
  688. document.getElementById('lngInput').value = '';
  689. document.getElementById('codiceCatastaleInput').value = '';
  690. document.getElementById('dataPredisposizione').value = '';
  691. document.getElementById('scala').value = '';
  692. document.getElementById('piano').value = '';
  693. document.getElementById('interno').value = '';
  694. document.getElementById('operatore').value = '1';
  695. document.getElementById('terminazione').value = '';
  696. document.getElementById('nota').value = '';
  697. }
  698. // Aggiungi un listener per il movimento della mappa
  699. map.on('moveend', debouncedCaricaEdifici);
  700. // Carica gli edifici iniziali
  701. caricaEdifici();
  702. </script>
  703. </body>
  704. </html>