netgescon-master/public/js/netgescon-forms.js
2025-07-20 14:57:25 +00:00

241 lines
8.6 KiB
JavaScript

/* ===================================
* NETGESCON FORM HANDLER
* ===================================
* Gestione form con UX migliorata:
* - Modal di conferma
* - Progress indicators
* - No refresh pagina
* - Feedback immediato
* =================================== */
class NetGesConFormHandler {
constructor() {
this.init();
}
init() {
this.setupFormListeners();
this.createLoadingModal();
this.setupAjaxDefaults();
}
setupAjaxDefaults() {
// Setup CSRF token per tutte le richieste AJAX
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
}
setupFormListeners() {
// Intercetta tutti i form con classe 'netgescon-form'
$(document).on('submit', '.netgescon-form', (e) => {
e.preventDefault();
this.handleFormSubmit(e.target);
});
// Intercetta i form di creazione/modifica stabili
$(document).on('submit', 'form[action*="stabili"]', (e) => {
if (!$(e.target).hasClass('netgescon-form')) {
e.preventDefault();
this.handleFormSubmit(e.target);
}
});
}
createLoadingModal() {
const modalHtml = `
<div id="netgescon-loading-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 max-w-sm w-full mx-auto">
<div class="text-center">
<div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 dark:bg-blue-900 mb-4">
<i class="fas fa-spinner fa-spin text-blue-600 dark:text-blue-400 text-2xl"></i>
</div>
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-2">
Elaborazione in corso...
</h3>
<p class="text-sm text-gray-500 dark:text-gray-400" id="loading-message">
Attendere mentre salviamo i dati
</p>
<div class="mt-4">
<div class="bg-gray-200 dark:bg-gray-700 rounded-full h-2">
<div class="bg-blue-600 h-2 rounded-full transition-all duration-300"
id="progress-bar" style="width: 0%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
$('body').append(modalHtml);
}
showLoadingModal(message = 'Elaborazione in corso...') {
$('#loading-message').text(message);
$('#progress-bar').css('width', '20%');
$('#netgescon-loading-modal').removeClass('hidden');
// Simula progress
setTimeout(() => $('#progress-bar').css('width', '60%'), 500);
setTimeout(() => $('#progress-bar').css('width', '80%'), 1000);
}
hideLoadingModal() {
$('#progress-bar').css('width', '100%');
setTimeout(() => {
$('#netgescon-loading-modal').addClass('hidden');
$('#progress-bar').css('width', '0%');
}, 300);
}
handleFormSubmit(form) {
const $form = $(form);
const formData = new FormData(form);
const action = $form.attr('action');
const method = $form.attr('method') || 'POST';
// Determina il messaggio di loading in base al form
let loadingMessage = 'Salvataggio in corso...';
if (action.includes('create') || method.toUpperCase() === 'POST') {
loadingMessage = 'Creazione in corso...';
} else if (action.includes('edit') || action.includes('update')) {
loadingMessage = 'Aggiornamento in corso...';
}
this.showLoadingModal(loadingMessage);
// Se il form ha un metodo specificato tramite _method, usalo
const actualMethod = formData.get('_method') || method;
$.ajax({
url: action,
type: method,
data: formData,
processData: false,
contentType: false,
success: (response) => {
this.hideLoadingModal();
this.handleSuccess(response, $form);
},
error: (xhr) => {
this.hideLoadingModal();
this.handleError(xhr, $form);
}
});
}
handleSuccess(response, $form) {
// Mostra notifica di successo
this.showNotification('Operazione completata con successo!', 'success');
// Reindirizza se specificato nella risposta
if (response.redirect) {
setTimeout(() => {
window.location.href = response.redirect;
}, 1500);
} else {
// Altrimenti ricarica la pagina dopo un delay
setTimeout(() => {
window.location.reload();
}, 1500);
}
}
handleError(xhr, $form) {
console.error('Form submission error:', xhr);
let errorMessage = 'Si è verificato un errore. Riprova.';
if (xhr.status === 422 && xhr.responseJSON && xhr.responseJSON.errors) {
// Errori di validazione
errorMessage = 'Errori di validazione:';
const errors = xhr.responseJSON.errors;
const errorList = Object.values(errors).flat();
this.showValidationErrors(errorList, $form);
return;
} else if (xhr.responseJSON && xhr.responseJSON.message) {
errorMessage = xhr.responseJSON.message;
}
this.showNotification(errorMessage, 'error');
}
showValidationErrors(errors, $form) {
// Rimuovi errori precedenti
$form.find('.error-message').remove();
$form.find('.border-red-500').removeClass('border-red-500');
// Mostra nuovo alert con errori
const errorHtml = `
<div class="error-message bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded mb-4">
<div class="flex items-start">
<i class="fas fa-exclamation-triangle mr-2 mt-1"></i>
<div>
<h4 class="font-bold">Errori di validazione:</h4>
<ul class="mt-2 text-sm">
${errors.map(error => `<li>• ${error}</li>`).join('')}
</ul>
</div>
</div>
</div>
`;
$form.prepend(errorHtml);
// Scroll al primo errore
$form[0].scrollIntoView({ behavior: 'smooth' });
}
showNotification(message, type = 'info') {
const bgColor = type === 'success' ? 'bg-green-500' :
type === 'error' ? 'bg-red-500' : 'bg-blue-500';
const notification = $(`
<div class="fixed top-4 right-4 ${bgColor} text-white px-6 py-4 rounded-lg shadow-lg z-50 transform translate-x-full transition-transform duration-300">
<div class="flex items-center">
<i class="fas fa-${type === 'success' ? 'check' : type === 'error' ? 'exclamation-triangle' : 'info'} mr-2"></i>
<span>${message}</span>
</div>
</div>
`);
$('body').append(notification);
// Mostra notifica
setTimeout(() => {
notification.removeClass('translate-x-full');
}, 100);
// Nascondi dopo 4 secondi
setTimeout(() => {
notification.addClass('translate-x-full');
setTimeout(() => notification.remove(), 300);
}, 4000);
}
}
// Inizializza quando il DOM è pronto
$(document).ready(() => {
// Verifica se jQuery è disponibile
if (typeof $ === 'undefined') {
console.warn('NetGesConFormHandler: jQuery non trovato, caricamento alternativo...');
// Carica jQuery se non presente
const script = document.createElement('script');
script.src = 'https://code.jquery.com/jquery-3.6.0.min.js';
script.onload = () => {
new NetGesConFormHandler();
};
document.head.appendChild(script);
} else {
new NetGesConFormHandler();
}
});
// Esporta per uso globale
window.NetGesConFormHandler = NetGesConFormHandler;