TFO.html 36 KB

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