Gestione completa ordini di acquisto: creazione, monitoraggio, righe dettaglio e statistiche. Sistema CRUD con paginazione e filtri avanzati.
// ==================== CONFERMA SLOT SELEZIONATO ====================
function confermaSlotSelezionato() {
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('✅ CONFERMA SLOT PREMUTO!');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
try {
// ✅ Recupera slot temporaneo
if (!window.slotCalendar || !window.slotCalendar.tempSlot) {
alert('⚠️ Nessuno slot selezionato! Clicca prima su uno slot nel calendario.');
console.error('❌ tempSlot non trovato!');
return;
}
const tempSlot = window.slotCalendar.tempSlot;
const slotDateTimeValue = tempSlot.date + 'T' + tempSlot.time;
console.log('📦 Slot temporaneo:', tempSlot);
console.log('🎯 Valore finale:', slotDateTimeValue);
// ✅ SCRIVE nel campo inputSlotTime (ORA SÌ!)
const inputSlot = document.getElementById('inputSlotTime');
const confirmBtn = document.getElementById('confirmSlotBtn');
const previewBox = document.getElementById('slotPreviewBox');
const slotAvailability = document.getElementById('slotAvailability');
const infoEl = document.getElementById('slotSelectedInfo');
if (inputSlot) {
inputSlot.value = slotDateTimeValue;
inputSlot.setAttribute('readonly', true);
inputSlot.style.background = '#d1fae5'; // Verde confermato
inputSlot.style.borderColor = '#10b981';
inputSlot.placeholder = '✅ Slot confermato!';
console.log('✅ Campo inputSlotTime compilato:', inputSlot.value);
}
// ✅ Compila anche inputDataArrivo
const dataArrivoInput = document.getElementById('inputDataArrivo');
if (dataArrivoInput) {
dataArrivoInput.value = slotDateTimeValue;
console.log('✅ Campo inputDataArrivo compilato:', dataArrivoInput.value);
}
// ✅ Nasconde box anteprima GIALLO e mostra VERDE
if (previewBox) {
previewBox.style.background = '#d1fae5'; // Verde confermato
previewBox.style.borderColor = '#10b981';
console.log('✅ Box anteprima cambiato in VERDE');
}
// ✅ Nasconde pulsante conferma
if (confirmBtn) {
confirmBtn.style.display = 'none';
confirmBtn.style.animation = 'none';
console.log('✅ Pulsante "Conferma Slot" nascosto');
}
// ✅ Aggiorna messaggio
if (slotAvailability) {
const slotDate = new Date(slotDateTimeValue);
slotAvailability.innerHTML = `✅ Slot confermato e prenotato!
${slotDate.toLocaleString('it-IT')}`;
slotAvailability.style.color = '#10b981';
}
// ✅ Aggiorna info nel box
if (infoEl) {
infoEl.style.color = '#10b981';
infoEl.style.fontWeight = '700';
}
// ✅ Aggiorna metadata confermati (per timeline)
const selectFornitore = document.getElementById('inputFornitoreId');
const docNumeroFornitore = document.getElementById('inputDocNumero1');
const savedMeta = window.confirmedSlotMeta || {};
if (selectFornitore && selectFornitore.selectedOptions.length > 0) {
const text = selectFornitore.selectedOptions[0].textContent.trim();
const label = text.includes(' - ') ? text.split(' - ').slice(1).join(' - ').trim() : text;
savedMeta.fornitore = label || savedMeta.fornitore || window.caricoFornitoreLabel;
window.caricoFornitoreLabel = savedMeta.fornitore;
}
if (docNumeroFornitore && docNumeroFornitore.value) {
savedMeta.numeroDoc = docNumeroFornitore.value;
window.caricoDocNumber = docNumeroFornitore.value;
}
savedMeta.date = tempSlot.date;
savedMeta.time = tempSlot.time;
window.confirmedSlotMeta = savedMeta;
// ✅ SALTA alla settimana dello slot confermato + RI-RENDERIZZA
if (window.slotCalendar) {
console.log('🚀 SALTO alla settimana dello slot confermato:', tempSlot.date);
if (window.slotCalendar.goToDate) {
window.slotCalendar.goToDate(tempSlot.date + 'T12:00:00');
} else {
window.slotCalendar.render();
}
console.log('✅ Calendario aggiornato con slot prenotato');
}
// ✅ NON usa più overlay (rimosso), lo slot è già visualizzato nel calendario
// const meta = window.confirmedSlotMeta || {};
// renderConfirmedSlotOverlay(meta.date || tempSlot.date, tempSlot.time, meta.fornitore || window.caricoFornitoreLabel, meta.numeroDoc || window.caricoDocNumber);
// ✅ TOAST SUCCESS
if (window.QMS && window.QMS.toast) {
window.QMS.toast.success('✅ Slot confermato e prenotato!');
} else {
alert('✅ Slot confermato e prenotato!');
}
// ✅ Pulisce slot temporaneo
window.slotCalendar.tempSlot = null;
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('✅✅✅ SLOT CONFERMATO E SALVATO NEL FORM!');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
} catch (error) {
console.error('❌❌❌ ERRORE in confermaSlotSelezionato:', error);
alert('⚠️ Errore nella conferma dello slot. Controlla la console (F12).');
}
}
// Mostra pulsante "Conferma Slot" quando uno slot viene selezionato/suggerito
document.addEventListener('DOMContentLoaded', () => {
const inputSlot = document.getElementById('inputSlotTime');
const btnConferma = document.getElementById('btnConfermaSlot');
if (inputSlot) {
// Observer per cambiamenti al campo slot
const observer = new MutationObserver(() => {
if (inputSlot.value && btnConferma) {
btnConferma.style.display = 'block';
console.log('🔘 Pulsante "Conferma Slot" mostrato');
}
});
observer.observe(inputSlot, { attributes: true, attributeFilter: ['value'] });
// Anche su change manuale
inputSlot.addEventListener('change', () => {
if (inputSlot.value && btnConferma) {
btnConferma.style.display = 'block';
console.log('🔘 Pulsante "Conferma Slot" mostrato (change event)');
}
});
}
});
// ==================== CALCOLO REAL-TIME DURATA SLOT ====================
document.addEventListener('DOMContentLoaded', () => {
const inputNumeroPallet = document.getElementById('inputNumeroPallet');
const inputTipoProdotto = document.getElementById('inputTipoProdotto');
if (inputNumeroPallet) {
// Listener su cambio numero pallet
inputNumeroPallet.addEventListener('input', async (e) => {
const numPallet = parseInt(e.target.value);
const tipoProdotto = inputTipoProdotto?.value || 'SURGELATO';
// 🤖 CALENDARIO INTELLIGENTE: Mostra/Nascondi calendario slot automaticamente
const calendarioSection = document.getElementById('calendarioSlotSection');
const palletCapacityInfo = document.getElementById('palletCapacityInfo');
if (numPallet > 0 && !isNaN(numPallet)) {
// Mostra calendario automaticamente
if (calendarioSection) {
calendarioSection.style.display = 'block';
console.log('📅 Calendario slot VISIBILE automaticamente');
}
// Aggiorna info capacità
if (palletCapacityInfo) {
palletCapacityInfo.textContent = ` Cercando slot per ${numPallet} pallet...`;
palletCapacityInfo.style.color = '#2196F3';
}
// Aggiorna calendario con nuova capacità richiesta
if (window.slotCalendar) {
window.slotCalendar.requiredPallet = numPallet;
window.slotCalendar.render();
console.log('🔄 Calendario aggiornato con capacità:', numPallet, 'pallet');
}
} else {
// ✅ FIX: Calendario SEMPRE VISIBILE (non nascondere mai)
// Il calendario è utile anche senza pallet per vedere disponibilità
if (calendarioSection) {
// calendarioSection.style.display = 'none'; ← RIMOSSO!
console.log('📅 Calendario slot SEMPRE VISIBILE (anche senza pallet)');
}
}
if (numPallet > 0 && !isNaN(numPallet)) {
try {
// ✅ FIX #3: Formula calcolo durata - Documentazione corretta
// Il backend calcola: (num_pallet × 2 min/pallet) + 10 min buffer
// Esempi: 5 pallet = 20 min | 10 pallet = 30 min | 15 pallet = 40 min
// La formula viene restituita dinamicamente dall'API e mostrata all'utente
const response = await fetch('https://quality.mercurysurgelati.org/api/slots/calculate-duration', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
num_pallet: numPallet,
tipo_prodotto: tipoProdotto
})
});
if (!response.ok) throw new Error('API error');
const data = await response.json();
if (data.success) {
// Crea o aggiorna preview durata
let previewEl = document.getElementById('slot_duration_preview');
if (!previewEl) {
previewEl = document.createElement('div');
previewEl.id = 'slot_duration_preview';
previewEl.style.cssText = 'margin-top: 12px; padding: 12px 16px; background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%); border-left: 4px solid #3b82f6; border-radius: 8px; animation: slideDown 0.3s ease-out;';
e.target.closest('.form-group').appendChild(previewEl);
}
previewEl.innerHTML = `
`; console.log(`✅ Durata calcolata: ${data.duration_minutes} min`); } } catch (error) { console.error('⚠️ Errore calcolo durata:', error); // Silently fail - non bloccare l'utente } } else { // Rimuovi preview se campo vuoto const previewEl = document.getElementById('slot_duration_preview'); if (previewEl) previewEl.remove(); } }); // Listener anche su cambio tipo prodotto if (inputTipoProdotto) { inputTipoProdotto.addEventListener('change', () => { // Trigger calcolo se c'è già un valore if (inputNumeroPallet.value) { inputNumeroPallet.dispatchEvent(new Event('input')); } }); } console.log('✅ Calcolo real-time durata slot attivato'); } }); // ==================== SISTEMA DOCUMENTI INTELLIGENTE - MAIN ==================== // 🤖 Drag & Drop PRIMA del numero documento (nella sezione principale) // 🔥 FUNZIONE GLOBALE per inizializzare automatismi (chiamata dopo apertura modale) // 🔄 Inizializza automatismi al caricamento SE il modale è già presente document.addEventListener('DOMContentLoaded', () => { // Controlla se il modale esiste già e inizializza if (document.getElementById('modalCarico')) { console.log('🔄 Modale già presente, inizializzo automatismi'); window.initModalAutomatismi(); } else { // Aspetta che il modale venga aggiunto al DOM const observer = new MutationObserver((mutations) => { if (document.getElementById('modalCarico')) { console.log('✅ Modale rilevato, inizializzo automatismi'); window.initModalAutomatismi(); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); } });