1// Variabili globali per parametri URL 2var idcorso, idescursione, biennio, idsocio, azione, keycorso, codiceEsito, esito, codTrans, descrizione; 3 4jQuery(document).ready(function () { 5 const switchEl = document.getElementById('themeSwitch'); 6 const body = document.body; 7 8 // Imposta il tema iniziale da localStorage o database 9 const savedTheme = localStorage.getItem('theme'); 10 if( savedTheme ) 11 { 12 if( switchEl ) 13 { 14 body.setAttribute('data-bs-theme', savedTheme); 15 switchEl.checked = savedTheme === 'dark'; 16 } 17 } 18 else 19 { 20 // Carica il tema dal database se non presente in localStorage 21 $.ajax({ 22 url: '/area_riservata/lib/api/api_interne.php?tipo_api=get_tema_utente', 23 type: 'POST', 24 success: function(response) { 25 if (response.success && response.tema) { 26 body.setAttribute('data-bs-theme', response.tema); 27 if( switchEl ) switchEl.checked = response.tema === 'dark'; 28 localStorage.setItem('theme', response.tema); 29 } else { 30 // Default a light se non trovato 31 body.setAttribute('data-bs-theme', 'light'); 32 if( switchEl ) switchEl.checked = false; 33 localStorage.setItem('theme', 'light'); 34 } 35 }, 36 error: function(xhr, status, error) { 37 console.error('Errore caricamento tema:', error); 38 // Default a light in caso di errore 39 body.setAttribute('data-bs-theme', 'light'); 40 if( switchEl ) switchEl.checked = false; 41 localStorage.setItem('theme', 'light'); 42 } 43 }); 44 } 45 46 if( switchEl ) 47 { 48 // Al cambio dello switch 49 switchEl.addEventListener('change', () => { 50 const theme = switchEl.checked ? 'dark' : 'light'; 51 body.setAttribute('data-bs-theme', theme); 52 localStorage.setItem('theme', theme); 53 54 // Salva il tema nel database 55 $.ajax({ 56 url: '/area_riservata/lib/api/api_interne.php?tipo_api=salva_tema', 57 type: 'POST', 58 data: { tema: theme }, 59 success: function(response) { 60 if (!response.success) { 61 console.error('Errore salvataggio tema:', response.message); 62 } 63 }, 64 error: function(xhr, status, error) { 65 console.error('Errore AJAX salvataggio tema:', error); 66 } 67 }); 68 }); 69 } 70 71 // Aggiungi onerror a tutte le immagini 72 $('img').attr('onerror', "this.src='img/loghi/Aigae_logo_n.png'"); 73 74}); 75 76function checkFileSize(input) { 77 // console.log("Controllo dimensione file...", input); 78 var maxSize = parseInt(jQuery(input).data('max-size')); 79 // console.log("Dimensione massima consentita:", maxSize); 80 var file = input.files[0]; 81 if (file && file.size > maxSize) { 82 alert('Il file selezionato è troppo grande. La dimensione massima consentita è ' + (maxSize / 1000000) + ' MB.'); 83 input.value = ''; 84 return false; 85 } 86 return true; 87} 88 89function rinnovaOra() { 90 cambia_pag('socio', 'rinnovo'); 91} 92 93/** 94 * Restituisce le impostazioni base per DataTable in italiano, con Bootstrap, esportazione e responsive. 95 * @param {Object} options - Opzioni specifiche (colonne, ajax, ecc.) 96 * @returns {Object} Configurazione DataTable 97 */ 98function getBaseDataTableConfig(options = {}) { 99 const filename = options.filename; 100 const baseConfig = { 101 language: { 102 url: 'lib/js/i18n/it-IT.json' 103 }, 104 dom: 'Blfrtip', 105 buttons: filename ? [ 106 { extend: 'excel', filename: filename }, 107 { extend: 'pdf', filename: filename } 108 ] : ['excel', 'pdf'], 109 responsive: true, 110 lengthMenu: [10, 25, 50, 100, -1], 111 pageLength: 25, 112 initComplete: function () { 113 $(this.api().table().container()).find('img').attr('onerror', "this.src='img/loghi/Aigae_logo_n.png'"); 114 }, 115 drawCallback: function () { 116 $(this.api().table().container()).find('img').attr('onerror', "this.src='img/loghi/Aigae_logo_n.png'"); 117 }, 118 }; 119 // Rimuovi filename dalle options per evitare conflitti 120 delete options.filename; 121 return Object.assign(baseConfig, options); 122} 123function populateAnniCorsi() { 124 $.ajax({ 125 url: 'lib/api/api_interne.php?tipo_api=get_anni_corsi', 126 type: 'POST', 127 dataType: 'json', 128 success: function (result) { 129 console.log(result); 130 if (result.success && result.data) { 131 var select = $('.select_anno'); 132 select.empty(); 133 select.append('<option value="">---</option>'); 134 var annoCorrente = new Date().getFullYear(); 135 result.data.forEach(function (anno) { 136 var selected = (anno == annoCorrente) ? 'selected' : ''; 137 select.append('<option value="' + anno + '" ' + selected + '>
137' + anno + '</option>'); 138 }); 139 } 140 } 141 }); 142} 143 144function login() { 145 var username = jQuery('#username').val(); 146 var password = jQuery('#password').val(); 147 148 jQuery.ajax({ 149 url: site_host + '/area_riservata/lib/api/api_interne.php?tipo_api=login', 150 type: 'POST', 151 data: { username: username, password: password }, 152 dataType: 'json', 153 success: function (result) { 154 if( result.success ) 155 { 156 var pagina = ''; 157 var tipouser = result.tipouser; 158 if( tipouser == "socio" ) 159 { 160 if( result.azione == "login_pagamento" ) 161 { 162 const oggi = Date.now(); 163 164 const currAnno = new Date().getFullYear(); 165 const nextAnno = currAnno + 1; 166 167 // Attenzione: Date in JS usa millisecondi 168 const startDate = new Date(currAnno+'-12-31').getTime(); 169 const endDate = new Date(nextAnno+getRinnovoDate()).getTime(); 170 171 if( oggi > startDate && oggi <= endDate ) 172 { 173 const strEndDate = new Intl.DateTimeFormat('it-IT', { 174 day: '2-digit', 175 month: '2-digit', 176 year: 'numeric', 177 hour: '2-digit', 178 minute: '2-digit', 179 hour12: false 180 }).format(endDate); 181 182 showBootstrapAlert('Sarà possibile rinnovare la tua tessera dal ' + strEndDate, 'danger'); 183 return; 184 } 185 else 186 { 187 pagina = '/area_riservata/pages/base.php?pagina=socio'; 188 } 189 } 190 else if( result.azione == "login" ) 191 { 192 pagina = '/area_riservata/pages/'; 193 } 194 } 195 else 196 { 197 pagina = "/gestione_soci/auto-login.php?uid=" + result.iduser + "&exp=" + result.expiry + "&sig=" + result.token + "&username=" + result.username + "&tipouser=" + result.tipouser; 198 } 199 200 var redirectUrl = site_host + pagina; 201 if( tipouser == "socio" && result.mostra_popup_crediti_biennio_precedente ) 202 { 203 showCreditiBiennioPrecedentePopup(function(){ 204 window.location.replace(redirectUrl); 205 }); 206 } 207 else 208 { 209 window.location.replace(redirectUrl); 210 } 211 } 212 else 213 { 214 if( result.azione == "reiscrizione_no_login" ) 215 showBootstrapConfirm('Attenzione, la tua tessera è scaduta da più di un anno!<br />Per poter accedere devi effettuare la reiscrizione <a href=\'/subscription\' style=\'cursor:pointer;\'> (Clicca qui)</a> oppure contatta la segreteria.', function(){ window.location.href = '/subscription' }); 216 else if( result.azione == "dimesso" ) 217 showBootstrapAlert('Attenzione, socio dimesso. Contatta la segreteria per maggiori informazioni.', 'danger'); 218 else if( result.azione == "bloccato" ) 219 showBootstrapAlert('Attenzione, il tuo account e\' stato bloccato fino al ' + result.bloccato_data + ', contatta la segreteria per maggiori informazioni.', 'danger'); 220 else if( result.azione == "pwd_scaduta" ) 221 showBootstrapConfirm('Attenzione, la tua password è scaduta. Prosegui per cambiarla.', function(){ requestPasswordChange(result.iduser); }); 222 else 223 showBootstrapAlert('Credenziali errate', 'danger'); 224 } 225 }, 226 error: function (xhr, status, error) { 227 console.log('Errore AJAX:', status, error); 228 showBootstrapAlert('Errore connessione durante il login.', 'danger'); 229 } 230 }); 231} 232 233function showBootstrapAlert(message, type = 'success') { 234 jQuery('#bootstrapAlertModal').remove(); // Rimuovi modale esistente se presente 235 // Crea modale Bootstrap 236 var modal = document.createElement('div'); 237 modal.id = 'bootstrapAlertModal'; 238 modal.className = 'modal fade'; 239 modal.tabIndex = -1; 240 modal.innerHTML = ` 241 <div class="modal-dialog"> 242 <div class="modal-content"> 243 <div class="modal-header bg-${type}"> 244 <h5 class="modal-title white-text">${type === 'danger' ? 'Errore' : 'Avviso'}</h5> 245 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 246 </div> 247 <div class="modal-body"> 248 <p id="bootstrapAlertMessage"></p> 249 </div> 250 </div> 251 </div>`; 252 document.body.appendChild(modal); 253 254 document.getElementById('bootstrapAlertMessage').innerText = message; 255 const bsModal = new bootstrap.Modal(modal, { backdrop: 'static' });
256 bsModal.show(); 257 setTimeout(function () { 258 bsModal.hide(); 259 }, 3000); 260} 261 262function showBootstrapConfirm(message, callback) { 263 // Crea modale Bootstrap se non esiste 264 let modal = document.getElementById('bootstrapConfirmModal'); 265 if (!modal) { 266 modal = document.createElement('div'); 267 modal.id = 'bootstrapConfirmModal'; 268 modal.className = 'modal fade'; 269 modal.tabIndex = -1; 270 modal.innerHTML = ` 271 <div class="modal-dialog"> 272 <div class="modal-content"> 273 <div class="modal-header"> 274 <h5 class="modal-title">Conferma</h5> 275 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 276 </div> 277 <div class="modal-body"> 278 <p id="bootstrapConfirmMessage"></p> 279 </div> 280 <div class="modal-footer"> 281 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button> 282 <button type="button" class="btn btn-primary" id="bootstrapConfirmOk">Conferma</button> 283 </div> 284 </div> 285 </div>`; 286 document.body.appendChild(modal); 287 } 288 document.getElementById('bootstrapConfirmMessage').innerHTML = message; 289 const okBtn = document.getElementById('bootstrapConfirmOk'); 290 // Rimuovi eventuali listener precedenti 291 okBtn.onclick = function () { 292 const modalInstance = bootstrap.Modal.getInstance(modal); 293 modalInstance.hide(); 294 callback(true); 295 }; 296 const bsModal = new bootstrap.Modal(modal, { backdrop: 'static' }); 297 bsModal.show(); 298} 299 300function showCreditiBiennioPrecedentePopup(callback) { 301 jQuery('#creditiBiennioPrecedenteModal').remove(); 302 303 var modal = document.createElement('div'); 304 modal.id = 'creditiBiennioPrecedenteModal'; 305 modal.className = 'modal fade'; 306 modal.tabIndex = -1; 307 modal.setAttribute('aria-labelledby', 'creditiBiennioPrecedenteModalLabel'); 308 modal.setAttribute('aria-hidden', 'true'); 309 modal.innerHTML = ` 310 <div class="modal-dialog modal-lg modal-dialog-scrollable"> 311 <div class="modal-content"> 312 <div class="modal-header"> 313 <h5 class="modal-title" id="creditiBiennioPrecedenteModalLabel">Aggiornamento e formazione continua</h5> 314 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Chiudi"></button> 315 </div> 316 <div class="modal-body"> 317 <p><strong>Ai soci Aigae non in regola con l'aggiornamento e la formazione continua.</strong></p> 318 <p>Cari colleghi,<br> 319 come sapete Aigae è associazione riconosciuta dal MISE, che indica gli standard di qualità per esercitare la professione di Guida Ambientale Escursionistica.</p> 320 <p>In applicazione delle Direttive UE e della L. 4/2013, infatti, tutte le GAE iscritte al registro nazionale hanno obbligo di aggiornamento e formazione continua.</p> 321 <p>Noi riteniamo questo obbligo una grande opportunità di migliorare sempre più il nostro lavoro a contatto con il pubblico e per l'ambiente del nostro amato e complesso Paese.</p> 322 <p>Nella tua area riservata, potrai controllare i crediti acquisiti e nel caso segnalare a <a href="mailto:[email protected]">[email protected]</a> eventuali errori. Se mancano corsi da te effettuati, potrai fare domanda di accredito direttamente con la nuova procedura digitale cui potrai accedere da "i miei crediti" nella tua area riservata.</p> 323 <p>Con la presente, allo stato attuale delle nostre conoscenze sul tuo aggiornamento professionale, questo messaggio purtroppo è un <strong>RICHIAMO FORMALE</strong> secondo lâart. 146 comma a) del Regolamento Nazionale per il socio poiché non è stato rispettato l'obbligo di aggiornamento e formazione professionale continua.</p> 324 <p>Ti chiediamo uno straordinario impegno per mettere in regola la tua situazione entro e non oltre il <strong>30 giugno 2026</strong>, in difetto di adempimento sarà il Collegio dei Probiviri di Aigae ad assumere le decisioni competenti, compresa la sospensione o radiazione dall'Associazione.</p> 325 <p>Ci auguriamo di cuore che tu voglia comprendere e risolvere questa particolare situazione che si è venuta a creare.</p> 326 <p>Aigae è un'Associazione di categoria, la più grande nel settore in Italia, quindi non può essere solo lo strumento per avere un'assicurazione.</p> 327 <p>Resta in contatto, controlla i tuoi dati personali in area riservata, controlla se ricevi la newsletter, partecipa alla vita associativa, formati ed aggiornati, per rafforzare sempre più AIGAE, quale strumento di partecipazione e di rafforzamento della nostra categoria professionale in Italia.</p> 328 <p>Buoni passi.</p> 329 <p>Daniela D'Amico<br> 330 Presidente Commissione Tecnico-Scientifica e Formazione di Aigae.</p> 331 </div> 332 <div class="modal-footer"> 333 <button type="button" class="btn btn-primary" id="creditiBiennioPrecedenteOk">Ho letto</button> 334 </div> 335 </div> 336 </div>`; 337 document.body.appendChild(modal); 338 339 var redirected = false;
340 var goNext = function () { 341 if( redirected ) 342 return; 343 344 redirected = true; 345 if( typeof callback === 'function' ) 346 callback(); 347 }; 348 349 var bsModal = new bootstrap.Modal(modal, { backdrop: 'static' }); 350 document.getElementById('creditiBiennioPrecedenteOk').onclick = function () { 351 bsModal.hide(); 352 goNext(); 353 }; 354 modal.addEventListener('hidden.bs.modal', goNext, { once: true }); 355 bsModal.show(); 356} 357 358function get_menu_tipo(tipo_menu) { 359 jQuery.ajax({ 360 url: site_host + '/lib/api/api_interne.php?tipo_api=get_menu_tipo', 361 type: 'POST', 362 dataType: 'json', 363 data: { tipo_menu: tipo_menu }, 364 success: function (data) { 365 console.log(data) 366 }, 367 error: function (xhr, status, error) { 368 console.error('Errore AJAX:', status, error); 369 showBootstrapAlert('Errore nel caricamento del menu.', 'danger'); 370 } 371 }); 372} 373 374function cambia_pag(pagina, id_pagina = '', reset = '') { 375 376 //gestione evidenziazione menu 377 console.log('Cambia pagina in: ' + pagina + ' ' + id_pagina); 378 jQuery('.btn-toggle').removeClass('active'); 379 var navButton = jQuery('#' + pagina.replace('/', '-') + id_pagina.replace('/', '-') + '-nav'); 380 if (navButton.length) { 381 navButton.addClass('active'); 382 }else{ 383 var navButton = jQuery('.' + pagina.replace('/', '-') + '-nav'); 384 if (navButton.length) { 385 navButton.addClass('active'); 386 } 387 } 388 389 // Apri il menu padre se non è già aperto 390 if (navButton.length) { 391 navButton.each(function() { 392 var collapse = jQuery(this).closest('.collapse'); 393 if (collapse.length && !collapse.hasClass('show')) { 394 collapse.collapse('show'); 395 } 396 }); 397 } 398 399 window.currentPage = pagina; // Imposta la pagina corrente 400 401 jQuery('#contenuto_pagina').empty(); 402 var link_pag = pagina + ".php"; 403 if (pagina == 'socio') { 404 var urlParams = new URLSearchParams(window.location.search); 405 var params = []; 406 for (let [key, value] of urlParams) { 407 params.push(key + '=' + value); 408 } 409 if (id_pagina == 'skip' && !urlParams.has('skip_photo')) { 410 params.push('skip_photo=1'); 411 } 412 if (id_pagina == 'rinnovo') { 413 params.push('rinnovo=1'); 414 } 415 if (params.length > 0) { 416 link_pag += '?' + params.join('&'); 417 } 418 } 419 else if (pagina == 'cms') { 420 link_pag += '?idpag=' + id_pagina; 421 pagina = 'cms/' + id_pagina; 422 } 423 else if (pagina === 'crediti' && biennio && reset !== 'reset') { 424 link_pag += biennio ? '?biennio=' + biennio : ''; 425 link_pag += idsocio ? '&idsocio=' + idsocio : ''; 426 } 427 else if (pagina === 'gest_corsi_direttore' && azione && reset !== 'reset') { 428 link_pag += azione ? '?azione=' + azione : ''; 429 link_pag += idcorso ? '&idcorso=' + idcorso : ''; 430 } 431 else if (pagina === 'pagamento_corso' && keycorso && reset !== 'reset') { 432 link_pag += keycorso ? '?keycorso=' + keycorso : ''; 433 link_pag += idcorso ? '&idcorso=' + idcorso : ''; 434 } 435 else if (pagina === 'escursione' && idescursione && reset !== 'reset') { 436 link_pag += idescursione ? '?idescursione=' + idescursione : ''; 437 } 438 else if ((pagina === 'pagamento' || pagina === 'card' || pagina === 'prodotti') && codiceEsito && reset !== 'reset') { 439 link_pag += codiceEsito ? '?codiceEsito=' + codiceEsito : ''; 440 link_pag += esito ? '&esito=' + esito : ''; 441 link_pag += codTrans ? '&codTrans=' + codTrans : ''; 442 link_pag += descrizione ? '&descrizione=' + descrizione : ''; 443 } 444 else if ((pagina === 'invio_mail_corsi' || pagina === 'richiedi_crediti_partecipanti' ) && reset !== 'reset') { 445 link_pag += idcorso ? '?idcorso=' + idcorso : ''; 446 } 447 else if (pagina === 'escursioni_socio_cammina_natura') { 448 var link_pag = "escursioni_socio.php?azione=cammina"; 449 } 450 else if (pagina === 'nuova_escursione_cammina_natura') { 451 var link_pag = "nuova_escursione.php?azione=cammina"; 452 } 453 454 455 // Ottieni i parametri attuali se la pagina è la stessa 456 var currentPath = window.location.pathname; 457 var newPath = "/area_riservata/pages/" + pagina; 458 var isPopState = reset === 'popstate'; 459 460 // Se la nuova pagina è una sottopagina della pagina attuale, mantieni i parametri (se reset è vuoto) 461 var finalUrl = isPopState ? currentPath : ((reset === '' && currentPath.startsWith(newPath)) ? currentPath : newPath); 462 if (!isPopState) { 463 history.pushState({ page: pagina }, "", finalUrl); 464 } 465 466 jQuery.get(site_host + '/area_riservata/pages/' + link_pag, function (html_scheda) { 467 jQuery('#contenuto_pagina').append(html_scheda); 468 if (pagina == 'homepage') { 469 showPWAPopup(); 470 } 471 }); 472 473} 474 475function cambiaTema() { 476 var tema = jQuery('#theme_selector').val(); 477 jQuery("body").attr("data-bs-theme", tema); 478} 479 480/** 481 * Visualizza un file (cifrato o meno) nel browser tramite API. 482 * @param {string} filePath - Percorso relativo del file (es: lib/archivio/soci/6463/documento.pdf.enc) 483 * @param {string} tipo - Tipo di accesso (socio, admin, corso, etc.) 484 * @param {boolean} download - Se true, forza il download invece della visualizzazione (default: false) 485 */ 486function downloadFile(filePath, tipo = 'socio', download = false) { 487 // Crea un form nascosto per il POST 488 const form = document.createElement('form'); 489 form.method = 'POST'; 490 form.action = site_host + '/area_riservata/lib/api/api_interne.php?tipo_api=download_file'; 491 form.target = '_blank'; // Apri in una nuova scheda/finestra 492 493 // Aggiungi i campi nascosti 494 const filePathInput = document.createElement('input'); 495 filePathInput.type = 'hidden'; 496 filePathInput.name = 'file_path'; 497 filePathInput.value = filePath; 498 form.appendChild(filePathInput); 499 500 const tipoInput = document.createElement('input'); 501 tipoInput.type = 'hidden'; 502 tipoInput.name = 'tipo'; 503 tipoInput.value = tipo; 504 form.appendChild(tipoInput); 505 506 const downloadInput = document.createElement('input'); 507 downloadInput.type = 'hidden'; 508 downloadInput.name = 'download'; 509 downloadInput.value = download ? '1' : '0'; 510 form.appendChild(downloadInput); 511 512 // Aggiungi il form al body, invia e rimuovi 513 document.body.appendChild(form); 514 form.submit(); 515 document.body.removeChild(form); 516} 517 518/** 519 * Richiede il reset della password 520 */ 521function requestPasswordReset() { 522 var identifier = $('#reset_identifier').val().trim(); 523 if (!identifier) { 524 showAlert('resetAlert', 'Inserisci numero tessera o email', 'danger'); 525 return; 526 } 527 528 $.ajax({
529 url: 'lib/api/api_interne.php?tipo_api=request_password_reset', 530 type: 'POST', 531 data: { identifier: identifier }, 532 dataType: 'json', 533 success: function (result) { 534 if (result.success) { 535 showAlert('resetAlert', result.message, 'success'); 536 setTimeout(function () { 537 $('#modalResetPassword').modal('hide'); 538 $('#formResetPassword')[0].reset(); 539 }, 2000); 540 } else { 541 showAlert('resetAlert', result.message, 'danger'); 542 } 543 }, 544 error: function () { 545 showAlert('resetAlert', 'Errore di connessione', 'danger'); 546 } 547 }); 548} 549 550/** 551 * Richiede il reset della password 552 */ 553function requestPasswordChange(user_id) 554{ 555 $.ajax({ 556 url: 'lib/api/api_interne.php?tipo_api=request_password_change', 557 type: 'POST', 558 data: { user_id: user_id }, 559 dataType: 'json', 560 success: function (result) { 561 if( result.success ) 562 { 563 if( result.success ) 564 window.location.href = '/area_riservata/reset_password.php?token=' + result.token; 565 else 566 showAlert('resetAlert', result.message, 'danger'); 567 } 568 else 569 { 570 showAlert('resetAlert', result.message, 'danger'); 571 } 572 }, 573 error: function () { 574 showAlert('resetAlert', 'Errore di connessione', 'danger'); 575 } 576 }); 577} 578 579/** 580 * Resetta la password con il token 581 */ 582function resetPassword() { 583 var token = $('#token').val(); 584 var newPassword = $('#new_password').val(); 585 var confirmPassword = $('#confirm_password').val(); 586 587 var passRegex = /^(?=.*\d)(?=.*[\W_])(?=.*[a-z])(?=.*[A-Z])[a-zA-Z\d\W_]{8,}$/; 588 589 if (!newPassword || !newPassword.match(passRegex)) { 590 if (newPassword.length < 8) 591 showAlert('resetAlert', "La password deve essere di almeno 8 caratteri!", 'danger'); 592 else if (!newPassword.match(/^(?=.*[A-Z]).*$/)) 593 showAlert('resetAlert', 'La password deve contenere almeno un carattere maiuscolo!', 'danger'); 594 else if (!newPassword.match(/^(?=.*[a-z]).*$/)) 595 showAlert('resetAlert', 'La password deve contenere almeno un carattere minuscolo!', 'danger'); 596 else if (!newPassword.match(/^(?=.*\d).*$/)) 597 showAlert('resetAlert', 'La password deve contenere almeno un numero', 'danger'); 598 else if (!newPassword.match(/^(?=.*[\W_])$/)) 599 showAlert('resetAlert', 'La password deve contenere almeno un carattere speciale', 'danger'); 600 601 return; 602 } 603 604 if (newPassword !== confirmPassword) { 605 showAlert('resetAlert', 'Le password non coincidono', 'danger'); 606 return; 607 } 608 609 $.ajax({ 610 url: 'lib/api/api_interne.php?tipo_api=reset_password', 611 type: 'POST', 612 data: { token: token, password: newPassword }, 613 dataType: 'json', 614 success: function (result) { 615 if (result.success) { 616 showAlert('resetAlert', result.message + '. Reindirizzamento al login...', 'success'); 617 setTimeout(function () { 618 window.location.href = 'index.php'; 619 }, 2000); 620 } else { 621 showAlert('resetAlert', result.message, 'danger'); 622 } 623 }, 624 error: function () { 625 showAlert('resetAlert', 'Errore di connessione', 'danger'); 626 } 627 }); 628} 629 630 631/** 632 * cambio la password 633 */ 634function changePassword() { 635 var username = $('#username').val(); 636 var user_id = $('#user_id').val(); 637 var current_password = $('#current_password').val(); 638 var newPassword = $('#new_password').val(); 639 var confirmPassword = $('#confirm_password').val(); 640 641 if (!newPassword || newPassword.length < 6) { 642 showAlert('resetAlert', 'La password deve essere di almeno 6 caratteri', 'danger'); 643 return; 644 } 645 646 if (newPassword !== confirmPassword) { 647 showAlert('resetAlert', 'Le password non coincidono', 'danger'); 648 return; 649 } 650 651 $.ajax({ 652 url: 'lib/api/api_interne.php?tipo_api=check_current_password', 653 type: 'POST', 654 data: { username: username, password: current_password }, 655 dataType: 'json', 656 success: function (result) { 657 if (result.success) { 658 if (confirm('Sei sicuro di voler cambiare la tua password?')) { 659 $.ajax({
660 url: 'lib/api/api_interne.php?tipo_api=change_password', 661 type: 'POST', 662 data: { user_id: user_id, password: newPassword }, 663 dataType: 'json', 664 success: function (result_2) { 665 if (result_2.success) { 666 showAlert('resetAlert', result.message + '. Reindirizzamento al login...', 'success'); 667 setTimeout(function () { 668 window.location.href = 'index.php'; 669 }, 2000); 670 } else { 671 showAlert('resetAlert', result.message, 'danger'); 672 } 673 }, 674 error: function () { 675 showAlert('resetAlert', 'Errore di connessione', 'danger'); 676 } 677 }); 678 } 679 680 } else { 681 showAlert('resetAlert', result.message, 'danger'); 682 } 683 }, 684 error: function () { 685 showAlert('resetAlert', 'Errore di connessione', 'danger'); 686 } 687 }); 688} 689 690/** 691 * Mostra un alert in un elemento specifico 692 */ 693function showAlert(elementId, message, type) { 694 var alertBox = $('#' + elementId); 695 alertBox.removeClass('d-none alert-success alert-danger alert-warning').addClass('alert-' + type); 696 alertBox.text(message); 697} 698 699// Intercetta il tasto back del browser 700$(window).on('popstate', function (event) { 701 // Qui puoi aggiungere la logica per gestire l'evento back 702 console.log('Tasto back premuto'); 703 console.log('URL attuale:', window.location.href); 704 705 // Ricava il valore dopo 'pages/' dall'URL 706 let path = window.location.pathname; 707 let index = path.indexOf('/pages/'); 708 if (index !== -1) { 709 let valore = path.substring(index + 7); // Lunghezza di '/pages/' 710 // Estrai il nome della pagina senza .php 711 let pageName = valore.replace('.php', ''); 712 // Gestisci i parametri query 713 let urlParams = new URLSearchParams(window.location.search); 714 // Imposta le variabili globali dai parametri 715 if (urlParams.has('idcorso')) { 716 window.idcorso = urlParams.get('idcorso'); 717 } 718 if (urlParams.has('idescursione')) { 719 window.idescursione = urlParams.get('idescursione'); 720 } 721 if (urlParams.has('biennio')) { 722 window.biennio = urlParams.get('biennio'); 723 } 724 if (urlParams.has('idsocio')) { 725 window.idsocio = urlParams.get('idsocio'); 726 } 727 if (urlParams.has('azione')) { 728 window.azione = urlParams.get('azione'); 729 } 730 if (urlParams.has('keycorso')) { 731 window.keycorso = urlParams.get('keycorso'); 732 } 733 if (urlParams.has('codiceEsito')) { 734 window.codiceEsito = urlParams.get('codiceEsito'); 735 } 736 if (urlParams.has('esito')) { 737 window.esito = urlParams.get('esito'); 738 } 739 if (urlParams.has('codTrans')) { 740 window.codTrans = urlParams.get('codTrans'); 741 } 742 if (urlParams.has('descrizione')) { 743 window.descrizione = urlParams.get('descrizione'); 744 } 745 cambia_pag(pageName, '', 'popstate'); 746 } else { 747 console.log('Nessun valore trovato dopo pages/'); 748 } 749 750}); 751 752/** 753 * Mostra le informazioni sulla pagina corrente in un modale. 754 */ 755function showInfo() { 756 const pageDescriptions = { 757 'homepage': 'Questa pagina mostra la homepage dell\'area riservata. Qui puoi vedere un riepilogo delle tue attività , notifiche e collegamenti rapidi alle sezioni principali.', 758 'socio': 'In questa pagina puoi visualizzare e modificare i tuoi dati personali come nome, indirizzo, contatti e altre informazioni del profilo socio.', 759 'corsi_socio': 'Qui trovi la lista dei corsi a cui sei iscritto o hai partecipato. Puoi visualizzare dettagli, attestati e gestire iscrizioni.', 760 'escursioni_socio': 'Visualizza le escursioni a cui hai partecipato o sei iscritto. Include dettagli su date, luoghi e guide.', 761 'escursioni_socio_cammina_natura': 'Visualizza le escursioni dell\'edizione corrente di Cammina Natura in cui sei coinvolto.', 762 'pagamento': 'Gestisci i pagamenti per corsi, escursioni o rinnovi. Puoi effettuare pagamenti online e visualizzare lo storico.', 763 'prodotti': 'Acquista prodotti dell\'AIGAE come gadget, libri o materiali escursionistici direttamente dall\'area riservata.', 764 'ordini': 'Visualizza gli ordini effettuati per i prodotti acquistati. Puoi vedere i dettagli degli acquisti completati.', 765 'crediti': 'Visualizza e gestisci i tuoi crediti formativi accumulati attraverso corsi e attività .', 766 'rinnovo': 'Effettua il rinnovo della tua tessera associativa annuale.', 767 'assicurazione': 'Visualizza e scarica la tua polizza assicurativa valida per le attività associative.', 768 'lista_attestati': 'Scarica gli attestati di partecipazione ai corsi e alle escursioni completate.', 769 'card': 'Acquista le card Assicurazione', 770 'gest_corsi_direttore': 'Se sei un direttore di corso, qui puoi gestire i tuoi corsi: visualizzare iscrizioni, partecipanti, materiali. Nella sezione partecipanti, puoi filtrare la lista per accettati/idonei utilizzando i pulsanti di filtro, rimuovere iscritti dal corso e modificare lo stato di accettazione e id
770oneità cliccando sui badge corrispondenti.', 771 'nuova_escursione': 'Crea e organizza nuove escursioni, specificando date, luoghi, guide e dettagli logistici.', 772 'nuova_escursione_cammina_natura': 'Inserisci un\'escursione gratuita per l\'edizione corrente di Cammina Natura.', 773 'escursione': 'Visualizza i dettagli di una specifica escursione, inclusi partecipanti e materiali.', 774 'crediti_richiesti': 'Visualizza le richieste di crediti formative inviate e il loro stato.', 775 'richiesta_crediti_soci': 'Invia richieste per il riconoscimento di crediti formativi da attività esterne.', 776 'pagamento_corso': 'Effettua il pagamento per un corso specifico selezionato.', 777 'cms': 'Contenuti informativi, come news, annunci o informazioni generali.', 778 'gestione_mail': 'Gestisci le tue preferenze per le comunicazioni email e newsletter.', 779 'fatture': 'Questa pagina permette di visualizzare la lista delle transazioni di pagamento in una tabella e scaricare le fatture relative ai pagamenti effettuati per i vari anni. Puoi filtrare la tabella per anno utilizzando il menu a tendina.', 780 'invio_mail_corsi': 'Questa pagina permette di selezionare i partecipanti a un corso e inviare loro email personalizzate. Seleziona i destinatari spuntando le caselle, componi il messaggio e invia.', 781 }; 782 783 const pageButtons = { 784 'homepage': [ 785 { label: 'Accedi ai Crediti', desc: 'Vai alla pagina per gestire i crediti formativi.' }, 786 { label: 'Rinnova Ora', desc: 'Procedi con il pagamento per il rinnovo della tessera.' }, 787 { label: 'Visualizza Assicurazione', desc: 'Vai alla pagina con le informazioni assicurative.' }, 788 { label: 'Scarica Fattura/Ricevuta', desc: 'Scarica il documento fiscale relativo al pagamento.' } 789 ], 790 'socio': [ 791 { label: 'Salva', desc: 'Salva le modifiche apportate ai tuoi dati personali.' }, 792 { label: 'Visualizza (occhio)', desc: 'Visualizza il documento caricato.' }, 793 { label: 'Modifica (matita)', desc: 'Modifica o sostituisci il documento.' }, 794 { label: 'Elimina (cestino)', desc: 'Elimina il documento caricato.' }, 795 { label: 'Aggiungi (+)', desc: 'Carica un nuovo documento.' } 796 ], 797 'crediti': [ 798 { label: 'Indietro', desc: 'Torna alla visualizzazione precedente.' }, 799 { label: 'BIENNIO X/Y', desc: 'Visualizza i crediti relativi al biennio selezionato.' }, 800 { label: 'Richiedi Crediti Formativi', desc: 'Vai alla pagina per inserire una nuova richiesta di crediti.' }, 801 { label: 'Crediti in attesa di Approvazione', desc: 'Visualizza lo stato delle tue richieste di crediti.' } 802 ], 803 'pagamento': [ 804 { label: 'Procedi con il pagamento', desc: 'Avvia la procedura di pagamento sicuro.' }, 805 { label: 'Torna alla home', desc: 'Ritorna alla homepage dell\'area riservata.' } 806 ], 807 'fatture': [ 808 { label: 'Filtra per anno', desc: 'Utilizza il menu a tendina per filtrare le transazioni per anno specifico.' }, 809 { label: 'Scarica Fattura', desc: 'Scarica la fattura annuale per l\'anno selezionato.' } 810 ], 811 'gest_corsi_direttore': [ 812 { label: 'Partecipanti (X)', desc: 'Visualizza la lista dei partecipanti iscritti al corso selezionato.' }, 813 { label: 'Elimina (cestino rosso)', desc: 'Rimuovi un partecipante dal corso. Verrà richiesta conferma prima della rimozione.' } 814 ], 815 'invio_mail_corsi': [ 816 { label: 'Seleziona Tutti', desc: 'Seleziona tutti i partecipanti nella lista.' }, 817 { label: 'Deseleziona Tutti', desc: 'Deseleziona tutti i partecipanti.' }, 818 { label: 'Invia Email', desc: 'Apri il modale per comporre e inviare l\'email ai selezionati. Puoi allegare file alla mail.' } 819 ] 820 }; 821 822 let content = '<p>' + (pageDescriptions[window.currentPage] || 'Descrizione non disponibile per questa pagina.') + '</p>'; 823 824 if (pageButtons[window.currentPage]) { 825 content += '<hr><h5>Funzionalità Pulsanti:</h5><ul class="list-group list-group-flush">'; 826 pageButtons[window.currentPage].forEach(btn => { 827 content += `<li class="list-group-item"><strong>${btn.label}:</strong> ${btn.desc}</li>`; 828 }); 829 content += '</ul>'; 830 } 831 832 $('#infoModalBody').html(content); 833 const modal = new bootstrap.Modal(document.getElementById('infoModal')); 834 modal.show(); 835} 836 837function showAssicurazioneInfo() { 838 $('#assicurazioneModal').modal('show'); 839} 840 841function showIdentitaeInfo() { 842 const content = '<p>Qui puoi caricare separatamente il fronte e il retro del tuo documento oppure un unico file.</p>'; 843 $('#infoModalLabel').text('Informazioni su Documenti identità '); 844 $('#infoModalBody').html(content); 845 const modal = new bootstrap.Modal(document.getElementById('infoModal')); 846 modal.show(); 847} 848 849function modificaOAggiungi(tipo, num = null) { 850 isModifica = true; 851 let id = 'file_upload_' + tipo; 852 let name = 'file_' + tipo; 853 if ((tipo === 'doc' || tipo === 'req') && num) { 854 name += num; 855 } 856 857 console.log("Modifica/Aggiungi file:", tipo, id, name); 858 859 if (tipo === 'blsd' || tipo === 'cert') 860 { 861 // Apri modal per attestati 862 document.getElementById('tipoCertificato').value = tipo; 863 document.getElementById('enteCertificato').value = ''; 864 document.getElementById('dataInizioCertificato').value = ''; 865 document.getElementById('dataFineCertificato').value = ''; 866 document.getElementById('fileCertificato').value = ''; 867 document.getElementById('modalCertificatoLabel').textContent = tipo === 'blsd' ? 'Carica Attestato BLSD' : 'Carica Attestato Primo Soccorso'; 868 869 jQuery('#modalCertificato').modal('show'); 870 871 // Re-inizializza datepicker dentro il modal per garantire funzionamento con zoom 872 jQuery('#modalCertificato').on('shown.bs.modal', function () { 873 var $modal = jQuery(this); 874 jQuery('#dataInizioCertificato, #dataFineCertificato').datepicker('destroy').datepicker({ 875 dateFormat: 'dd/mm/yy', 876 changeMonth: true, 877 changeYear: true, 878 yearRange: '-100:+10', 879 beforeShow: function (input, inst) { 880 // Appendi il datepicker dentro il modal body per posizionamento corretto con zoom 881 setTimeout(function () { 882 var $dp = inst.dpDiv; 883 $dp.css('z-index', 1065);
884 $modal.find('.modal-body').append($dp); 885 // Ricalcola posizione relativa all'input 886 var $input = jQuery(input); 887 var inputOffset = $input.position(); 888 $dp.css({ 889 position: 'absolute', 890 top: inputOffset.top + $input.outerHeight(), 891 left: inputOffset.left 892 }); 893 }, 0); 894 } 895 }); 896 }); 897 898 return; 899 } 900 901 // Se si modifica il documento BLSD o Certificato, svuota i campi collegati (per altri tipi) 902 if (tipo === 'blsd') { 903 document.getElementById('blsd_rilasciato_ente').value = ''; 904 document.getElementById('blsd_rilasciato_data_inizio').value = ''; 905 document.getElementById('blsd_rilasciato_data_fine').value = ''; 906 } else if (tipo === 'cert') { 907 document.getElementById('soccorso_rilasciato_ente').value = ''; 908 document.getElementById('soccorso_rilasciato_data_inizio').value = ''; 909 document.getElementById('soccorso_rilasciato_data_fine').value = ''; 910 } 911 912 document.getElementById(id).name = name; 913 document.getElementById(id).click(); 914} 915 916function uploadFotoHome() { 917 const fileInput = document.getElementById('file_foto_home'); 918 919 const file = fileInput.files[0]; 920 if (!file) return; 921 922 if(!checkFileSize(fileInput)) 923 return; 924 925 const formData = new FormData(); 926 formData.append('file_foto', file); 927 928 $.ajax({ 929 url: '/area_riservata/lib/api/api_interne.php?tipo_api=upload_foto', 930 type: 'POST', 931 data: formData, 932 processData: false, 933 contentType: false, 934 success: function(response) { 935 if (response.success) { 936 showBootstrapAlert('Foto caricata con successo! In attesa di approvazione.', 'success'); 937 // Reload page or update UI 938 setTimeout(() => location.reload(), 2000); 939 } else { 940 showBootstrapAlert('Errore nel caricamento: ' + response.message, 'danger'); 941 } 942 }, 943 error: function(xhr, status, error) { 944 showBootstrapAlert('Errore di connessione.', 'danger'); 945 } 946 }); 947} 948 949function updateFotoHome() { 950 951} 952 953function togglePasswordVisibility() { 954 var passwordInput = document.getElementById('password'); 955 var icon = document.querySelector('#password ~ .material-icons'); 956 if (passwordInput.type === 'password') { 957 passwordInput.type = 'text'; 958 icon.textContent = 'visibility_off'; 959 } else { 960 passwordInput.type = 'password'; 961 icon.textContent = 'visibility'; 962 } 963} 964 965function getRinnovoDate() 966{ 967 return "-01-02 10:00"; 968} 969 970function getDeviceType() { 971 const ua = navigator.userAgent; 972 if (/android/i.test(ua)) { 973 return 'android'; 974 } else if (/iPad|iPhone|iPod/.test(ua)) { 975 return 'ios'; 976 } else { 977 return 'desktop'; 978 } 979} 980 981function showPWAPopup() { 982 if (!localStorage.getItem('pwa_popup_shown')) { 983 const device = getDeviceType(); 984 let instructions = ''; 985 if (device === 'ios') { 986 instructions = "Per installare la Web app evoluta, apri Safari, tocca il pulsante Condividi (icona quadrata con freccia), poi seleziona 'Aggiungi alla schermata Home'."; 987 } else if (device === 'android') { 988 instructions = "Per installare la Web app evoluta, apri Chrome, tocca il menu (tre punti), poi seleziona 'Aggiungi alla schermata Home' o 'Installa app'."; 989 } else { 990 instructions = "Per installare la Web app evoluta, clicca sull'icona di installazione nella barra degli indirizzi del browser."; 991 } 992 $('#pwaInstallModal .modal-body').html(instructions); 993 $('#pwaInstallModal').modal('show'); 994 localStorage.setItem('pwa_popup_shown', 'true'); 995 } 996}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.