Differenze

Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.

Link a questa pagina di confronto

Entrambe le parti precedenti la revisioneRevisione precedente
docuneo:programma_npt [2025/08/02 21:46] neoadmindocuneo:programma_npt [2025/08/11 15:34] (versione attuale) neoadmin
Linea 5: Linea 5:
     <title>Programma NPT Neonatale v3.0 - Versione Unificata</title>     <title>Programma NPT Neonatale v3.0 - Versione Unificata</title>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>     <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
 +    <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
 +    
 +    <script>
 +    // Simple Barcode Generator - CODE128 - Versione Embedded
 +    window.SimpleBarcode = (function() {
 +        
 +    // Patterns per CODE128
 +    const patterns = {
 +        '0': '11011001100', '1': '11001101100', '2': '11001100110', '3': '10010011000', '4': '10010001100',
 +        '5': '10001001100', '6': '10011001000', '7': '10011000100', '8': '10001100100', '9': '11001001000',
 +        '10': '11001000100', '11': '11000100100', '12': '10110011100', '13': '10011011100', '14': '10011001110',
 +        '15': '10111001100', '16': '10011101100', '17': '10011100110', '18': '11001110010', '19': '11001011100',
 +        '20': '11001001110', '21': '11011100100', '22': '11001110100', '23': '11101010000', '24': '11101000100',
 +        '25': '11100010100', '26': '11100000110', '27': '11101100000', '28': '11100110000', '29': '11100001100',
 +        '30': '11010011000', '31': '11010000110', '32': '11000110100', '33': '10100011000', '34': '10001011000',
 +        '35': '10001000110', '36': '10110001000', '37': '10001101000', '38': '10001100010', '39': '11010001100',
 +        '40': '11000101100', '41': '11000100110', '42': '10110111000', '43': '10110001110', '44': '10001101110',
 +        '45': '10111011000', '46': '10111000110', '47': '10001110110', '48': '11101110110', '49': '11010001110',
 +        '50': '11000101110', '51': '11011101000', '52': '11011100010', '53': '11011101110', '54': '11101011000',
 +        '55': '11101000010', '56': '11100010010', '57': '11101101000', '58': '11101100010', '59': '11100011010',
 +        '60': '11101111010', '61': '11001000010', '62': '11110001010', '63': '10100110000', '64': '10100001100',
 +        '65': '10010110000', '66': '10010000110', '67': '10000101100', '68': '10000100110', '69': '10110010000',
 +        '70': '10110000100', '71': '10011010000', '72': '10011000010', '73': '10000110100', '74': '10000110010',
 +        '75': '11000010010', '76': '11001010000', '77': '11110111010', '78': '11000010100', '79': '10001111010',
 +        '80': '10100111100', '81': '10010111100', '82': '10010011110', '83': '10111100100', '84': '10011110100',
 +        '85': '10011110010', '86': '11110100100', '87': '11110010100', '88': '11110010010', '89': '11011011110',
 +        '90': '11011110110', '91': '11110110110', '92': '10101111000', '93': '10100011110', '94': '10001011110',
 +        '95': '10111101000', '96': '10111100010', '97': '11110101000', '98': '11110100010', '99': '10111011110',
 +        '100': '10111101110', '101': '11101011110', '102': '11110101110', '103': '11010000100', '104': '11010010000', 
 +        '105': '11010011100', 'STOP': '1100011101011'
 +    };
 +    
 +    function generateCode128(text) {
 +        // START B (per caratteri ASCII normali)
 +        let result = patterns['104'];
 +        let checksum = 104;
 +        
 +        // Aggiungi ogni carattere
 +        for (let i = 0; i < text.length; i++) {
 +            const charCode = text.charCodeAt(i) - 32; // ASCII offset
 +            if (patterns[charCode.toString()]) {
 +                result += patterns[charCode.toString()];
 +                checksum += charCode * (i + 1);
 +            }
 +        }
 +        
 +        // Calcola e aggiungi checksum
 +        checksum = checksum % 103;
 +        result += patterns[checksum.toString()];
 +        
 +        // Aggiungi STOP
 +        result += patterns['STOP'];
 +        
 +        return result;
 +    }
 +    
 +    function drawBarcode(canvas, text, options = {}) {
 +        const ctx = canvas.getContext('2d');
 +        const data = generateCode128(text);
 +        
 +        // Opzioni default
 +        const opts = {
 +            width: options.width || 2,
 +            height: options.height || 60,
 +            margin: options.margin || 5,
 +            background: options.background || '#ffffff',
 +            lineColor: options.lineColor || '#000000'
 +        };
 +        
 +        // Calcola dimensioni
 +        const barWidth = opts.width;
 +        const totalWidth = data.length * barWidth + (opts.margin * 2);
 +        const totalHeight = opts.height + (opts.margin * 2);
 +        
 +        // Imposta dimensioni canvas
 +        canvas.width = totalWidth;
 +        canvas.height = totalHeight;
 +        
 +        // Pulisci canvas
 +        ctx.clearRect(0, 0, totalWidth, totalHeight);
 +        
 +        // Background
 +        ctx.fillStyle = opts.background;
 +        ctx.fillRect(0, 0, totalWidth, totalHeight);
 +        
 +        // Disegna le barre
 +        ctx.fillStyle = opts.lineColor;
 +        let x = opts.margin;
 +        
 +        for (let i = 0; i < data.length; i++) {
 +            if (data[i] === '1') {
 +                ctx.fillRect(x, opts.margin, barWidth, opts.height);
 +            }
 +            x += barWidth;
 +        }
 +        
 +        console.log('Codice a barre generato:', text);
 +    }
 +    
 +    return {
 +        generate: drawBarcode
 +    };
 +})();
 +</script>
 +    
     <style>     <style>
 +        * {
 +            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
 +}
         body {         body {
-            font-family: Arial, sans-serif; +        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 
-            margin: 0; +        margin: 0; 
-            padding: 20px; +        padding: 20px; 
-            background-color: #f5f5f5; +        background-color: #f5f5f5; 
-        }+}
  
         .container {         .container {
Linea 23: Linea 131:
  
         h1 {         h1 {
-            text-align: center; +            
-            color: #2c3e50+    text-align: center; 
-            border-bottom3px solid #3498db+    color: white; 
-            padding-bottom: 10px;+    background: linear-gradient(135deg, #1e3c72 0%, #2a5298 50%, #16a085 100%)
 +    border: none
 +    padding: 20px; 
 +    border-radius: 10px; 
 +    margin-bottom: 20px; 
 +    text-shadow: 2px 2px 4px rgba(0,0,0,0.3); 
 +    position: relative; 
 +    overflow: hidden; 
 +
 + 
 +h1::before { 
 +    content: "👶"; 
 +    font-size: 30px; 
 +    position: absolute; 
 +    left: 20px; 
 +    top: 50%; 
 +    transform: translateY(-50%); 
 +}
         }         }
  
Linea 241: Linea 366:
             flex: 1;             flex: 1;
             max-width: 160px;             max-width: 160px;
-            font-size: 12px;+            font-size: 14px; 
 +            font-weight: bold; 
 +        } 
 +        .config-tab { 
 +        min-width: 50px !important; 
 +        max-width: 50px !important; 
 +        width: 50px !important; 
 +        flex: 0 0 50px !important; 
 +        font-size: 24px !important; 
 +        padding: 12px 8px !important; 
 +        transform: none !important; 
 +        } 
 + 
 +        .config-tab:hover { 
 +            background-color: #d5dbdb; 
 +            transform: none !important; 
 +        } 
 + 
 +        .config-tab.active { 
 +            background-color: #3498db; 
 +            color: white; 
 +            transform: none !important;
         }         }
  
Linea 397: Linea 543:
             margin-top: 30px;             margin-top: 30px;
             background-color: white;             background-color: white;
-            font-family: 'Times New Roman', serif;+            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
             line-height: 1.6;             line-height: 1.6;
         }         }
Linea 440: Linea 586:
                 box-shadow: none;                  box-shadow: none; 
             }             }
 +        
 +            
         }         }
 +
 +         /* NUOVA INTESTAZIONE MEDICA ASST LECCO */
 +        .medical-header-table {
 +    width: 100%;
 +    border-collapse: collapse;
 +    border: 2px solid #2c3e50;
 +    margin-bottom: 25px;
 +        }       
 +
 +.medical-header-table td {
 +    border: 1px solid #2c3e50;
 +    padding: 10px;
 +    vertical-align: top;
 +}
 +
 +.medical-header-left {
 +    width: 45%;
 +    background-color: #f8f9fa;
 +}
 +
 +.medical-header-center {
 +    width: 30%;
 +    text-align: center;
 +    background-color: #f8f9fa;
 +}
 +
 +.medical-header-right {
 +    width: 25%;
 +    text-align: center;
 +    background-color: #f8f9fa;
 +}
 +
 +.medical-header-left h2 {
 +    font-size: 14px;
 +    font-weight: bold;
 +    color: #2c3e50;
 +    margin: 0 0 5px 0;
 +}
 +
 +.medical-header-left h3 {
 +    font-size: 12px;
 +    color: #34495e;
 +    margin: 0 0 5px 0;
 +}
 +
 +.medical-header-left p {
 +    font-size: 11px;
 +    color: #7f8c8d;
 +    margin: 0;
 +}          
 +
 +/* NUOVA INTESTAZIONE MEDICA ASST LECCO */
 +.medical-header-table {
 +    width: 100%;
 +    border-collapse: collapse;
 +    border: 2px solid #2c3e50;
 +    margin-bottom: 25px;
 +}
 +
 +.medical-header-table td {
 +    border: 1px solid #2c3e50;
 +    padding: 10px;
 +    vertical-align: top;
 +}
 +
 +.medical-header-left {
 +    width: 45%;
 +    background-color: #f8f9fa;
 +}
 +
 +.medical-header-center {
 +    width: 30%;
 +    text-align: center;
 +    background-color: #f8f9fa;
 +}
 +
 +.medical-header-right {
 +    width: 25%;
 +    text-align: center;
 +    background-color: #f8f9fa;
 +}
 +
 +.medical-header-left h2 {
 +    font-size: 14px;
 +    font-weight: bold;
 +    color: #2c3e50;
 +    margin: 0 0 5px 0;
 +}
 +
 +.medical-header-left h3 {
 +    font-size: 12px;
 +    color: #34495e;
 +    margin: 0 0 5px 0;
 +}
 +
 +.medical-header-left p {
 +    font-size: 11px;
 +    color: #7f8c8d;
 +    margin: 0;
 +}
 +
 +/* STILI KNOWLEDGE BASE */
 +.knowledge-section {
 +    display: none;
 +}
 +
 +.knowledge-section.active {
 +    display: block;
 +}
 +
 +.knowledge-tooltip {
 +    position: absolute;
 +    background-color: #2c3e50;
 +    color: white;
 +    padding: 10px;
 +    border-radius: 5px;
 +    font-size: 12px;
 +    max-width: 300px;
 +    z-index: 1000;
 +    box-shadow: 0 2px 10px rgba(0,0,0,0.3);
 +    animation: fadeIn 0.3s ease-in-out;
 +}
 +
 +@keyframes fadeIn {
 +    from { opacity: 0; transform: translateY(-10px); }
 +    to { opacity: 1; transform: translateY(0); }
 +}
 +
 +.knowledge-section h3 {
 +    color: #2c3e50;
 +    border-bottom: 2px solid #3498db;
 +    padding-bottom: 8px;
 +    margin-bottom: 15px;
 +}
 +
 +.knowledge-section h4 {
 +    color: #34495e;
 +    margin-top: 20px;
 +    margin-bottom: 10px;
 +}
 +
 +/* STILI SPECIFICI PER ETICHETTA SACCA */
 +.label-section {
 +    border: 3px solid #2c3e50;
 +    background-color: #f8f9fa;
 +    padding: 15px;
 +    margin: 15px 0;
 +    border-radius: 8px;
 +}
 +
 +.label-patient-id {
 +    border: 4px solid #d32f2f;
 +    background-color: #ffebee;
 +    padding: 15px;
 +    margin: 15px 0;
 +    text-align: center;
 +    border-radius: 8px;
 +}
 +
 +.label-content {
 +    border: 3px solid #388e3c;
 +    background-color: #e8f5e8;
 +    padding: 15px;
 +    margin: 15px 0;
 +    border-radius: 8px;
 +}
 +
 +.label-header {
 +    text-align: center;
 +    border-bottom: 3px solid #000;
 +    padding-bottom: 10px;
 +    margin-bottom: 15px;
 +}
 +
 +.label-volume-total {
 +    background-color: #4caf50;
 +    color: white;
 +    font-weight: bold;
 +    font-size: 16px;
 +}
 +
     </style>     </style>
 </head> </head>
Linea 446: Linea 775:
  
 <div class="container"> <div class="container">
-    <h1>Programma NPT Neonatale v3.0 - Versione Unificata</h1> +    <h1>Gestione della Nutrizione del Neonato (GNN v3.0)</h1> 
-    <div class="version-info"> +   <div class="version-info"> 
-        <strong>Versione:</strong> 3.0 UNIFIED | <strong>Data creazione:</strong> 02 Agosto 2025 | <strong>Ora:</strong> 20:00 | <strong>Sistema:</strong> NPT Calculator Advanced UNIFIED +    <strong>Sistema:</strong> GNN (Gestione Nutrizione Neonato) v3.0 | <strong>Data creazione:</strong> 02 Agosto 2025 | <strong>Ora:</strong> 20:00 | <strong>Modulo:</strong> Calcolo NPT Integrato 
-    </div>+</div>
          
     <!-- TAB ORIZZONTALI CORRETTI -->     <!-- TAB ORIZZONTALI CORRETTI -->
     <div class="tabs">     <div class="tabs">
-        <div class="tab active" onclick="showTab('patient-data')"> +    <div class="tab active" onclick="showTab('patient-data')"> 
-            <span style="font-size: 16px;">1</span><br>Dati Paziente +        <span style="font-size: 20px; font-weight: bold;">1</span><br>Dati Paziente 
-        </div> +    </div> 
-         +     
-        <!-- SEZIONE CONFIGURAZIONE COMPONENTI (DA VERSIONE 17) --> +    <!-- SEZIONE CONFIGURAZIONE COMPONENTI (DA VERSIONE 17) --> 
-        <div class="tab" onclick="showTab('enteral')"> +    <div class="tab" onclick="showTab('enteral')"> 
-            <span style="font-size: 16px;">2</span><br>Nutrizione Enterale +        <span style="font-size: 20px; font-weight: bold;">2</span><br>Nutrizione Enterale 
-        </div> +    </div> 
-        <div class="tab" onclick="showTab('nutrition-calc')"> +    <div class="tab" onclick="showTab('nutrition-calc')"> 
-            <span style="font-size: 16px;">3</span><br>Calcolo Fabbisogni +        <span style="font-size: 20px; font-weight: bold;">3</span><br>Calcolo Fabbisogni 
-        </div> +    </div> 
-        <div class="tab" onclick="showTab('parenteral')"> +    <div class="tab" onclick="showTab('parenteral')"> 
-            <span style="font-size: 16px;">4</span><br>Nutrizione Parenterale +        <span style="font-size: 20px; font-weight: bold;">4</span><br>Nutrizione Parenterale 
-        </div> +    </div> 
-        <div class="tab" onclick="showTab('report')"> +    <div class="tab" onclick="showTab('report')"> 
-            <span style="font-size: 16px;">5</span><br>Report Finale +        <span style="font-size: 20px; font-weight: bold;">5</span><br>Report Finale 
-        </div> +    </div> 
-        <div class="tab" onclick="showTab('config')"> +    <div class="tab" onclick="showTab('knowledge-base')"> 
-            <span style="font-size: 16px;">6</span><br>Configurazione +        <span style="font-size: 20px; font-weight: bold;">📚</span><br>Knowledge Base 
-        </div>+    </div> 
 +    <div class="tab" onclick="showTab('config')" style="max-width: 60px; min-width: 60px;"> 
 +        <span style="font-size: 24px;">⚙️</span> 
 +    </div>
     </div>     </div>
  
     <!-- TAB 1: DATI PAZIENTE (VERSIONE 17 ORIGINALE) -->     <!-- TAB 1: DATI PAZIENTE (VERSIONE 17 ORIGINALE) -->
     <div id="patient-data" class="tab-content active">     <div id="patient-data" class="tab-content active">
-        <div class="info"> +       <div class="info"> 
-            <strong>PASSO 1 - DATI PAZIENTE</strong><br> +    <strong>PASSO 1 - DATI PAZIENTE</strong><br> 
-            <strong>Obiettivo:</strong> Inserire i dati antropometrici ed ematochimici del neonato +    <strong>Sistema GNN:</strong> Gestione integrata della nutrizione neonatale con calcolo automatico dei fabbisogni<br> 
-        </div>+    <strong>Obiettivo:</strong> Inserire i dati antropometrici ed ematochimici del neonato per determinare la strategia nutrizionale ottimale 
 +</div>
         <div class="section">         <div class="section">
             <h2>Dati Prescrizione</h2>             <h2>Dati Prescrizione</h2>
Linea 527: Linea 860:
                         <input type="number" id="daysOfLife" min="1" max="365" value="9">                         <input type="number" id="daysOfLife" min="1" max="365" value="9">
                     </div>                     </div>
 +
 +                    <div class="input-group">
 +                <label for="gestationalAge">Età gestazionale:</label>
 +                <div style="display: flex; align-items: center; gap: 5px;">
 +                    <input type="number" id="gestationalWeeks" min="22" max="45" placeholder="36" style="width: 60px;">
 +                    <span>sett.</span>
 +                    <input type="number" id="gestationalDays" min="0" max="6" placeholder="3" style="width: 50px;">
 +                    <span>gg.</span>
 +                    <span style="margin-left: 10px; font-size: 12px; color: #666;">(es: 36+3)</span>
 +                </div>
 +            </div>
 +
 +            <div class="input-group">
 +            <label for="postConceptionalAge">Età post-concezionale:</label>
 +            <div style="display: flex; align-items: center; gap: 5px;">
 +                <input type="text" id="postConceptionalAge" readonly style="width: 120px; background-color: #f0f0f0; font-weight: bold;" placeholder="Calcolata automaticamente">
 +                <span style="font-size: 12px; color: #666;">(età gest. + giorni di vita)</span>
 +            </div>
 +</div>
 +
 +
 +
 +
 +
                 </div>                 </div>
                 <div class="form-col">                 <div class="form-col">
Linea 845: Linea 1202:
             <div id="preparationTable"></div>             <div id="preparationTable"></div>
                          
 +
             <div style="margin-top: 20px;">             <div style="margin-top: 20px;">
                 <button class="button" onclick="generatePDF('foglio_lavoro')">📄 Genera PDF - FOGLIO DI LAVORO</button>                 <button class="button" onclick="generatePDF('foglio_lavoro')">📄 Genera PDF - FOGLIO DI LAVORO</button>
                 <button class="button" onclick="generatePDF('report_parenterale')" style="margin-left: 10px;">📄 Genera PDF - REPORT PARENTERALE</button>                 <button class="button" onclick="generatePDF('report_parenterale')" style="margin-left: 10px;">📄 Genera PDF - REPORT PARENTERALE</button>
 +                <button class="button" onclick="generatePDF('etichetta_sacca')" style="margin-left: 10px;">🏷️ Genera PDF - ETICHETTA SACCA</button>
             </div>             </div>
         </div>         </div>
     </div>     </div>
 +
  
     <!-- TAB 5: REPORT FINALE (SPOSTATO DA TAB 6) -->     <!-- TAB 5: REPORT FINALE (SPOSTATO DA TAB 6) -->
Linea 857: Linea 1217:
             <strong>PASSO 5 - REPORT FINALE</strong><br>             <strong>PASSO 5 - REPORT FINALE</strong><br>
             <strong>Obiettivo:</strong> Generare la documentazione completa per prescrizione e preparazione             <strong>Obiettivo:</strong> Generare la documentazione completa per prescrizione e preparazione
 +        </div>
 +
 +    <!-- Banner stato prescrizione -->
 +    <div id="prescriptionStatusBanner" style="display: none;">
 +    <!-- Popolato dinamicamente -->
 +    </div>    
 +    <div class="section no-print">
 +        <h2>Genera Documentazione</h2>
 +        <button class="button" onclick="generatePrescription()">Genera Prescrizione Medica</button>
 +        <button class="button" onclick="generateWorksheet()">Genera Ricetta Preparazione</button>
 +        <button class="button" onclick="generateLabel()">Genera Etichetta Sacca</button>
 +        <button class="button secondary" onclick="window.print()">Stampa Pagina</button>
 +                <!-- Report appare subito qui sotto i pulsanti -->
 +                <div id="reportOutput"></div>
 +            </div>
 +
 +        <!-- SEZIONE 2A: VALIDAZIONE FARMACISTA -->
 +<div class="section">
 +    <h2>💊 Fase 1 - Validazione Farmacista</h2>
 +    <div class="info" style="margin-bottom: 15px;">
 +        <strong>📋 VALIDAZIONE PRESCRIZIONE NPT</strong><br>
 +        Il farmacista deve validare la prescrizione medica prima dell'allestimento.
 +    </div>
 +    
 +    <div class="form-row">
 +        <div class="form-col">
 +            <div class="input-group">
 +                <label for="validatingPharmacist">Farmacista Validatore:</label>
 +                <select id="validatingPharmacist" style="width: 300px;">
 +                    <option value="">Seleziona farmacista responsabile</option>
 +                    <!-- Popolato dinamicamente da pharmacistsData -->
 +                </select>
 +            </div>
 +            <div class="info" style="margin-top: 5px; font-size: 12px;">
 +                <strong>Responsabile della validazione clinica e farmacologica della prescrizione NPT</strong>
 +            </div>
         </div>         </div>
                  
-        <div class="section no-print"> +        <div class="form-col"> 
-            <h2>Genera Documentazione</h2> +            <button class="button" onclick="validatePrescription()" id="validatePrescriptionBtn"> 
-            <button class="buttononclick="generatePrescription()">Genera Prescrizione Medica</button+                📝 VALIDA PRESCRIZIONE 
-            <button class="buttononclick="generateWorksheet()">Genera Ricetta Preparazione</button+            </button> 
-            <button class="button secondaryonclick="window.print()">Stampa Pagina</button>+            <div id="validationStatus" style="margin-top: 15px; display: none;"> 
 +                <!-- Status validazione --> 
 +            </div> 
 +        </div> 
 +    </div> 
 +</div> 
 + 
 +<!-- SEZIONE 2B: ALLESTIMENTO TECNICI --> 
 +<div class="section"> 
 +    <h2>🔬 Fase 2 - Allestimento Galenico</h2
 +    <div class="info" style="margin-bottom: 15px;"> 
 +        <strong>⚗️ PREPARAZIONE FISICA NPT</strong><br> 
 +        Due tecnici qualificati preparano la sacca NPT secondo protocolli GMP con controllo incrociato. 
 +    </div> 
 +     
 +    <div class="form-row"> 
 +        <div class="form-col"
 +            <div class="input-group"
 +                <label for="preparingTechnician1">Primo Tecnico Preparatore:</label> 
 +                <select id="preparingTechnician1" style="width: 300px;" disabled> 
 +                    <option value="">Prima completare validazione farmacista</option> 
 +                    <!-- Popolato dinamicamente da technicianData --> 
 +                </select
 +            </div> 
 +             
 +            <div class="input-group"
 +                <label for="preparingTechnician2">Secondo Tecnico Preparatore:</label> 
 +                <select id="preparingTechnician2" style="width: 300px;" disabled> 
 +                    <option value="">Prima completare validazione farmacist</option> 
 +                    <!-- Popolato dinamicamente da technicianData --> 
 +                </select
 +            </div> 
 +            <div class="infostyle="margin-top: 5px; font-size: 12px;"> 
 +                <strong>Due tecnici diversi per controllo incrociato secondo protocolli GMP</strong> 
 +            </div>
         </div>         </div>
                  
-        <div id="reportOutput"></div>+        <div class="form-col"> 
 +            <button class="button" onclick="confirmPreparation()" id="confirmPreparationBtndisabled> 
 +                🧪 CONFERMA ALLESTIMENTO 
 +            </button> 
 +           <button class="button secondary" onclick="downloadPreparationJSON()" id="downloadBtn" disabled style="margin-top: 10px;"> 
 +                💾 ARCHIVIA PREPARAZIONE (JSON) 
 +            </button> 
 +            <button class="button" onclick="lockPrescription()" id="lockPrescriptionBtn" disabled style="margin-top: 10px; background-color: #e74c3c;"> 
 +                🔒 BLOCCA PRESCRIZIONE 
 +            </button> 
 +            <div id="preparationStatus" style="margin-top: 15px; display: none;"> 
 +                <!-- Status preparazione --> 
 +            </div> 
 +        </div> 
 +    </div> 
 +</div> 
 + 
 +        <!-- SEZIONE ARCHIVIAZIONE MENSILE --> 
 + 
 +     <div class="section"> 
 +    <h2>📊 Archiviazione Mensile Excel</h2> 
 +    <div class="info" style="margin-bottom: 15px;"> 
 +        <strong>📈 CONSOLIDAMENTO PREPARAZIONI NPT</strong><br> 
 +        Genera report Excel mensile con tutte le preparazioni NPT archiviate come JSON. 
 +    </div> 
 +     
 +    <div class="form-row"> 
 +        <div class="form-col"> 
 +            <div class="input-group"> 
 +                <label for="selectedMonth">Mese da consolidare:</label> 
 +                <input type="month" id="selectedMonth" style="width: 150px;"> 
 +            </div> 
 +            <div class="input-group"> 
 +                <label for="jsonFilesInput">File JSON da includere:</label> 
 +                <input type="file" id="jsonFilesInput" multiple accept=".json" style="width: 300px;"> 
 +            </div> 
 +            <div class="info" style="margin-top: 5px; font-size: 12px;"> 
 +                <strong>Seleziona tutti i file NPT_*.json del mese da consolidare</strong> 
 +            </div> 
 +        </div> 
 +         
 +        <div class="form-col"> 
 +            <button class="button" onclick="generateMonthlyExcel()" id="generateExcelBtn"> 
 +                📊 GENERA EXCEL MENSILE 
 +            </button> 
 +            <button class="button secondary" onclick="previewMonthlyData()" id="previewBtn" style="margin-top: 10px;"> 
 +                👁️ ANTEPRIMA DATI 
 +            </button> 
 +             
 +            <div id="monthlyStats" style="margin-top: 15px; display: none;"> 
 +                <!-- Statistiche mensili popolate dinamicamente --> 
 +            </div> 
 +        </div> 
 +    </div> 
 +</div> 
 +    
 +         
 +    </div> 
 + 
 + 
 +<!-- TAB 6: KNOWLEDGE BASE --> 
 +    <div id="knowledge-base" class="tab-content"> 
 +        <div class="info"> 
 +            <strong>🧠 KNOWLEDGE BASE NPT v3.0</strong><br> 
 +            <strong>Sistema:</strong> Base di conoscenza integrata per decision support clinico<br> 
 +            <strong>Obiettivo:</strong> Spiegare regole di calcolo, linee guida e supportare le decisioni cliniche 
 +        </div> 
 + 
 +        <!-- NAVIGAZIONE INTERNA KNOWLEDGE BASE --> 
 +        <div class="tabs" style="margin-bottom: 15px;"> 
 +            <div class="tab active" onclick="showKnowledgeSection('calculation-rules')" style="font-size: 12px; padding: 6px 12px;"> 
 +                🧮 Regole Calcolo 
 +            </div> 
 +            <div class="tab" onclick="showKnowledgeSection('clinical-guidelines')" style="font-size: 12px; padding: 6px 12px;"> 
 +                👩‍⚕️ Linee Guida 
 +            </div> 
 +            <div class="tab" onclick="showKnowledgeSection('alert-system')" style="font-size: 12px; padding: 6px 12px;"> 
 +                🚨 Sistema Alert 
 +            </div> 
 +            <div class="tab" onclick="showKnowledgeSection('evidence-base')" style="font-size: 12px; padding: 6px 12px;"> 
 +                📖 Evidenze 
 +            </div> 
 +            <div class="tab" onclick="showKnowledgeSection('decision-support')" style="font-size: 12px; padding: 6px 12px;"> 
 +                🎯 Decision Support 
 +            </div> 
 +        </div> 
 + 
 +        <!-- SEZIONE 1: REGOLE DI CALCOLO --> 
 +        <div id="calculation-rules" class="knowledge-section active"> 
 +            <div class="section"> 
 +                <h2>🧮 REGOLE DI CALCOLO NPT</h2> 
 +                 
 +                <div class="config-advanced"> 
 +                    <h3>Algoritmi Automatici</h3> 
 +                     
 +                    <div class="form-row"> 
 +                        <div class="form-col"> 
 +                            <h4>📊 Calcolo GIR (Glucose Infusion Rate)</h4> 
 +                            <div class="info" style="font-size: 13px;"> 
 +                                <strong>Formula:</strong> GIR = (Glucidi g/kg/die × 1000) ÷ 1440 minuti<br> 
 +                                <strong>Range sicurezza:</strong> < 12 mg/kg/min (configurabile)<br> 
 +                                <strong>Fonte glucosio:</strong> Glucosio 50% + Acqua bidistillata<br> 
 +                                <strong>Alert automatico:</strong> GIR > 12 mg/kg/min 
 +                            </div> 
 +                             
 +                            <h4>🧪 Calcolo Osmolarità</h4> 
 +                            <div class="info" style="font-size: 13px;"> 
 +                                <strong>Formula:</strong> Σ(Volume componente × Osmolarità componente) ÷ Volume totale<br> 
 +                                <strong>Soglie:</strong><br> 
 +                                • < 600 mOsm/L: Accesso periferico possibile<br> 
 +                                • 600-900 mOsm/L: CVC raccomandato<br> 
 +                                • > 900 mOsm/L: Solo CVC (soluzione ipertonica) 
 +                            </div> 
 +                        </div> 
 +                         
 +                        <div class="form-col"> 
 +                            <h4>⚖️ Gestione Automatica BUN</h4> 
 +                            <div class="info" style="font-size: 13px;"> 
 +                                <strong>Range normale:</strong> 9-14 mg/dL<br> 
 +                                <strong>BUN < 9:</strong> Aumenta proteine +1 g/kg/die<br> 
 +                                <strong>BUN > 14:</strong> Riduce proteine -1 g/kg/die<br> 
 +                                <strong>Applicazione:</strong> Automatica nel caricamento defaults 
 +                            </div> 
 +                             
 +                            <h4>🧂 Selezione Sodio Intelligente</h4> 
 +                            <div class="info" style="font-size: 13px;"> 
 +                                <strong>NaCl standard:</strong> pH > 7.30 e BE > -4<br> 
 +                                <strong>Sodio Acetato:</strong> pH < 7.30 o BE < -4<br> 
 +                                <strong>Effetto:</strong> Sodio Acetato ha azione alcalinizzante<br> 
 +                                <strong>Suggerimento:</strong> Automatico basato su parametri clinici 
 +                            </div> 
 +                        </div> 
 +                    </div> 
 +                </div> 
 +                 
 +                <div class="section"> 
 +                    <h3>📐 Formule Matematiche Principali</h3> 
 +                    <div style="overflow-x: auto;"> 
 +                        <table class="config-table"> 
 +                            <thead> 
 +                                <tr> 
 +                                    <th style="min-width: 200px;">Parametro</th> 
 +                                    <th>Formula</th> 
 +                                    <th>Unità</th> 
 +                                    <th>Range Normale</th> 
 +                                    <th>Note</th> 
 +                                </tr> 
 +                            </thead> 
 +                            <tbody> 
 +                                <tr> 
 +                                    <td><strong>GIR</strong></td> 
 +                                    <td>(Glucidi g/kg/die × 1000) ÷ 1440</td> 
 +                                    <td>mg/kg/min</td> 
 +                                    <td>4-12</td> 
 +                                    <td>Alert se > 12</td> 
 +                                </tr> 
 +                                <tr> 
 +                                    <td><strong>Energia Totale</strong></td> 
 +                                    <td>(Proteine×4) + (Glucidi×4) + (Lipidi×9)</td> 
 +                                    <td>kcal/kg/die</td> 
 +                                    <td>80-120</td> 
 +                                    <td>Dipende da età</td> 
 +                                </tr> 
 +                                <tr> 
 +                                    <td><strong>Osmolarità</strong></td> 
 +                                    <td>Σ(Vol.comp × Osm.comp) ÷ Vol.tot</td> 
 +                                    <td>mOsm/L</td> 
 +                                    <td>&lt; 900</td> 
 +                                    <td>CVC se > 600</td> 
 +                                </tr> 
 +                                <tr> 
 +                                    <td><strong>Rapporto Ca:P</strong></td> 
 +                                    <td>mg Ca elementare : mg P</td> 
 +                                    <td>ratio</td> 
 +                                    <td>1.3:1 - 2:1</td> 
 +                                    <td>Evita precipitazioni</td> 
 +                                </tr> 
 +                                <tr> 
 +                                    <td><strong>Velocità Infusione</strong></td> 
 +                                    <td>Volume totale NPT ÷ 24</td> 
 +                                    <td>ml/h</td> 
 +                                    <td>Variabile</td> 
 +                                    <td>Infusione continua</td> 
 +                                </tr> 
 +                            </tbody> 
 +                        </table> 
 +                    </div> 
 +                </div> 
 +            </div> 
 +        </div> 
 + 
 +        <!-- SEZIONE 2: LINEE GUIDA CLINICHE (placeholder per ora) --> 
 +        <div id="clinical-guidelines" class="knowledge-section hidden"> 
 +            <div class="section"> 
 +                <h2>👩‍⚕️ LINEE GUIDA CLINICHE</h2> 
 +                <div class="info"> 
 +                    <strong>🚧 In sviluppo...</strong><br> 
 +                    Questa sezione conterrà protocolli per età, patologie e tempistiche. 
 +                </div> 
 +            </div> 
 +        </div> 
 + 
 +        <!-- SEZIONE 3: SISTEMA ALERT (placeholder per ora) --> 
 +        <div id="alert-system" class="knowledge-section hidden"> 
 +            <div class="section"> 
 +                <h2>🚨 SISTEMA ALERT</h2> 
 +                <div class="info"> 
 +                    <strong>🚧 In sviluppo...</strong><br> 
 +                    Questa sezione spiegherà soglie di allarme e azioni consigliate. 
 +                </div> 
 +            </div> 
 +        </div> 
 + 
 +        <!-- SEZIONE 4: EVIDENZE (placeholder per ora) --> 
 +        <div id="evidence-base" class="knowledge-section hidden"> 
 +            <div class="section"> 
 +                <h2>📖 EVIDENZE SCIENTIFICHE</h2> 
 +                <div class="info"> 
 +                    <strong>🚧 In sviluppo...</strong><br> 
 +                    Questa sezione conterrà bibliografia e riferimenti scientifici. 
 +                </div> 
 +            </div> 
 +        </div> 
 + 
 +        <!-- SEZIONE 5: DECISION SUPPORT (placeholder per ora) --> 
 +        <div id="decision-support" class="knowledge-section hidden"> 
 +            <div class="section"> 
 +                <h2>🎯 DECISION SUPPORT</h2> 
 +                <div class="info"> 
 +                    <strong>🚧 In sviluppo...</strong><br> 
 +                    Questa sezione conterrà configurazione regole e simulatore. 
 +                </div> 
 +            </div> 
 +        </div> 
     </div>     </div>
  
Linea 983: Linea 1647:
                 <table class="config-table">                 <table class="config-table">
                     <thead>                     <thead>
-                        <tr> +    <tr> 
-                            <th style="min-width: 180px;">Componente</th> +        <th style="min-width: 180px;">Componente</th> 
-                            <th>Proteine<br>(g)</th> +        <th>Proteine<br>(g)</th> 
-                            <th>Carboidrati<br>(g)</th> +        <th>Carboidrati<br>(g)</th> 
-                            <th>Lipidi<br>(g)</th> +        <th>Lipidi<br>(g)</th> 
-                            <th>Sodio<br>(mEq)</th> +        <th>Sodio<br>(mEq)</th> 
-                            <th>Potassio<br>(mEq)</th> +        <th>Potassio<br>(mEq)</th> 
-                            <th>Calcio<br>(mg)</th> +        <th>Calcio<br>(mg)</th> 
-                            <th>Fosforo<br>(mg)</th> +        <th>Fosforo<br>(mg)</th> 
-                            <th>Magnesio<br>(mEq)</th> +        <th>Magnesio<br>(mEq)</th> 
-                            <th>Energia<br>(kcal)</th> +        <th>Energia<br>(kcal)</th> 
-                            <th>Acqua<br>(ml)</th> +        <th>Acqua<br>(ml)</th> 
-                            <th style="min-width: 200px;">Descrizione e Note</th> +        <th>Osmolarità<br>(mOsm/L)</th> 
-                            <th>Azioni</th> +        <th style="min-width: 200px;">Descrizione e Note</th> 
-                        </tr> +        <th>Azioni</th> 
-                    </thead>+    </tr> 
 +</thead>
                     <tbody id="parenteralConfigTable">                     <tbody id="parenteralConfigTable">
                         <!-- Popolato dinamicamente -->                         <!-- Popolato dinamicamente -->
Linea 1044: Linea 1709:
                 </div>                 </div>
             </div>             </div>
 +            <div class="section">
 +            <h2>Lista Infermiere</h2>
 +            <div class="info" style="margin-bottom: 15px;">
 +                <strong>👩‍⚕️ CONFIGURAZIONE INFERMIERE</strong><br>
 +                Gestisci la lista delle infermiere del reparto. Le modifiche si applicano automaticamente.
 +            </div>
 +            <div style="overflow-x: auto;">
 +                <table class="config-table">
 +                    <thead>
 +                        <tr>
 +                            <th style="min-width: 120px;">Nome</th>
 +                            <th style="min-width: 120px;">Cognome</th>
 +                            <th style="min-width: 80px;">Titolo</th>
 +                            <th style="min-width: 250px;">Nome Completo (Visualizzato)</th>
 +                            <th>Azioni</th>
 +                        </tr>
 +                    </thead>
 +                    <tbody id="nursesConfigTable">
 +                        <!-- Popolato dinamicamente -->
 +                    </tbody>
 +                </table>
 +            </div>
 +            <div class="form-row">
 +                <div class="form-col">
 +                    <button id="updateNursesBtn" class="button" onclick="updateNursesConfig()">Aggiorna Lista Infermiere</button>
 +                </div>
 +                <div class="form-col">
 +                    <button class="button secondary" onclick="showAddNurseForm()">Aggiungi Nuova Infermiera</button>
 +                </div>
 +            </div>
 +        </div>
 +
 +        <div class="section">
 +            <h2>Lista Farmacisti</h2>
 +            <div class="info" style="margin-bottom: 15px;">
 +                <strong>💊 CONFIGURAZIONE FARMACISTI</strong><br>
 +                Gestisci la lista dei farmacisti ospedalieri. Le modifiche si applicano automaticamente.
 +            </div>
 +            <div style="overflow-x: auto;">
 +                <table class="config-table">
 +                    <thead>
 +                        <tr>
 +                            <th style="min-width: 120px;">Nome</th>
 +                            <th style="min-width: 120px;">Cognome</th>
 +                            <th style="min-width: 80px;">Titolo</th>
 +                            <th style="min-width: 250px;">Nome Completo (Visualizzato)</th>
 +                            <th>Azioni</th>
 +                        </tr>
 +                    </thead>
 +                    <tbody id="pharmacistsConfigTable">
 +                        <!-- Popolato dinamicamente -->
 +                    </tbody>
 +                </table>
 +            </div>
 +            <div class="form-row">
 +                <div class="form-col">
 +                    <button id="updatePharmacistsBtn" class="button" onclick="updatePharmacistsConfig()">Aggiorna Lista Farmacisti</button>
 +                </div>
 +                <div class="form-col">
 +                    <button class="button secondary" onclick="showAddPharmacistForm()">Aggiungi Nuovo Farmacista</button>
 +                </div>
 +            </div>
 +        </div>
 +
 +        <div class="section">
 +            <h2>Lista Tecnici di Farmacia</h2>
 +            <div class="info" style="margin-bottom: 15px;">
 +                <strong>🔬 CONFIGURAZIONE TECNICI</strong><br>
 +                Gestisci la lista dei tecnici di farmacia. Le modifiche si applicano automaticamente.
 +            </div>
 +            <div style="overflow-x: auto;">
 +                <table class="config-table">
 +                    <thead>
 +                        <tr>
 +                            <th style="min-width: 120px;">Nome</th>
 +                            <th style="min-width: 120px;">Cognome</th>
 +                            <th style="min-width: 80px;">Titolo</th>
 +                            <th style="min-width: 250px;">Nome Completo (Visualizzato)</th>
 +                            <th>Azioni</th>
 +                        </tr>
 +                    </thead>
 +                    <tbody id="techniciansConfigTable">
 +                        <!-- Popolato dinamicamente -->
 +                    </tbody>
 +                </table>
 +            </div>
 +            <div class="form-row">
 +                <div class="form-col">
 +                    <button id="updateTechniciansBtn" class="button" onclick="updateTechniciansConfig()">Aggiorna Lista Tecnici</button>
 +                </div>
 +                <div class="form-col">
 +                    <button class="button secondary" onclick="showAddTechnicianForm()">Aggiungi Nuovo Tecnico</button>
 +                </div>
 +            </div>
 +        </div>
         </div>         </div>
  
Linea 1225: Linea 1985:
         protein: 6.0, carbs: 0, lipids: 0, sodium: 0, potassium: 0,         protein: 6.0, carbs: 0, lipids: 0, sodium: 0, potassium: 0,
         calcium: 0, phosphorus: 0, magnesium: 0, energy: 24, water: 94,         calcium: 0, phosphorus: 0, magnesium: 0, energy: 24, water: 94,
 +        osmolarity: 360, // mOsm/L
         description: "Soluzione di aminoacidi pediatrica",         description: "Soluzione di aminoacidi pediatrica",
         notes: "Soluzione sterile per uso endovenoso. Osmolarità: ~360 mOsm/L"         notes: "Soluzione sterile per uso endovenoso. Osmolarità: ~360 mOsm/L"
Linea 1232: Linea 1993:
         protein: 0, carbs: 0, lipids: 20.0, sodium: 0, potassium: 0,         protein: 0, carbs: 0, lipids: 20.0, sodium: 0, potassium: 0,
         calcium: 0, phosphorus: 0, magnesium: 0, energy: 200, water: 80,         calcium: 0, phosphorus: 0, magnesium: 0, energy: 200, water: 80,
 +        osmolarity: 280, // mOsm/L
         description: "Emulsione lipidica endovenosa",         description: "Emulsione lipidica endovenosa",
-        notes: "Fornisce acidi grassi essenziali. Max 4g/kg/die"+        notes: "Fornisce acidi grassi essenziali. Max 4g/kg/die. Osmolarità: ~280 mOsm/L"
     },     },
     glucose50: {     glucose50: {
Linea 1239: Linea 2001:
         protein: 0, carbs: 50.0, lipids: 0, sodium: 0, potassium: 0,         protein: 0, carbs: 50.0, lipids: 0, sodium: 0, potassium: 0,
         calcium: 0, phosphorus: 0, magnesium: 0, energy: 200, water: 50,         calcium: 0, phosphorus: 0, magnesium: 0, energy: 200, water: 50,
 +        osmolarity: 2780, // mOsm/L
         description: "Soluzione glucosata molto ipertonica",         description: "Soluzione glucosata molto ipertonica",
-        notes: "Osmolarità: ~2800 mOsm/L. Solo per alte concentrazioni"+        notes: "Osmolarità: ~2780 mOsm/L. Solo per alte concentrazioni"
     },     },
     ca_gluconato: {     ca_gluconato: {
Linea 1246: Linea 2009:
         protein: 0, carbs: 0, lipids: 0, sodium: 0, potassium: 0,         protein: 0, carbs: 0, lipids: 0, sodium: 0, potassium: 0,
         calcium: 840, phosphorus: 0, magnesium: 0, energy: 0, water: 90,         calcium: 840, phosphorus: 0, magnesium: 0, energy: 0, water: 90,
 +        osmolarity: 320, // mOsm/L
         description: "Sale di calcio organico",         description: "Sale di calcio organico",
-        notes: "8.4 mg Ca/ml. Non precipita con fosfati"+        notes: "8.4 mg Ca/ml. Non precipita con fosfati. Osmolarità: ~320 mOsm/L"
     },     },
     esafosfina: {     esafosfina: {
Linea 1253: Linea 2017:
         protein: 0, carbs: 0, lipids: 0, sodium: 130, potassium: 0,         protein: 0, carbs: 0, lipids: 0, sodium: 130, potassium: 0,
         calcium: 0, phosphorus: 1600, magnesium: 0, energy: 0, water: 98,         calcium: 0, phosphorus: 1600, magnesium: 0, energy: 0, water: 98,
 +        osmolarity: 450, // mOsm/L
         description: "Glicerofosfato di sodio",         description: "Glicerofosfato di sodio",
-        notes: "16 mg P/ml + 1.3 mEq Na/ml. Fosforo organico"+        notes: "16 mg P/ml + 1.3 mEq Na/ml. Fosforo organico. Osmolarità: ~450 mOsm/L"
     },     },
     mg_sulfate: {     mg_sulfate: {
Linea 1260: Linea 2025:
         protein: 0, carbs: 0, lipids: 0, sodium: 0, potassium: 0,         protein: 0, carbs: 0, lipids: 0, sodium: 0, potassium: 0,
         calcium: 0, phosphorus: 0, magnesium: 800, energy: 0, water: 99,         calcium: 0, phosphorus: 0, magnesium: 800, energy: 0, water: 99,
 +        osmolarity: 1620, // mOsm/L
         description: "Elettrolita essenziale",         description: "Elettrolita essenziale",
-        notes: "8 mEq Mg/ml. Cofattore enzimatico"+        notes: "8 mEq Mg/ml. Cofattore enzimatico. Osmolarità: ~1620 mOsm/L"
     },     },
     nacl: {     nacl: {
Linea 1267: Linea 2033:
         protein: 0, carbs: 0, lipids: 0, sodium: 1000, potassium: 0,         protein: 0, carbs: 0, lipids: 0, sodium: 1000, potassium: 0,
         calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99,         calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99,
 +        osmolarity: 2050, // mOsm/L
         description: "Elettrolita essenziale",         description: "Elettrolita essenziale",
-        notes: "10 mEq Na/ml. Prima scelta per supplementazione sodio"+        notes: "10 mEq Na/ml. Prima scelta per supplementazione sodio. Osmolarità: ~2050 mOsm/L"
     },     },
     sodium_acetate: {     sodium_acetate: {
-        name: "Sodio Acetato (mEq/mL)",+        name: "Sodio Acetato (mEq/mL)",
         protein: 0, carbs: 0, lipids: 0, sodium: 667, potassium: 0,         protein: 0, carbs: 0, lipids: 0, sodium: 667, potassium: 0,
         calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99,         calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99,
 +        osmolarity: 1340, // mOsm/L
         description: "Elettrolita alcalinizzante",         description: "Elettrolita alcalinizzante",
-        notes: "6.67 mEq Na/ml. Per acidosi: pH < 7.25 o BE < -4"+        notes: "6.67 mEq Na/ml. Per acidosi: pH < 7.25 o BE < -4. Osmolarità: ~1340 mOsm/L"
     },     },
     kcl: {     kcl: {
Linea 1281: Linea 2049:
         protein: 0, carbs: 0, lipids: 0, sodium: 0, potassium: 1000,         protein: 0, carbs: 0, lipids: 0, sodium: 0, potassium: 1000,
         calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99,         calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99,
 +        osmolarity: 2050, // mOsm/L
         description: "Elettrolita essenziale",         description: "Elettrolita essenziale",
-        notes: "10 mEq K/ml. Max velocità infusione: 0.5 mEq/kg/h"+        notes: "10 mEq K/ml. Max velocità infusione: 0.5 mEq/kg/h. Osmolarità: ~2050 mOsm/L"
     },     },
     carnitene: {     carnitene: {
Linea 1288: Linea 2057:
         protein: 0, carbs: 0, lipids: 0, sodium: 0, potassium: 0,         protein: 0, carbs: 0, lipids: 0, sodium: 0, potassium: 0,
         calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99,         calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99,
 +        osmolarity: 280, // mOsm/L
         carnitine: 10000, // 100 mg/ml = 10000 mg/100ml         carnitine: 10000, // 100 mg/ml = 10000 mg/100ml
         description: "L-Carnitina per NPT prolungata",         description: "L-Carnitina per NPT prolungata",
-        notes: "100 mg/ml. Indicata per NPT > 1 mese. Dose: 5 mg/kg/die"+        notes: "100 mg/ml. Indicata per NPT > 1 mese. Dose: 5 mg/kg/die. Osmolarità: ~280 mOsm/L"
     }     }
 }; };
Linea 1324: Linea 2094:
     dr_aquisti: { name: "Giulia", surname: "Aquisti", title: "Dr.ssa", fullName: "Dr.ssa Giulia Aquisti" }     dr_aquisti: { name: "Giulia", surname: "Aquisti", title: "Dr.ssa", fullName: "Dr.ssa Giulia Aquisti" }
 }; };
 +
 +// Database infermiere dinamico
 +let nursesData = {
 +    inf_rossi: { name: "Maria", surname: "Rossi", title: "Inf.", fullName: "Inf. Maria Rossi" },
 +    inf_bianchi: { name: "Laura", surname: "Bianchi", title: "Inf.", fullName: "Inf. Laura Bianchi" },
 +    inf_verdi: { name: "Giulia", surname: "Verdi", title: "Inf.", fullName: "Inf. Giulia Verdi" },
 +    inf_ferrari: { name: "Anna", surname: "Ferrari", title: "Inf.", fullName: "Inf. Anna Ferrari" },
 +    inf_moretti: { name: "Silvia", surname: "Moretti", title: "Inf.", fullName: "Inf. Silvia Moretti" },
 +    inf_conti: { name: "Elena", surname: "Conti", title: "Inf.", fullName: "Inf. Elena Conti" }
 +};
 +
 +// Database farmacisti dinamico
 +let pharmacistsData = {
 +    farm_lombardi: { name: "Marco", surname: "Lombardi", title: "Dr. Farm.", fullName: "Dr. Farm. Marco Lombardi" },
 +    farm_ricci: { name: "Paolo", surname: "Ricci", title: "Dr. Farm.", fullName: "Dr. Farm. Paolo Ricci" },
 +    farm_marino: { name: "Francesca", surname: "Marino", title: "Dr.ssa Farm.", fullName: "Dr.ssa Farm. Francesca Marino" },
 +    farm_greco: { name: "Andrea", surname: "Greco", title: "Dr. Farm.", fullName: "Dr. Farm. Andrea Greco" },
 +    farm_bruno: { name: "Valentina", surname: "Bruno", title: "Dr.ssa Farm.", fullName: "Dr.ssa Farm. Valentina Bruno" }
 +};
 +
 +// Database tecnici di farmacia dinamico
 +let technicianData = {
 +    tec_russo: { name: "Giuseppe", surname: "Russo", title: "Tec.", fullName: "Tec. Giuseppe Russo" },
 +    tec_gallo: { name: "Roberto", surname: "Gallo", title: "Tec.", fullName: "Tec. Roberto Gallo" },
 +    tec_costa: { name: "Michela", surname: "Costa", title: "Tec.", fullName: "Tec. Michela Costa" },
 +    tec_rizzo: { name: "Alessandro", surname: "Rizzo", title: "Tec.", fullName: "Tec. Alessandro Rizzo" },
 +    tec_longo: { name: "Chiara", surname: "Longo", title: "Tec.", fullName: "Tec. Chiara Longo" },
 +    tec_giordano: { name: "Matteo", surname: "Giordano", title: "Tec.", fullName: "Tec. Matteo Giordano" }
 +};
 +
 +
  
 // VARIABILI GLOBALI // VARIABILI GLOBALI
Linea 1339: Linea 2140:
     maxProtein: 4.5,     maxProtein: 4.5,
     hospitalName: "ASST LECCO",     hospitalName: "ASST LECCO",
-    departmentName: "S.C. Neonatologia e TIN", +    departmentName: "S.C. Neonatologia e Terapia Intensiva Neonatale", 
-    directorName: "Dott. Roberto Bellù"+    directorName: "Dr. Roberto Bellù"
 }; };
  
Linea 1381: Linea 2182:
     }     }
 } }
 +
 +
 +// SISTEMA PROTEZIONE CONFIGURAZIONE
 +function checkConfigAccess() {
 +    // Password predefinita (modificabile)
 +    const ADMIN_PASSWORD = "admin2025";
 +    
 +    // Controlla se l'accesso è già stato autorizzato in questa sessione
 +    if (window.configAccessGranted === true) {
 +        return true;
 +    }
 +    
 +    // Richiedi password
 +    const userPassword = prompt(
 +        "🔐 ACCESSO CONFIGURAZIONE RISERVATO\n\n" +
 +        "Inserire la password di amministrazione per accedere alle impostazioni del sistema NPT Calculator v3.0:"
 +    );
 +    
 +    // Se utente cancella
 +    if (userPassword === null) {
 +        return false;
 +    }
 +    
 +    // Verifica password
 +    if (userPassword === ADMIN_PASSWORD) {
 +        window.configAccessGranted = true;
 +        alert("✅ Accesso autorizzato!\n\nBenvenuto nella configurazione avanzata NPT Calculator v3.0");
 +        return true;
 +    } else {
 +        alert("❌ Password non corretta!\n\nAccesso negato alla configurazione.");
 +        return false;
 +    }
 +}
 +
 +// Funzione per logout configurazione
 +function logoutConfig() {
 +    window.configAccessGranted = false;
 +    alert("🔓 Logout configurazione effettuato.\nPer rientrare servirà di nuovo la password.");
 +    // Torna al TAB 1
 +    showTab('patient-data');
 +}
 +
  
 // FUNZIONE CORRETTA PER CAMBIO TAB // FUNZIONE CORRETTA PER CAMBIO TAB
Linea 1406: Linea 2249:
     }     }
          
-    // Popola le tabelle di configurazione quando si apre il TAB 6 (ora config)+    // Sistema di protezione per TAB configurazione
     if (tabId === 'config') {     if (tabId === 'config') {
 +        if (!checkConfigAccess()) {
 +            return; // Blocca l'accesso se password non corretta
 +        }
         setTimeout(() => {         setTimeout(() => {
             populateEnteralConfigTable();             populateEnteralConfigTable();
             populateParenteralConfigTable();             populateParenteralConfigTable();
             populateDoctorsConfigTable();             populateDoctorsConfigTable();
 +            populateNursesConfigTable();
 +            populatePharmacistsConfigTable();
 +            populateTechniciansConfigTable();
         }, 100);         }, 100);
     }     }
 +
 +// Popola le dropdown del personale quando si apre il TAB 5 (report)
 +if (tabId === 'report') {
 +    setTimeout(() => {
 +        updatePreparationStaffDropdowns();
 +    }, 100);
 +}
 +
 } }
  
Linea 1462: Linea 2319:
  
 function updateDoctorsDropdown() { function updateDoctorsDropdown() {
 +    console.log('updateDoctorsDropdown chiamata');
     const prescribingDoctorSelect = document.getElementById('prescribingDoctor');     const prescribingDoctorSelect = document.getElementById('prescribingDoctor');
-    if (!prescribingDoctorSelect) return;+    console.log('Elemento prescribingDoctor trovato:', prescribingDoctorSelect); 
 +     
 +    if (!prescribingDoctorSelect) 
 +        console.error('ERRORE: Elemento prescribingDoctor non trovato!'); 
 +        return
 +    } 
 +     
 +    console.log('doctorsData:', doctorsData); 
 +    console.log('Numero medici:', Object.keys(doctorsData).length);
          
     const currentValue = prescribingDoctorSelect.value;     const currentValue = prescribingDoctorSelect.value;
Linea 1470: Linea 2336:
     Object.keys(doctorsData).forEach(function(key) {     Object.keys(doctorsData).forEach(function(key) {
         const doctor = doctorsData[key];         const doctor = doctorsData[key];
 +        console.log('Aggiungendo medico:', doctor.fullName);
         const option = document.createElement('option');         const option = document.createElement('option');
         option.value = key;         option.value = key;
Linea 1480: Linea 2347:
         prescribingDoctorSelect.value = currentValue;         prescribingDoctorSelect.value = currentValue;
     }     }
 +    
 +    console.log('Dropdown popolata con', prescribingDoctorSelect.options.length, 'opzioni');
 +}
 +
 +// FUNZIONE CALCOLO ETÀ POST-CONCEZIONALE
 +function calculatePostConceptionalAge() {
 +    const gestWeeks = parseInt(document.getElementById('gestationalWeeks').value) || 0;
 +    const gestDays = parseInt(document.getElementById('gestationalDays').value) || 0;
 +    const daysOfLife = parseInt(document.getElementById('daysOfLife').value) || 0;
 +    
 +    if (gestWeeks === 0 || daysOfLife === 0) {
 +        document.getElementById('postConceptionalAge').value = '';
 +        return null;
 +    }
 +    
 +    // Calcola età post-concezionale
 +    const totalGestationalDays = (gestWeeks * 7) + gestDays;
 +    const totalPostConceptionalDays = totalGestationalDays + daysOfLife;
 +    
 +    // Converti in settimane+giorni
 +    const pcWeeks = Math.floor(totalPostConceptionalDays / 7);
 +    const pcDays = totalPostConceptionalDays % 7;
 +    
 +    const pcAge = pcWeeks + '+' + pcDays;
 +    document.getElementById('postConceptionalAge').value = pcAge + ' sett.';
 +    
 +    return { weeks: pcWeeks, days: pcDays, format: pcAge };
 } }
  
Linea 1501: Linea 2395:
                           doctorsData[prescribingDoctorValue].fullName : '';                           doctorsData[prescribingDoctorValue].fullName : '';
          
-    patientData = { + 
-        medicalRecord: medicalRecord, +// Recupera età gestazionale per i report 
-        birthWeight: phaseBirthWeight,  +const gestationalWeeks = parseInt(document.getElementById('gestationalWeeks').value) || null; 
-        currentWeight: phaseCurrentWeight,  +const gestationalDays = parseInt(document.getElementById('gestationalDays').value) || null; 
-        daysOfLife: daysOfLife, + 
-        bun: bun, +// Calcola età post-concezionale 
-        glucose: glucose, +const postConceptionalAge = calculatePostConceptionalAge(); 
-        sodium: sodium, + 
-        ph: ph, +patientData = { 
-        baseExcess: baseExcess, +    medicalRecord: medicalRecord, 
-        diuresis: diuresis, +    birthWeight: phaseBirthWeight,  
-        prescriptionDate: prescriptionDate, +    currentWeight: phaseCurrentWeight,  
-        prescribingDoctor: prescribingDoctorValue, +    daysOfLife: daysOfLife, 
-        prescribingDoctorName: doctorFullName +    gestationalWeeks: gestationalWeeks, 
-    };+    gestationalDays: gestationalDays, 
 +    postConceptionalAge: postConceptionalAge, 
 +    bun: bun, 
 +    glucose: glucose, 
 +    sodium: sodium, 
 +    ph: ph, 
 +    baseExcess: baseExcess, 
 +    diuresis: diuresis, 
 +    prescriptionDate: prescriptionDate, 
 +    prescribingDoctor: prescribingDoctorValue, 
 +    prescribingDoctorName: doctorFullName 
 +};
          
     document.getElementById('targetDay').value = daysOfLife;     document.getElementById('targetDay').value = daysOfLife;
Linea 1605: Linea 2510:
     phaseInfoHtml += '<p><strong>Peso:</strong> ' + phaseCurrentWeight + 'g (nascita: ' + phaseBirthWeight + 'g)</p>';     phaseInfoHtml += '<p><strong>Peso:</strong> ' + phaseCurrentWeight + 'g (nascita: ' + phaseBirthWeight + 'g)</p>';
     phaseInfoHtml += '<p><strong>Giorni di vita:</strong> ' + daysOfLife + '</p>';     phaseInfoHtml += '<p><strong>Giorni di vita:</strong> ' + daysOfLife + '</p>';
 +    
 +  if (gestationalWeeks && gestationalWeeks > 0) {
 +    const gestDaysDisplay = gestationalDays || 0;
 +    phaseInfoHtml += '<p><strong>Età gestazionale:</strong> ' + gestationalWeeks + '+' + gestDaysDisplay + ' settimane</p>';
 +    if (postConceptionalAge && postConceptionalAge.format) {
 +        phaseInfoHtml += '<p><strong>Età post-concezionale:</strong> ' + postConceptionalAge.format + ' settimane</p>';
 +    }
 +    }
     phaseInfoHtml += '<p><strong>Fase nutrizionale:</strong> ' + phase + '</p>';     phaseInfoHtml += '<p><strong>Fase nutrizionale:</strong> ' + phase + '</p>';
     phaseInfoHtml += '</div>';     phaseInfoHtml += '</div>';
Linea 2158: Linea 3071:
          
     return additions;     return additions;
 +}
 +
 +
 +// FUNZIONE CALCOLO OSMOLARITÀ NPT (MIGLIORATA)
 +function calculateNPTOsmolarity(calc, currentWeightKg, residualNeeds) {
 +    let totalOsmolarity = 0;
 +    let osmolarityBreakdown = {};
 +    let componentDetails = [];
 +    
 +    // Glucosio 50% - osmolarità molto alta
 +    if (calc.neededGlucose > 0) {
 +        const glucoseOsmol = (calc.glucose50Volume * parenteralConfig.glucose50.osmolarity) / calc.totalVolume;
 +        osmolarityBreakdown.glucose = glucoseOsmol;
 +        totalOsmolarity += glucoseOsmol;
 +        componentDetails.push({
 +            name: 'Glucosio 50%',
 +            volume: calc.glucose50Volume,
 +            concentration: parenteralConfig.glucose50.osmolarity,
 +            contribution: glucoseOsmol
 +        });
 +    }
 +    
 +    // Trophamine 6%
 +    const proteinOsmol = (calc.proteinVolume * parenteralConfig.trophamine.osmolarity) / calc.totalVolume;
 +    osmolarityBreakdown.protein = proteinOsmol;
 +    totalOsmolarity += proteinOsmol;
 +    componentDetails.push({
 +        name: 'Trophamine 6%',
 +        volume: calc.proteinVolume,
 +        concentration: parenteralConfig.trophamine.osmolarity,
 +        contribution: proteinOsmol
 +    });
 +    
 +    // Intralipid 20%
 +    const lipidOsmol = (calc.lipidVolume * parenteralConfig.intralipid.osmolarity) / calc.totalVolume;
 +    osmolarityBreakdown.lipid = lipidOsmol;
 +    totalOsmolarity += lipidOsmol;
 +    componentDetails.push({
 +        name: 'Intralipid 20%',
 +        volume: calc.lipidVolume,
 +        concentration: parenteralConfig.intralipid.osmolarity,
 +        contribution: lipidOsmol
 +    });
 +    
 +    // Elettroliti
 +    if (calc.electrolyteAdditions.ca_gluconato > 0) {
 +        const caOsmol = (calc.electrolyteAdditions.ca_gluconato * parenteralConfig.ca_gluconato.osmolarity) / calc.totalVolume;
 +        osmolarityBreakdown.calcium = caOsmol;
 +        totalOsmolarity += caOsmol;
 +        componentDetails.push({
 +            name: 'Calcio Gluconato 10%',
 +            volume: calc.electrolyteAdditions.ca_gluconato,
 +            concentration: parenteralConfig.ca_gluconato.osmolarity,
 +            contribution: caOsmol
 +        });
 +    }
 +    
 +    if (calc.electrolyteAdditions.esafosfina > 0) {
 +        const pOsmol = (calc.electrolyteAdditions.esafosfina * parenteralConfig.esafosfina.osmolarity) / calc.totalVolume;
 +        osmolarityBreakdown.phosphorus = pOsmol;
 +        totalOsmolarity += pOsmol;
 +        componentDetails.push({
 +            name: 'Esafosfina',
 +            volume: calc.electrolyteAdditions.esafosfina,
 +            concentration: parenteralConfig.esafosfina.osmolarity,
 +            contribution: pOsmol
 +        });
 +    }
 +    
 +    if (calc.electrolyteAdditions.mg_sulfate > 0) {
 +        const mgOsmol = (calc.electrolyteAdditions.mg_sulfate * parenteralConfig.mg_sulfate.osmolarity) / calc.totalVolume;
 +        osmolarityBreakdown.magnesium = mgOsmol;
 +        totalOsmolarity += mgOsmol;
 +        componentDetails.push({
 +            name: 'Magnesio Solfato',
 +            volume: calc.electrolyteAdditions.mg_sulfate,
 +            concentration: parenteralConfig.mg_sulfate.osmolarity,
 +            contribution: mgOsmol
 +        });
 +    }
 +    
 +    if (calc.electrolyteAdditions.nacl > 0) {
 +        const naclOsmol = (calc.electrolyteAdditions.nacl * parenteralConfig.nacl.osmolarity) / calc.totalVolume;
 +        osmolarityBreakdown.nacl = naclOsmol;
 +        totalOsmolarity += naclOsmol;
 +        componentDetails.push({
 +            name: 'Sodio Cloruro',
 +            volume: calc.electrolyteAdditions.nacl,
 +            concentration: parenteralConfig.nacl.osmolarity,
 +            contribution: naclOsmol
 +        });
 +    }
 +    
 +    if (calc.electrolyteAdditions.sodium_acetate > 0) {
 +        const naAcetOsmol = (calc.electrolyteAdditions.sodium_acetate * parenteralConfig.sodium_acetate.osmolarity) / calc.totalVolume;
 +        osmolarityBreakdown.sodium_acetate = naAcetOsmol;
 +        totalOsmolarity += naAcetOsmol;
 +        componentDetails.push({
 +            name: 'Sodio Acetato',
 +            volume: calc.electrolyteAdditions.sodium_acetate,
 +            concentration: parenteralConfig.sodium_acetate.osmolarity,
 +            contribution: naAcetOsmol
 +        });
 +    }
 +    
 +    if (calc.electrolyteAdditions.kcl > 0) {
 +        const kclOsmol = (calc.electrolyteAdditions.kcl * parenteralConfig.kcl.osmolarity) / calc.totalVolume;
 +        osmolarityBreakdown.kcl = kclOsmol;
 +        totalOsmolarity += kclOsmol;
 +        componentDetails.push({
 +            name: 'Potassio Cloruro',
 +            volume: calc.electrolyteAdditions.kcl,
 +            concentration: parenteralConfig.kcl.osmolarity,
 +            contribution: kclOsmol
 +        });
 +    }
 +    
 +    // Vitamine e Carnitina (osmolarità bassa)
 +    let vitaminsOsmol = 0;
 +    if (residualNeeds.vitalipid > 0) {
 +        const vitalipidVolume = residualNeeds.vitalipid * currentWeightKg;
 +        const vitOsmol = (vitalipidVolume * 280) / calc.totalVolume;
 +        vitaminsOsmol += vitOsmol;
 +        componentDetails.push({
 +            name: 'Vitalipid N Infant',
 +            volume: vitalipidVolume,
 +            concentration: 280,
 +            contribution: vitOsmol
 +        });
 +    }
 +    
 +    if (residualNeeds.soluvit > 0) {
 +        const soluvitVolume = residualNeeds.soluvit * currentWeightKg;
 +        const solOsmol = (soluvitVolume * 300) / calc.totalVolume;
 +        vitaminsOsmol += solOsmol;
 +        componentDetails.push({
 +            name: 'Soluvit N',
 +            volume: soluvitVolume,
 +            concentration: 300,
 +            contribution: solOsmol
 +        });
 +    }
 +    
 +    if (residualNeeds.peditrace > 0) {
 +        const peditraceVolume = residualNeeds.peditrace * currentWeightKg;
 +        const pedOsmol = (peditraceVolume * 350) / calc.totalVolume;
 +        vitaminsOsmol += pedOsmol;
 +        componentDetails.push({
 +            name: 'Peditrace',
 +            volume: peditraceVolume,
 +            concentration: 350,
 +            contribution: pedOsmol
 +        });
 +    }
 +    
 +    if (vitaminsOsmol > 0) {
 +        osmolarityBreakdown.vitamins = vitaminsOsmol;
 +        totalOsmolarity += vitaminsOsmol;
 +    }
 +    
 +    if (residualNeeds.carnitine > 0) {
 +        const carnitineVolume = (residualNeeds.carnitine * currentWeightKg) / 100;
 +        const carOsmol = (carnitineVolume * parenteralConfig.carnitene.osmolarity) / calc.totalVolume;
 +        osmolarityBreakdown.carnitine = carOsmol;
 +        totalOsmolarity += carOsmol;
 +        componentDetails.push({
 +            name: 'Carnitene',
 +            volume: carnitineVolume,
 +            concentration: parenteralConfig.carnitene.osmolarity,
 +            contribution: carOsmol
 +        });
 +    }
 +    
 +    return {
 +        total: Math.round(totalOsmolarity),
 +        breakdown: osmolarityBreakdown,
 +        details: componentDetails,
 +        isHypertonic: totalOsmolarity > 900,
 +        requiresCVC: totalOsmolarity > 600
 +    };
 } }
  
Linea 2262: Linea 3355:
     }     }
     if (electrolyteAdditions.sodium_acetate > 0) {     if (electrolyteAdditions.sodium_acetate > 0) {
-        resultHtml += '<tr><td><strong>Sodio Acetato (mEq/mL) - Alcalinizzante</strong></td><td><strong>' + electrolyteAdditions.sodium_acetate.toFixed(1) + '</strong></td></tr>';+        resultHtml += '<tr><td><strong>Sodio Acetato (mEq/mL) - Alcalinizzante</strong></td><td><strong>' + electrolyteAdditions.sodium_acetate.toFixed(1) + '</strong></td></tr>';
     }     }
     if (electrolyteAdditions.kcl > 0) {     if (electrolyteAdditions.kcl > 0) {
         resultHtml += '<tr><td><strong>Potassio Cloruro (2 mEq/mL)</strong></td><td><strong>' + electrolyteAdditions.kcl.toFixed(1) + '</strong></td></tr>';         resultHtml += '<tr><td><strong>Potassio Cloruro (2 mEq/mL)</strong></td><td><strong>' + electrolyteAdditions.kcl.toFixed(1) + '</strong></td></tr>';
     }     }
-    +   
     // VITAMINE     // VITAMINE
     if (residualNeeds.vitalipid > 0) {     if (residualNeeds.vitalipid > 0) {
Linea 2281: Linea 3374:
         resultHtml += '<tr><td><strong>Peditrace</strong></td><td><strong>' + peditraceVolume.toFixed(1) + '</strong></td></tr>';         resultHtml += '<tr><td><strong>Peditrace</strong></td><td><strong>' + peditraceVolume.toFixed(1) + '</strong></td></tr>';
     }     }
 +    
          
     // CARNITINA     // CARNITINA
Linea 2297: Linea 3391:
     document.getElementById('parenteralTable').innerHTML = resultHtml;     document.getElementById('parenteralTable').innerHTML = resultHtml;
          
 +    // CALCOLO OSMOLARITÀ
 +const osmolarityData = calculateNPTOsmolarity({
 +    totalVolume: totalVolume,
 +    waterVolume: waterVolume,
 +    glucose50Volume: glucose50Volume,
 +    proteinVolume: proteinVolume,
 +    lipidVolume: lipidVolume,
 +    electrolyteAdditions: electrolyteAdditions
 +}, currentWeightKg, residualNeeds);
 +
 +// AGGIUNGI SEZIONE OSMOLARITÀ
 +let osmolarityHtml = '<div style="margin-top: 20px; padding: 15px; border-radius: 8px; background-color: ';
 +if (osmolarityData.isHypertonic) {
 +    osmolarityHtml += '#ffebee; border-left: 4px solid #f44336;';
 +} else if (osmolarityData.requiresCVC) {
 +    osmolarityHtml += '#fff3e0; border-left: 4px solid #ff9800;';
 +} else {
 +    osmolarityHtml += '#e8f5e8; border-left: 4px solid #4caf50;';
 +}
 +osmolarityHtml += '">';
 +osmolarityHtml += '<h4 style="margin-top: 0; color: #2c3e50;">📊 ANALISI OSMOLARITÀ NPT</h4>';
 +osmolarityHtml += '<div style="display: flex; flex-wrap: wrap; gap: 20px;">';
 +osmolarityHtml += '<div>';
 +osmolarityHtml += '<p><strong>Osmolarità totale:</strong> ' + osmolarityData.total + ' mOsm/L</p>';
 +
 +if (osmolarityData.isHypertonic) {
 +    osmolarityHtml += '<p style="color: #d32f2f; font-weight: bold;"><strong>⚠️ SOLUZIONE IPERTONICA</strong><br>Richiede OBBLIGATORIAMENTE accesso venoso centrale</p>';
 +} else if (osmolarityData.requiresCVC) {
 +    osmolarityHtml += '<p style="color: #f57c00; font-weight: bold;"><strong>⚠️ OSMOLARITÀ ELEVATA</strong><br>Raccomandato accesso venoso centrale</p>';
 +} else {
 +    osmolarityHtml += '<p style="color: #388e3c; font-weight: bold;"><strong>✅ OSMOLARITÀ NORMALE</strong><br>Compatibile con accesso periferico</p>';
 +}
 +
 +osmolarityHtml += '</div>';
 +osmolarityHtml += '<div>';
 +osmolarityHtml += '<p><strong>Contributi principali:</strong></p>';
 +osmolarityData.details.forEach(function(detail) {
 +    if (detail.contribution > 30) { // Mostra contributi > 30 mOsm/L
 +        osmolarityHtml += '<p style="font-size: 13px;">• ' + detail.name + ': ' + Math.round(detail.contribution) + ' mOsm/L</p>';
 +    }
 +});
 +osmolarityHtml += '</div>';
 +osmolarityHtml += '</div>';
 +osmolarityHtml += '</div>';
 +
 +document.getElementById('parenteralTable').innerHTML += osmolarityHtml;
 +
     // CREAZIONE RICETTA PER PREPARAZIONE     // CREAZIONE RICETTA PER PREPARAZIONE
     const deflectorVolume = parseInt(document.getElementById('deflectorVolume').value) || 30;     const deflectorVolume = parseInt(document.getElementById('deflectorVolume').value) || 30;
Linea 2332: Linea 3473:
     }     }
     if (electrolyteAdditions.sodium_acetate > 0) {     if (electrolyteAdditions.sodium_acetate > 0) {
-        preparationHtml += '<tr><td><strong>Sodio Acetato (mEq/mL) - Alcalinizzante</strong></td><td>' + electrolyteAdditions.sodium_acetate.toFixed(1) + '</td><td><strong>' + (electrolyteAdditions.sodium_acetate * ratio).toFixed(1) + '</strong></td></tr>';+        preparationHtml += '<tr><td><strong>Sodio Acetato (mEq/mL) - Alcalinizzante</strong></td><td>' + electrolyteAdditions.sodium_acetate.toFixed(1) + '</td><td><strong>' + (electrolyteAdditions.sodium_acetate * ratio).toFixed(1) + '</strong></td></tr>';
     }     }
     if (electrolyteAdditions.kcl > 0) {     if (electrolyteAdditions.kcl > 0) {
Linea 2362: Linea 3503:
          
     preparationHtml += '<tr class="energy-highlight"><td><strong>TOTALE</strong></td><td><strong>' + totalVolume + ' ml</strong></td><td><strong>' + totalVolumeWithDeflector + ' ml</strong></td></tr>';     preparationHtml += '<tr class="energy-highlight"><td><strong>TOTALE</strong></td><td><strong>' + totalVolume + ' ml</strong></td><td><strong>' + totalVolumeWithDeflector + ' ml</strong></td></tr>';
 +    preparationHtml += '<tr style="background-color: #e3f2fd;"><td><strong>Osmolarità Finale</strong></td><td><strong>' + osmolarityData.total + ' mOsm/L</strong></td><td><strong>-</strong></td></tr>';
 +    preparationHtml += '<tr><td><strong>Velocità infusione</strong></td><td><strong>' + (totalVolume / 24).toFixed(2) + ' ml/h</strong></td><td><strong>-</strong></td></tr>';
 +
 +// Aggiungi avvertenze osmolarità nella tabella di preparazione
 +if (osmolarityData.isHypertonic) {
 +    preparationHtml += '<tr style="background-color: #ffebee; color: #d32f2f; font-weight: bold;"><td colspan="3"><strong>⚠️ OSMOLARITÀ IPERTONICA (' + osmolarityData.total + ' mOsm/L) - SOLO ACCESSO VENOSO CENTRALE</strong></td></tr>';
 +} else if (osmolarityData.requiresCVC) {
 +    preparationHtml += '<tr style="background-color: #fff3e0; color: #f57c00; font-weight: bold;"><td colspan="3"><strong>⚠️ OSMOLARITÀ ELEVATA (' + osmolarityData.total + ' mOsm/L) - RACCOMANDATO ACCESSO VENOSO CENTRALE</strong></td></tr>';
 +} else {
 +    preparationHtml += '<tr style="background-color: #e8f5e8; color: #2e7d32;"><td colspan="3"><strong>✅ OSMOLARITÀ NORMALE (' + osmolarityData.total + ' mOsm/L) - COMPATIBILE CON ACCESSO PERIFERICO</strong></td></tr>';
 +}
     preparationHtml += '</table>';     preparationHtml += '</table>';
          
Linea 2382: Linea 3534:
         vitaminsVolume: vitaminsVolume,         vitaminsVolume: vitaminsVolume,
         carnitineVolume: carnitineVolume,         carnitineVolume: carnitineVolume,
-        deflectorVolume: deflectorVolume+        deflectorVolume: deflectorVolume
 +        osmolarityData: osmolarityData
     };     };
 } }
Linea 2428: Linea 3581:
             '<td><input type="number" id="config_' + key + '_energy" value="' + component.energy + '" step="1" oninput="markConfigChanged(\'parenteral\')"></td>' +             '<td><input type="number" id="config_' + key + '_energy" value="' + component.energy + '" step="1" oninput="markConfigChanged(\'parenteral\')"></td>' +
             '<td><input type="number" id="config_' + key + '_water" value="' + component.water + '" step="1" oninput="markConfigChanged(\'parenteral\')"></td>' +             '<td><input type="number" id="config_' + key + '_water" value="' + component.water + '" step="1" oninput="markConfigChanged(\'parenteral\')"></td>' +
 +            '<td><input type="number" id="config_' + key + '_osmolarity" value="' + (component.osmolarity || 0) + '" step="10" oninput="markConfigChanged(\'parenteral\')" style="background-color: #e8f5e8;"></td>' +
             '<td style="font-size: 11px; color: #7f8c8d; max-width: 200px;">' + (component.description || 'Componente') + '<br><em>' + (component.notes || 'Note') + '</em></td>' +             '<td style="font-size: 11px; color: #7f8c8d; max-width: 200px;">' + (component.description || 'Componente') + '<br><em>' + (component.notes || 'Note') + '</em></td>' +
             '<td><button class="button secondary" onclick="removeParenteralComponent(\'' + key + '\')" style="padding: 5px 10px; font-size: 12px;">Rimuovi</button></td>';             '<td><button class="button secondary" onclick="removeParenteralComponent(\'' + key + '\')" style="padding: 5px 10px; font-size: 12px;">Rimuovi</button></td>';
Linea 2451: Linea 3605:
             '<td style="font-weight: bold; color: #2c3e50;">' + doctor.fullName + '</td>' +             '<td style="font-weight: bold; color: #2c3e50;">' + doctor.fullName + '</td>' +
             '<td><button class="button secondary" onclick="removeDoctor(\'' + key + '\')" style="padding: 5px 10px; font-size: 12px;">Rimuovi</button></td>';             '<td><button class="button secondary" onclick="removeDoctor(\'' + key + '\')" style="padding: 5px 10px; font-size: 12px;">Rimuovi</button></td>';
 +    });
 +}
 +
 +function populateNursesConfigTable() {
 +    const tbody = document.getElementById('nursesConfigTable');
 +    if (!tbody) return;
 +    
 +    tbody.innerHTML = '';
 +    Object.keys(nursesData).forEach(key => {
 +        const nurse = nursesData[key];
 +        const row = tbody.insertRow();
 +        row.innerHTML = '<td><input type="text" id="nurse_' + key + '_name" value="' + nurse.name + '" style="width: 100px;" oninput="markConfigChanged(\'nurses\')"></td>' +
 +            '<td><input type="text" id="nurse_' + key + '_surname" value="' + nurse.surname + '" style="width: 100px;" oninput="markConfigChanged(\'nurses\')"></td>' +
 +            '<td><select id="nurse_' + key + '_title" style="width: 70px;" oninput="markConfigChanged(\'nurses\')">' +
 +                '<option value="Inf."' + (nurse.title === 'Inf.' ? ' selected' : '') + '>Inf.</option>' +
 +                '<option value="Inf. Coord."' + (nurse.title === 'Inf. Coord.' ? ' selected' : '') + '>Inf. Coord.</option>' +
 +                '<option value="Inf. Spec."' + (nurse.title === 'Inf. Spec.' ? ' selected' : '') + '>Inf. Spec.</option>' +
 +            '</select></td>' +
 +            '<td style="font-weight: bold; color: #2c3e50;">' + nurse.fullName + '</td>' +
 +            '<td><button class="button secondary" onclick="removeNurse(\'' + key + '\')" style="padding: 5px 10px; font-size: 12px;">Rimuovi</button></td>';
 +    });
 +}
 +
 +function populatePharmacistsConfigTable() {
 +    const tbody = document.getElementById('pharmacistsConfigTable');
 +    if (!tbody) return;
 +    
 +    tbody.innerHTML = '';
 +    Object.keys(pharmacistsData).forEach(key => {
 +        const pharmacist = pharmacistsData[key];
 +        const row = tbody.insertRow();
 +        row.innerHTML = '<td><input type="text" id="pharmacist_' + key + '_name" value="' + pharmacist.name + '" style="width: 100px;" oninput="markConfigChanged(\'pharmacists\')"></td>' +
 +            '<td><input type="text" id="pharmacist_' + key + '_surname" value="' + pharmacist.surname + '" style="width: 100px;" oninput="markConfigChanged(\'pharmacists\')"></td>' +
 +            '<td><select id="pharmacist_' + key + '_title" style="width: 90px;" oninput="markConfigChanged(\'pharmacists\')">' +
 +                '<option value="Dr. Farm."' + (pharmacist.title === 'Dr. Farm.' ? ' selected' : '') + '>Dr. Farm.</option>' +
 +                '<option value="Dr.ssa Farm."' + (pharmacist.title === 'Dr.ssa Farm.' ? ' selected' : '') + '>Dr.ssa Farm.</option>' +
 +                '<option value="Farm."' + (pharmacist.title === 'Farm.' ? ' selected' : '') + '>Farm.</option>' +
 +            '</select></td>' +
 +            '<td style="font-weight: bold; color: #2c3e50;">' + pharmacist.fullName + '</td>' +
 +            '<td><button class="button secondary" onclick="removePharmacist(\'' + key + '\')" style="padding: 5px 10px; font-size: 12px;">Rimuovi</button></td>';
 +    });
 +}
 +
 +function populateTechniciansConfigTable() {
 +    const tbody = document.getElementById('techniciansConfigTable');
 +    if (!tbody) return;
 +    
 +    tbody.innerHTML = '';
 +    Object.keys(technicianData).forEach(key => {
 +        const technician = technicianData[key];
 +        const row = tbody.insertRow();
 +        row.innerHTML = '<td><input type="text" id="technician_' + key + '_name" value="' + technician.name + '" style="width: 100px;" oninput="markConfigChanged(\'technicians\')"></td>' +
 +            '<td><input type="text" id="technician_' + key + '_surname" value="' + technician.surname + '" style="width: 100px;" oninput="markConfigChanged(\'technicians\')"></td>' +
 +            '<td><select id="technician_' + key + '_title" style="width: 70px;" oninput="markConfigChanged(\'technicians\')">' +
 +                '<option value="Tec."' + (technician.title === 'Tec.' ? ' selected' : '') + '>Tec.</option>' +
 +                '<option value="Tec. Spec."' + (technician.title === 'Tec. Spec.' ? ' selected' : '') + '>Tec. Spec.</option>' +
 +                '<option value="Coord. Tec."' + (technician.title === 'Coord. Tec.' ? ' selected' : '') + '>Coord. Tec.</option>' +
 +            '</select></td>' +
 +            '<td style="font-weight: bold; color: #2c3e50;">' + technician.fullName + '</td>' +
 +            '<td><button class="button secondary" onclick="removeTechnician(\'' + key + '\')" style="padding: 5px 10px; font-size: 12px;">Rimuovi</button></td>';
     });     });
 } }
Linea 2474: Linea 3688:
             buttonId = 'updateDoctorsBtn';             buttonId = 'updateDoctorsBtn';
             buttonText = 'SALVA MODIFICHE MEDICI';             buttonText = 'SALVA MODIFICHE MEDICI';
 +            break;
 +        case 'nurses':
 +            buttonId = 'updateNursesBtn';
 +            buttonText = 'SALVA MODIFICHE INFERMIERE';
 +            break;
 +        case 'pharmacists':
 +            buttonId = 'updatePharmacistsBtn';
 +            buttonText = 'SALVA MODIFICHE FARMACISTI';
 +            break;
 +        case 'technicians':
 +            buttonId = 'updateTechniciansBtn';
 +            buttonText = 'SALVA MODIFICHE TECNICI';
             break;             break;
         case 'system':         case 'system':
Linea 2487: Linea 3713:
     }     }
 } }
 +
  
 function updateEnteralConfig() {  function updateEnteralConfig() { 
Linea 2541: Linea 3768:
             parenteralConfig[key].energy = parseFloat(document.getElementById('config_' + key + '_energy').value);             parenteralConfig[key].energy = parseFloat(document.getElementById('config_' + key + '_energy').value);
             parenteralConfig[key].water = parseFloat(document.getElementById('config_' + key + '_water').value);             parenteralConfig[key].water = parseFloat(document.getElementById('config_' + key + '_water').value);
 +            parenteralConfig[key].osmolarity = parseFloat(document.getElementById('config_' + key + '_osmolarity').value);
                          
             if (JSON.stringify(oldValues) !== JSON.stringify(parenteralConfig[key])) {             if (JSON.stringify(oldValues) !== JSON.stringify(parenteralConfig[key])) {
Linea 2618: Linea 3846:
             button.className = 'button';             button.className = 'button';
             button.innerHTML = 'Aggiorna Lista Medici';             button.innerHTML = 'Aggiorna Lista Medici';
 +        }, 3000);
 +    }
 +}
 +
 +function updateNursesConfig() {
 +    let changesCount = 0;
 +    
 +    Object.keys(nursesData).forEach(key => {
 +        const oldValues = Object.assign({}, nursesData[key]);
 +        
 +        const nameEl = document.getElementById('nurse_' + key + '_name');
 +        if (nameEl) {
 +            const newName = nameEl.value.trim();
 +            const newSurname = document.getElementById('nurse_' + key + '_surname').value.trim();
 +            const newTitle = document.getElementById('nurse_' + key + '_title').value;
 +            
 +            nursesData[key].name = newName;
 +            nursesData[key].surname = newSurname;
 +            nursesData[key].title = newTitle;
 +            nursesData[key].fullName = newTitle + ' ' + newName + ' ' + newSurname;
 +            
 +            if (JSON.stringify(oldValues) !== JSON.stringify(nursesData[key])) {
 +                changesCount++;
 +            }
 +        }
 +    });
 +    
 +    populateNursesConfigTable();
 +    
 +    const button = document.getElementById('updateNursesBtn');
 +    if (button) {
 +        button.className = 'button config-update-completed';
 +        button.innerHTML = 'INFERMIERE SALVATE ✓ (' + changesCount + ' modifiche)';
 +        setTimeout(() => {
 +            button.className = 'button';
 +            button.innerHTML = 'Aggiorna Lista Infermiere';
 +        }, 3000);
 +    }
 +}
 +
 +function updatePharmacistsConfig() {
 +    let changesCount = 0;
 +    
 +    Object.keys(pharmacistsData).forEach(key => {
 +        const oldValues = Object.assign({}, pharmacistsData[key]);
 +        
 +        const nameEl = document.getElementById('pharmacist_' + key + '_name');
 +        if (nameEl) {
 +            const newName = nameEl.value.trim();
 +            const newSurname = document.getElementById('pharmacist_' + key + '_surname').value.trim();
 +            const newTitle = document.getElementById('pharmacist_' + key + '_title').value;
 +            
 +            pharmacistsData[key].name = newName;
 +            pharmacistsData[key].surname = newSurname;
 +            pharmacistsData[key].title = newTitle;
 +            pharmacistsData[key].fullName = newTitle + ' ' + newName + ' ' + newSurname;
 +            
 +            if (JSON.stringify(oldValues) !== JSON.stringify(pharmacistsData[key])) {
 +                changesCount++;
 +            }
 +        }
 +    });
 +    
 +    populatePharmacistsConfigTable();
 +    
 +    const button = document.getElementById('updatePharmacistsBtn');
 +    if (button) {
 +        button.className = 'button config-update-completed';
 +        button.innerHTML = 'FARMACISTI SALVATI ✓ (' + changesCount + ' modifiche)';
 +        setTimeout(() => {
 +            button.className = 'button';
 +            button.innerHTML = 'Aggiorna Lista Farmacisti';
 +        }, 3000);
 +    }
 +}
 +
 +function updateTechniciansConfig() {
 +    let changesCount = 0;
 +    
 +    Object.keys(technicianData).forEach(key => {
 +        const oldValues = Object.assign({}, technicianData[key]);
 +        
 +        const nameEl = document.getElementById('technician_' + key + '_name');
 +        if (nameEl) {
 +            const newName = nameEl.value.trim();
 +            const newSurname = document.getElementById('technician_' + key + '_surname').value.trim();
 +            const newTitle = document.getElementById('technician_' + key + '_title').value;
 +            
 +            technicianData[key].name = newName;
 +            technicianData[key].surname = newSurname;
 +            technicianData[key].title = newTitle;
 +            technicianData[key].fullName = newTitle + ' ' + newName + ' ' + newSurname;
 +            
 +            if (JSON.stringify(oldValues) !== JSON.stringify(technicianData[key])) {
 +                changesCount++;
 +            }
 +        }
 +    });
 +    
 +    populateTechniciansConfigTable();
 +    
 +    const button = document.getElementById('updateTechniciansBtn');
 +    if (button) {
 +        button.className = 'button config-update-completed';
 +        button.innerHTML = 'TECNICI SALVATI ✓ (' + changesCount + ' modifiche)';
 +        setTimeout(() => {
 +            button.className = 'button';
 +            button.innerHTML = 'Aggiorna Lista Tecnici';
         }, 3000);         }, 3000);
     }     }
Linea 2691: Linea 4027:
         autoSave: document.getElementById('autoSave').value,         autoSave: document.getElementById('autoSave').value,
         decimalPlaces: document.getElementById('decimalPlaces').value,         decimalPlaces: document.getElementById('decimalPlaces').value,
-        clinicalConfig: clinicalConfig+        clinicalConfig: clinicalConfig
 +        doctorsData: doctorsData, 
 +        nursesData: nursesData, 
 +        pharmacistsData: pharmacistsData, 
 +        technicianData: technicianData
     };     };
          
Linea 2701: Linea 4041:
     // Simula salvataggio configurazione     // Simula salvataggio configurazione
     window.savedConfig = config;     window.savedConfig = config;
-    alert('Configurazione salvata con successo!');+    alert('Configurazione salvata con successo!\n\n' + 
 +          'Inclusi:\n'
 +          '• ' + Object.keys(doctorsData).length + ' medici\n'
 +          '• ' + Object.keys(nursesData).length + ' infermiere\n'
 +          '• ' + Object.keys(pharmacistsData).length + ' farmacisti\n'
 +          '• ' + Object.keys(technicianData).length + ' tecnici di farmacia');
 } }
  
-// FUNZIONI REPORT (COMPLETE CON TUTTI GLI ELEMENTI) 
 function generatePrescription() { function generatePrescription() {
     if (!window.residualNeeds || !patientData.currentWeight) {     if (!window.residualNeeds || !patientData.currentWeight) {
Linea 2724: Linea 4068:
     birthDate.setDate(birthDate.getDate() - patientData.daysOfLife);     birthDate.setDate(birthDate.getDate() - patientData.daysOfLife);
          
-    const doctorName patientData.prescribingDoctorName ||  +        // Genera ID prescrizione univoco (una sola volta per sessione) 
-                      (patientData.prescribingDoctor && doctorsData[patientData.prescribingDoctor] ?  +    if (!window.currentPrescriptionID) { 
-                       doctorsData[patientData.prescribingDoctor].fullName : 'Non specificato');+        window.currentPrescriptionID = generatePreparationID(); 
 +    } 
 +    const prescriptionID window.currentPrescriptionID; 
 +     
 +    // Recupera il medico attualmente selezionato 
 +    const currentPrescribingDoctor = document.getElementById('prescribingDoctor').value; 
 +    const doctorName = currentPrescribingDoctor && doctorsData[currentPrescribingDoctor] ?  
 +                  doctorsData[currentPrescribingDoctor].fullName :  
 +                  (patientData.prescribingDoctorName || 'Non specificato');
          
     let html = '<div class="report-output">';     let html = '<div class="report-output">';
          
-    // INTESTAZIONE MEDICA ESATTA COME DA PDF+    // INTESTAZIONE MEDICA (già OK secondo le tue indicazioni)
     html += '<div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #2c3e50; padding-bottom: 15px; margin-bottom: 25px;">';     html += '<div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #2c3e50; padding-bottom: 15px; margin-bottom: 25px;">';
          
Linea 2736: Linea 4088:
     html += '<div style="text-align: left;">';     html += '<div style="text-align: left;">';
     html += '<h2 style="margin: 0; font-size: 16px; color: #2c3e50;">Dipartimento Area della Donna e Materno Infantile</h2>';     html += '<h2 style="margin: 0; font-size: 16px; color: #2c3e50;">Dipartimento Area della Donna e Materno Infantile</h2>';
-    html += '<h3 style="margin: 5px 0; font-size: 14px; color: #34495e;">S.C. Neonatologia Terapia Intensiva Neonatale</h3>';+    html += '<h3 style="margin: 5px 0; font-size: 14px; color: #34495e;">S.C. Neonatologia Terapia Intensiva Neonatale</h3>';
     html += '<p style="margin: 5px 0; font-size: 12px; color: #7f8c8d;">Direttore: ' + clinicalConfig.directorName + '</p>';     html += '<p style="margin: 5px 0; font-size: 12px; color: #7f8c8d;">Direttore: ' + clinicalConfig.directorName + '</p>';
     html += '</div>';     html += '</div>';
Linea 2749: Linea 4101:
     // TITOLO DOCUMENTO     // TITOLO DOCUMENTO
     html += '<div style="text-align: center; margin: 20px 0;">';     html += '<div style="text-align: center; margin: 20px 0;">';
-    html += '<h2 style="font-size: 18px; font-weight: bold; color: #2c3e50; margin: 10px 0;">CALCOLO NUTRIZIONALE PARENTERALE</h2>'; +    html += '<h2 style="font-size: 18px; font-weight: bold; color: #2c3e50; margin: 10px 0;">CALCOLO NUTRIZIONALE PARENTERALE Data: ' + currentDate + '</h2>'; 
-    html += '<style="font-size: 14px; color: #7f8c8d; margin: 5px 0;">Data: ' + currentDate + '</p>';+    html += '<h3 style="font-size: 16px; color: #2c3e50; margin: 10px 0;">REPORT PARENTERALE</h3>';
     html += '</div>';     html += '</div>';
          
-    // DATI PAZIENTE +    // INFO PAZIENTE (con cartella clinica e ID prescrizione) 
-    html += '<div style="background-color: #f8f9fa; padding: 15px; border-left4px solid #3498db; margin: 20px 0;">'; +    html += '<div style="border: 2px solid #000; margin: 15px 0;">'; 
-    html += '<h3 style="margin-top0; color: #2c3e50;">DATI PAZIENTE</h3>'; +    html += '<div style="background-color#000; color: white; padding: 5px; font-weight: bold; font-size: 12px;">INFO Paziente</div>'; 
-    html += '<div style="displayflexjustify-contentspace-between;">'; +    html += '<table style="width100%font-size11px; border-collapse: collapse;">'; 
-    html += '<div>'; +    html += '<tr><td style="padding: 3px; width: 200px;">Medico Prescrittore</td><td style="padding: 3px;">' + doctorName + '</td></tr>'; 
-    html += '<p><strong>Medico Prescrittore:</strong> ' + doctorName + '</p>'; +    html += '<tr><td style="padding: 3px;">Data Prescrizione</td><td style="padding: 3px;">' + (patientData.prescriptionDate || currentDate) + '</td></tr>'; 
-    html += '<p><strong>Data Prescrizione:</strong> ' + (patientData.prescriptionDate || currentDate) + '</p>'; +    html += '<tr><td style="padding: 3px;">Data Somministrazione</td><td style="padding3px;">' + currentDate + '</td></tr>'; 
-    html += '<p><strong>N° Cartella:</strong> ' + (patientData.medicalRecord || 'N/A') + '</p>'; +    html += '<tr><td style="padding: 3px;">ID Paziente</td><td style="padding: 3px;">' + (patientData.medicalRecord || 'N/A') + '</td></tr>'; 
-    html += '</div>'; +    if (prescriptionID) { 
-    html +'<div>'; +        html += '<tr><td style="padding: 3px;">ID Prescrizione</td><td style="padding: 3px;"><strong>' + prescriptionID + '</strong></td></tr>'; 
-    html += '<p><strong>Data Nascita:</strong> ' + birthDate.toLocaleDateString('it-IT') + '</p>'; +    } 
-    html += '<p><strong>Età:</strong> ' + patientData.daysOfLife + ' giorni di vita</p>'; +     
-    html += '<p><strong>Peso:</strong> ' + patientData.currentWeight + 'g (' + prescriptionPatientWeightKg.toFixed(3) + ' kg)</p>'; +     
-    html += '</div>'; +    html += '<tr><td style="padding: 3px;">Data di Nascita</td><td style="padding: 3px;">' + birthDate.toLocaleDateString('it-IT') + '</td></tr>'; 
-    html += '</div>';+        html += '<tr><td style="padding3px;">Giorni di Vita</td><td style="padding: 3px;">' + patientData.daysOfLife + '</td></tr>'
 +     
 +   if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) { 
 +    const gestDays = patientData.gestationalDays || 0
 +    html += '<tr><td style="padding3px;">Età Gestazionale</td><td style="padding: 3px;">' + patientData.gestationalWeeks + '+' + gestDays + ' settimane</td></tr>'; 
 +    if (patientData.postConceptionalAge && patientData.postConceptionalAge.format
 +        html +'<tr><td style="padding: 3px;">Età Post-concezionale</td><td style="padding: 3px;">' + patientData.postConceptionalAge.format + ' settimane</td></tr>'; 
 +    } 
 +    } 
 +    html += '<tr><td style="padding: 3px;">Peso (g)</td><td style="padding: 3px;">' + patientData.currentWeight + '</td></tr>'; 
 +    html += '</table>';
     html += '</div>';     html += '</div>';
          
-    // COMPOSIZIONE NPT COMPLETA (TUTTI GLI ELEMENTI DAL TAB 4) +    // LISTA DEGLI APPORTI PER LA GIORNATA CORRENTE 
-    html += '<h3 style="color: #27ae60; margin-top30px;">COMPOSIZIONE NPT</h3>'; +    html += '<div style="border2px solid #000; margin: 15px 0;">'; 
-    html += '<table style="width100%border-collapsecollapsemargin20px 0; font-size: 13px;">'; +    html += '<div style="background-color#000colorwhitepadding5px; font-weight: bold; font-size: 12px;">Lista Degli Apporti per la Giornata Corrente</div>'; 
-    html += '<thead><tr style="background-color#34495ecolorwhite;">'; +    html += '<table style="width: 100%; font-size11pxborder-collapsecollapse;">'; 
-    html += '<th style="border: 1px solid #2c3e50; padding: 10px;">COMPONENTE</th>'; +    html += '<tr><td style="padding: 3pxwidth200pxfont-weightbold;">Apporto</td><td style="padding3pxfont-weightbold; text-align: center;">Quant.</td><td style="padding3pxfont-weightbold;">Somministrazione</td></tr>';
-    html += '<th style="border1px solid #2c3e50padding10px;">VOLUME (ml)</th>'; +
-    html += '<th style="border1px solid #2c3e50padding10px;">CONCENTRAZIONE</th>'; +
-    html += '<th style="border1px solid #2c3e50padding10px;">QUANTITÀ TOTALE</th>'; +
-    html += '</tr></thead><tbody>';+
          
-    // ACQUA BIDISTILLATA +    // Apporti enterali 
-    if (calc.waterVolume > 0) { +    if (enteralData && enteralData.volume > 0) { 
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Acqua Bidistillata</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>' + calc.waterVolume.toFixed(1) + '</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;">-</td><td style="border: 1px solid #2c3e50; padding: 10px;">-</td></tr>';+        const formulaType = document.getElementById('formulaType').value; 
 +        const formulaName = formulaData[formulaType] ? formulaData[formulaType].name : 'Latte'; 
 +        html += '<tr><td style="padding: 3px;">' + formulaName + '</td><td style="padding3pxtext-aligncenter;">'enteralData.volume + ' ml</td><td style="padding: 3px;">oro-naso-gastrica intermittente</td></tr>';
     }     }
          
-    // GLUCOSIO +    // Altri liquidi 
-    if (calc.neededGlucose > 0) { +    if (enteralData && enteralData.additionalFluids > 0) { 
-        html += '<tr><td style="border1px solid #2c3e50padding10px;"><strong>Glucosio</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>' + calc.glucose50Volume.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50padding10px;">50%</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + calc.neededGlucose.toFixed(1) + ' g</td></tr>';+        const fluidType document.getElementById('fluidType').value; 
 +        let fluidName 'Altri liquidi'; 
 +        switch(fluidType) { 
 +            case 'saline'fluidName = 'Soluzione fisiologica'break; 
 +            case 'glucose5'fluidName = 'Glucosio 5%'break; 
 +            case 'glucose10': fluidName = 'Glucosio 10%'; break; 
 +            case 'drugs': fluidName = 'Farmaci in soluzione'; break; 
 +        } 
 +        html += '<tr><td style="padding: 3px;">'fluidName + '</td><td style="padding3pxtext-aligncenter;">' + enteralData.additionalFluids + ' ml</td><td style="padding: 3px;">endovenosa continua</td></tr>';
     }     }
          
-    // PROTEINE +    // Se nessun apporto enterale 
-    html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Trophamine</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>' + calc.proteinVolume.toFixed(1) + '</strong></td><td style="border: 1px solid #2c3e50; padding10px;">6%</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.protein * prescriptionPatientWeightKg).toFixed(1) + ' g</td></tr>';+    if (!enteralData || (enteralData.volume === 0 && enteralData.additionalFluids === 0)) { 
 +        html += '<tr><td style="padding: 3px;">Nessun apporto enterale</td><td style="padding: 3pxtext-aligncenter;">0 ml</td><td style="padding: 3px;">-</td></tr>'; 
 +    }
          
-    // LIPIDI +    html += '</table>'; 
-    html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Intralipid</strong></td><td style="border1px solid #2c3e50; padding: 10px;"><strong>' + calc.lipidVolume.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50; padding: 10px;">20%</td><td style="border1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.lipids prescriptionPatientWeightKg).toFixed(1) + ' g</td></tr>';+    html += '</div>'; 
 +     
 +    // COMPOSIZIONE PARENTERALE (con deflussore) 
 +    const deflectorVolume = parseInt(document.getElementById('deflectorVolume').value) || 30; 
 +    const totalVolumeWithDeflector = calc.totalVolume + deflectorVolume; 
 +    const ratio = totalVolumeWithDeflector / calc.totalVolume; 
 +     
 +    html += '<div style="border: 2px solid #000; margin: 15px 0;">'; 
 +    html += '<div style="background-color: #000; color: white; padding: 5px; font-weight: bold; font-size: 12px;">Composizione Parenterale (numero sacche: 1)</div>'; 
 +    html += '<table style="width: 100%; font-size: 11px; border-collapse: collapse;">'; 
 +    html += '<tr style="border-bottom: 1px solid #000;"><td style="padding: 3px; font-weight: bold;"></td><td style="padding: 3px; font-weight: bold; text-align: center;">Teorici</td><td style="padding: 3px; font-weight: bold; text-align: center;">Con Deflussore</td><td style="padding3pxfont-weight: bold;"></td></tr>'; 
 +     
 +    // Componenti nell'ordine del PDF 
 +    html += '<tr><td style="padding: 3px;">Acqua bidistillata</td><td style="padding: 3px; text-align: center;">' + calc.waterVolume.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>'(calc.waterVolume * ratio).toFixed(2) + '</strong></td><td style="padding3px;">ml</td></tr>'; 
 +     
 +    if (calc.neededGlucose > 0) { 
 +        html += '<tr><td style="padding: 3px;">glucosata 50(parenterale)</td><td style="padding3pxtext-align: center;">' + calc.glucose50Volume.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + (calc.glucose50Volume ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    }
          
-    // ELETTROLITI (SE PRESENTI) 
     if (calc.electrolyteAdditions.ca_gluconato > 0) {     if (calc.electrolyteAdditions.ca_gluconato > 0) {
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Calcio Gluconato 10%</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>' + calc.electrolyteAdditions.ca_gluconato.toFixed(1) + '</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;">100 mg/ml</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.calcium * prescriptionPatientWeightKg).toFixed(1) + ' mg Ca</td></tr>'; +        html += '<tr><td style="padding: 3px;">Calcio gluconato (1g/10mL,0.44mEq/mL)</td><td style="padding: 3pxtext-aligncenter;">' + calc.electrolyteAdditions.ca_gluconato.toFixed(2) + '</td><td style="padding3pxtext-aligncenter;"><strong>' + (calc.electrolyteAdditions.ca_gluconato * ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>';
-    } +
-    if (calc.electrolyteAdditions.esafosfina > 0) { +
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Esafosfina</strong></td><td style="border1px solid #2c3e50; padding: 10px;"><strong>' + calc.electrolyteAdditions.esafosfina.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50padding10px;">100 mg P/ml</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.phosphorus * prescriptionPatientWeightKg).toFixed(1) + ' mg P</td></tr>'; +
-    } +
-    if (calc.electrolyteAdditions.mg_sulfate > 0+
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Magnesio Solfato</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>' + calc.electrolyteAdditions.mg_sulfate.toFixed(1) + '</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;">200 mg/ml</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.magnesium * prescriptionPatientWeightKg).toFixed(1) + ' mEq Mg</td></tr>';+
     }     }
 +    
 +    html += '<tr style="border-top: 1px solid #000;">';
     if (calc.electrolyteAdditions.nacl > 0) {     if (calc.electrolyteAdditions.nacl > 0) {
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Sodio Cloruro</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>' + calc.electrolyteAdditions.nacl.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50padding10px;">5.85 g/100ml</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.sodium * prescriptionPatientWeightKg).toFixed(1) + ' mEq Na</td></tr>'; +        html += '<td style="padding: 3px;">Sodio cloruro (3mEq/mL)</td><td style="padding3pxtext-aligncenter;">' + calc.electrolyteAdditions.nacl.toFixed(2) + '</td><td style="padding3pxtext-aligncenter;"><strong>' + (calc.electrolyteAdditions.nacl * ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
-    } +    } else if (calc.electrolyteAdditions.sodium_acetate > 0) { 
-    if (calc.electrolyteAdditions.sodium_acetate > 0) { +        html += '<td style="padding: 3px;">Sodio acetato (2mEq/mL)</td><td style="padding3pxtext-aligncenter;">' + calc.electrolyteAdditions.sodium_acetate.toFixed(2) + '</td><td style="padding3pxtext-aligncenter;"><strong>' + (calc.electrolyteAdditions.sodium_acetate * ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Sodio Acetato</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>' + calc.electrolyteAdditions.sodium_acetate.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50padding10px;">Alcalinizzante</td><td style="border: 1px solid #2c3e50; padding: 10px;">'(window.residualNeeds.sodium * prescriptionPatientWeightKg).toFixed(1) + mEq Na</td></tr>';+    } else { 
 +        html +'</tr><tr>';
     }     }
 +    
     if (calc.electrolyteAdditions.kcl > 0) {     if (calc.electrolyteAdditions.kcl > 0) {
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Potassio Cloruro</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>' + calc.electrolyteAdditions.kcl.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50padding10px;">149 mg/ml</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.potassium * prescriptionPatientWeightKg).toFixed(1) + ' mEq K</td></tr>';+        html += '<tr><td style="padding: 3px;">Potassio cloruro (2mEq/mL)</td><td style="padding3pxtext-aligncenter;">' + calc.electrolyteAdditions.kcl.toFixed(2) + '</td><td style="padding3pxtext-aligncenter;"><strong>' + (calc.electrolyteAdditions.kcl * ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>';
     }     }
          
-    // VITAMINE (SE PRESENTI) +    if (calc.electrolyteAdditions.mg_sulfate > 0) { 
-    if (window.residualNeeds.vitalipid > 0) { +        html += '<tr><td style="padding: 3px;">Magnesio solfato (2g/10mL,1.6mEq/mL)</td><td style="padding3pxtext-aligncenter;">'calc.electrolyteAdditions.mg_sulfate.toFixed(2) + '</td><td style="padding3pxtext-aligncenter;"><strong>' + (calc.electrolyteAdditions.mg_sulfate ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>';
-        const vitalipidVolume = window.residualNeeds.vitalipid * prescriptionPatientWeightKg; +
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Vitalipid N Infant</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>' + vitalipidVolume.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50padding10px;">Vitamine liposolubili</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.vitalipid prescriptionPatientWeightKg).toFixed(1) + ' ml</td></tr>';+
     }     }
-    if (window.residualNeeds.soluvit > 0) { +     
-        const soluvitVolume = window.residualNeeds.soluvit * prescriptionPatientWeightKg; +    html += '<tr style="border-top: 1px solid #000;">'; 
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Soluvit N</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>'soluvitVolume.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50; padding: 10px;">Vitamine idrosolubili</td><td style="border1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.soluvit * prescriptionPatientWeightKg).toFixed(1) + ' ml</td></tr>';+    if (window.residualNeeds.carnitine > 0) { 
 +        const carnitineVolume (window.residualNeeds.carnitine * prescriptionPatientWeightKg) / 100
 +        html += '<td style="padding: 3px;">Carnitene f</td><td style="padding: 3px; text-align: center;">' + carnitineVolume.toFixed(2) + '</td><td style="padding3pxtext-aligncenter;"><strong>'(carnitineVolume * ratio).toFixed(2) + '</strong></td><td style="padding3px;">ml</td></tr>'; 
 +    } else { 
 +        html += '<td style="padding: 3px;">Carnitene f</td><td style="padding3pxtext-align: center;">0.00</td><td style="padding: 3px; text-align: center;"><strong>0.00</strong></td><td style="padding: 3px;">ml</td></tr>';
     }     }
 +    
 +    html += '<tr><td style="padding: 3px;">Trophamine 6%</td><td style="padding: 3px; text-align: center;">' + calc.proteinVolume.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + (calc.proteinVolume * ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>';
 +    
 +    if (calc.electrolyteAdditions.esafosfina > 0) {
 +        html += '<tr><td style="padding: 3px;">Esafosfina f 5g</td><td style="padding: 3px; text-align: center;">' + calc.electrolyteAdditions.esafosfina.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + (calc.electrolyteAdditions.esafosfina * ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>';
 +    }
 +    
     if (window.residualNeeds.peditrace > 0) {     if (window.residualNeeds.peditrace > 0) {
         const peditraceVolume = window.residualNeeds.peditrace * prescriptionPatientWeightKg;         const peditraceVolume = window.residualNeeds.peditrace * prescriptionPatientWeightKg;
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Peditrace</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>' + peditraceVolume.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50; padding: 10px;">Oligoelementi</td><td style="border1px solid #2c3e50; padding: 10px;">' + (window.residualNeeds.peditrace * prescriptionPatientWeightKg).toFixed(1) + ' ml</td></tr>';+        html += '<tr><td style="padding: 3px;">Peditrace</td><td style="padding: 3px; text-align: center;">' + peditraceVolume.toFixed(2) + '</td><td style="padding3pxtext-aligncenter;"><strong>'(peditraceVolume * ratio).toFixed(2) + '</strong></td><td style="padding3px;">ml</td></tr>'; 
 +    } else { 
 +        html += '<tr><td style="padding: 3px;">Peditrace</td><td style="padding3pxtext-align: center;">0.00</td><td style="padding: 3px; text-align: center;"><strong>0.00</strong></td><td style="padding: 3px;">ml</td></tr>';
     }     }
          
-    // CARNITINA (SE PRESENTE) +    if (window.residualNeeds.soluvit > 0) { 
-    if (window.residualNeeds.carnitine > 0) { +        const soluvitVolume = window.residualNeeds.soluvit * prescriptionPatientWeightKg; 
-        const carnitineVolume (window.residualNeeds.carnitine * prescriptionPatientWeightKg) / 100+        html += '<tr><td style="padding: 3px;">Soluvit</td><td style="padding: 3px; text-align: center;">' + soluvitVolume.toFixed(2) + '</td><td style="padding3pxtext-aligncenter;"><strong>'(soluvitVolume * ratio).toFixed(2) + '</strong></td><td style="padding3px;">ml</td></tr>'; 
-        html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>Carnitene</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>'carnitineVolume.toFixed(1) + '</strong></td><td style="border1px solid #2c3e50; padding: 10px;">100 mg/ml</td><td style="border1px solid #2c3e50; padding: 10px;">' (window.residualNeeds.carnitine * prescriptionPatientWeightKg).toFixed(1) + ' mg</td></tr>';+    } else { 
 +        html += '<tr><td style="padding: 3px;">Soluvit</td><td style="padding: 3px; text-align: center;">0.00</td><td style="padding3pxtext-align: center;"><strong>0.00</strong></td><td style="padding: 3px;">ml</td></tr>'
 +    } 
 +     
 +    if (window.residualNeeds.vitalipid > 0) { 
 +        const vitalipidVolume = window.residualNeeds.vitalipid * prescriptionPatientWeightKg
 +        html += '<tr><td style="padding: 3px;">Vitalipid N</td><td style="padding: 3px; text-align: center;">' + vitalipidVolume.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + (vitalipidVolume * ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    } else { 
 +        html += '<tr><td style="padding: 3px;">Vitalipid N</td><td style="padding: 3px; text-align: center;">0.00</td><td style="padding: 3px; text-align: center;"><strong>0.00</strong></td><td style="padding: 3px;">ml</td></tr>';
     }     }
          
-    // TOTALE +    html += '<tr><td style="padding: 3px;">Intralipid 20%</td><td style="padding3pxtext-aligncenter;">' + calc.lipidVolume.toFixed(2) + '</td><td style="padding3pxtext-aligncenter;"><strong>' + (calc.lipidVolume * ratio).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>';
-    html += '<tr style="background-color: #e8f5e8; font-weight: bold; border-top: 2px solid #27ae60;"><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>TOTALE NPT</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>' + calc.totalVolume + ' ml</strong></td><td style="border1px solid #2c3e50padding10px;"><strong>' + (calc.totalVolume / 24).toFixed(2) + ' ml/h</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>' + window.residualNeeds.energy.toFixed(0) + ' kcal</strong></td></tr>'; +
-    html += '</tbody></table>';+
          
-    // PARAMETRI CLINICI +    // TOTALI 
-    html += '<div style="background-color#fff3cd; border: 1px solid #ffc107border-radius5px; padding: 15pxmargin20px 0;">'+    html += '<tr style="border-top2px solid #000font-weightbold;"><td style="padding: 3px;">Totale</td><td style="padding: 3px; text-aligncenter;">'calc.totalVolume.toFixed(2) + '</td><td style="padding: 3px; text-aligncenter;"><strong>' + totalVolumeWithDeflector.toFixed(2) + '</strong></td><td style="padding3px;">ml</td></tr>'; 
-    html +'<h4 style="margin-top0color#856404;">PARAMETRI CLINICI</h4>'; +    html += '<tr><td style="padding3px;">Deflussore</td><td style="padding: 3px; text-align: center;">' + deflectorVolume + '</td><td style="padding: 3px; text-align: center;">-</td><td style="padding: 3px;">ml</td></tr>'; 
-    html += '<p><strong>GIR:</strong> ' + calc.gir.toFixed(1) + ' mg/kg/min</p>'; +    html += '<tr><td style="padding: 3px;">Velocità infusione</td><td style="padding: 3px; text-align: center;">' + (calc.totalVolume / 24).toFixed(2) + '</td><td style="padding: 3px; text-align: center;">-</td><td style="padding: 3px;">ml/h</td></tr>'; 
-    html += '<p><strong>Velocità infusione:</strong> ' + (calc.totalVolume / 24).toFixed(2) + ' ml/h</p>'; +    html += '<tr><td style="padding3px;">Osmolalità Totale</td><td style="padding: 3px; text-align: center;">' + (calc.osmolarityData ? calc.osmolarityData.total : '---') + '</td><td style="padding: 3px; text-align: center;">-</td><td style="padding3px;">mOsm/L</td></tr>'; 
-    html += '<p><strong>Via di somministrazione:</strongAccesso venoso centrale</p>'+    html += '</table>';
-    html +'<p><strong>Durata:</strong24 ore continue</p>';+
     html += '</div>';     html += '</div>';
          
-    // FIRMA +    // TOTALE ELEMENTI PRO KILO 
-    html += '<div style="margin-top40pxdisplayflexjustify-contentspace-between;">'; +    html += '<div style="border: 2px solid #000; margin: 15px 0;">'; 
-    html += '<div style="text-align: centerwidth200px;">'; +    html += '<div style="background-color#000colorwhitepadding: 5px; font-weightbold; font-size: 12px;">Totale Elementi Pro Kilo</div>'; 
-    html += '<p><strong>Data:</strong> ' + currentDate + '</p>'; +    html += '<table style="width: 100%; font-size: 11px; border-collapse: collapse;">'; 
-    html += '<p><strong>Ora:</strong> ' + currentTime + '</p>'; +     
-    html += '</div>'; +    // Calcola valori totali (enterali + parenterali) per kg 
-    html += '<div style="text-align: centerwidth200px;">'; +    const totalLiquidsPerKg = window.residualNeeds.liquids; 
-    html += '<div style="border-bottom: 1px solid #2c3e50margin-bottom5pxheight40px;"></div>'; +    const totalProteinPerKg = (enteralData ? enteralData.protein : 0) + window.residualNeeds.protein; 
-    html += '<p><strong>Medico Prescrittore</strong><br>' + doctorName + '</p>'; +    const totalLipidsPerKg = (enteralData ? enteralData.lipids : 0) + window.residualNeeds.lipids; 
-    html += '</div>';+    const totalCarbsPerKg = (enteralData ? enteralData.carbs : 0) + window.residualNeeds.carbs; 
 +    const totalCalciumPerKg = (enteralData ? enteralData.calcium : 0) + window.residualNeeds.calcium; 
 +    const totalPhosphorusPerKg = (enteralData ? enteralData.phosphorus : 0) + window.residualNeeds.phosphorus; 
 +    const totalSodiumPerKg = (enteralData ? enteralData.sodium : 0) + window.residualNeeds.sodium; 
 +    const totalPotassiumPerKg = (enteralData ? enteralData.potassium : 0) + window.residualNeeds.potassium; 
 +    const totalMagnesiumPerKg = (enteralData ? enteralData.magnesium : 0) + window.residualNeeds.magnesium; 
 +    const totalCarnitinePerKg = window.residualNeeds.carnitine; 
 +    const totalOligoelementsPerKg = window.residualNeeds.peditrace; 
 +    const totalVitLiposolubiliPerKg = window.residualNeeds.vitalipid; 
 +    const totalVitIdrosolubiliPerKg = window.residualNeeds.soluvit; 
 +     
 +    // Energia totale e non proteiche 
 +    const totalEnergyPerKg = window.residualNeeds.totalEnergyRequirement; 
 +    const nonProteinEnergyPerKg = totalEnergyPerKg - (totalProteinPerKg * 4); 
 +     
 +    html += '<tr><td style="padding: 3px;">Liquidi</td><td style="padding: 3px; text-align: left;">' + totalLiquidsPerKg.toFixed(2) + '</td><td style="padding3px;">mL/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Proteine</td><td style="padding3px; text-align: left;">' + totalProteinPerKg.toFixed(2) + '</td><td style="padding: 3px;">g/kg/die</td></tr>'
 +    html += '<tr><td style="padding: 3px;">Lipidi</td><td style="padding: 3px; text-align: left;">' + totalLipidsPerKg.toFixed(2) + '</td><td style="padding: 3px;">g/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Glucidi</td><td style="padding3px; text-align: left;">' + totalCarbsPerKg.toFixed(2) + '</td><td style="padding: 3px;">g/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Calcio</td><td style="padding: 3px; text-align: left;">' + totalCalciumPerKg.toFixed(2) + '</td><td style="padding: 3px;">mg/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Fosforo</td><td style="padding: 3px; text-align: left;">' + totalPhosphorusPerKg.toFixed(2) + '</td><td style="padding: 3px;">mg/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Sodio</td><td style="padding: 3px; text-align: left;">' + totalSodiumPerKg.toFixed(2) + '</td><td style="padding3px;">mEq/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Potassio</td><td style="padding: 3px; text-align: left;">' + totalPotassiumPerKg.toFixed(2) + '</td><td style="padding: 3px;">mEq/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Magnesio</td><td style="padding: 3px; text-align: left;">' + totalMagnesiumPerKg.toFixed(2) + '</td><td style="padding: 3px;">mEq/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Carnitina</td><td style="padding: 3px; text-align: left;">' + totalCarnitinePerKg.toFixed(2) + '</td><td style="padding: 3px;">mg/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Oligoelementi</td><td style="padding: 3px; text-align: left;">' + totalOligoelementsPerKg.toFixed(2) + '</td><td style="padding: 3px;">mL/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Vit. idrosolubili</td><td style="padding: 3px; text-align: left;">' + totalVitIdrosolubiliPerKg.toFixed(2) + '</td><td style="padding: 3px;">mL/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Vit. liposolubili</td><td style="padding: 3px; text-align: left;">' + totalVitLiposolubiliPerKg.toFixed(2) + '</td><td style="padding: 3px;">mL/kg/die</td></tr>'; 
 +    html += '<tr style="border-top: 1px solid #000;"><td style="padding: 3px; font-weightbold;">KCal Totali</td><td style="padding3px; text-align: left; font-weight: bold;">' + totalEnergyPerKg.toFixed(2) + '</td><td style="padding: 3px; font-weight: bold;">kcal/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px; font-weight: bold;">KCal non proteiche</td><td style="padding: 3px; text-align: left; font-weight: bold;">' + nonProteinEnergyPerKg.toFixed(2) + '</td><td style="padding: 3px; font-weight: bold;">kcal/kg/die</td></tr>'; 
 +    html += '<tr><td style="padding: 3px; font-weight: bold;">Glucosio (mg/Kg al minuto)</td><td style="padding: 3px; text-align: left; font-weight: bold;">' + calc.gir.toFixed(3) + '</td><td style="padding: 3px; font-weight: bold;">mg/kg/min</td></tr>'; 
 +    html += '</table>';
     html += '</div>';     html += '</div>';
 +    
     html += '</div>';     html += '</div>';
          
Linea 2871: Linea 4303:
     }     }
          
 +    const currentDate = new Date().toLocaleDateString('it-IT');
     const calc = window.nptCalculation;     const calc = window.nptCalculation;
 +    
     if (!calc) {     if (!calc) {
         alert('Prima calcolare la NPT nel TAB 4');         alert('Prima calcolare la NPT nel TAB 4');
         return;         return;
     }     }
-     
-    const currentDate = new Date().toLocaleDateString('it-IT'); 
-    const currentTime = new Date().toLocaleTimeString('it-IT'); 
-    const worksheetPatientWeightKg = patientData.currentWeight / 1000; 
          
     const birthDate = new Date();     const birthDate = new Date();
     birthDate.setDate(birthDate.getDate() - patientData.daysOfLife);     birthDate.setDate(birthDate.getDate() - patientData.daysOfLife);
          
-    const deflectorVolume calc.deflectorVolume || 30+   // Recupera il medico attualmente selezionato 
-    const totalVolumeWithDeflector calc.totalVolume + deflectorVolume; +        const currentPrescribingDoctor document.getElementById('prescribingDoctor').value
-    const ratio = totalVolumeWithDeflector / calc.totalVolume;+        const doctorName currentPrescribingDoctor && doctorsData[currentPrescribingDoctor] ?  
 +                  doctorsData[currentPrescribingDoctor].fullName :  
 +                  (patientData.prescribingDoctorName || 'Medico non specificato')
          
-    let html = '<div class="report-output">'; +    // Genera ID prescrizione per il foglio di lavoro 
-    html += '<div class="medical-header">'; +    // Usa lo stesso ID prescrizione della sessione 
-    html += '<h1>' + clinicalConfig.hospitalName + '</h1>'; +        if (!window.currentPrescriptionID) { 
-    html += '<h2>'clinicalConfig.departmentName + '</h2>';+            window.currentPrescriptionID = generatePreparationID(); 
 +        } 
 +        const worksheetPreparationID = window.currentPrescriptionID; 
 +                 
 +        let html = '<div class="report-output">'; 
 +     
 +    // INTESTAZIONE ASST LECCO 
 +    html += '<table class="medical-header-table">'; 
 +    html += '<tr>'
 +    html +'<td class="medical-header-left">'; 
 +    html += '<h2><strong>Dipartimento Area della Donna e Materno Infantile</strong></h2>'
 +    html +'<h3>S.C. Neonatologia e Terapia Intensiva Neonatale</h3>';
     html += '<p>Direttore: ' + clinicalConfig.directorName + '</p>';     html += '<p>Direttore: ' + clinicalConfig.directorName + '</p>';
 +    html += '</td>';
 +    html += '<td class="medical-header-center">';
 +    html += '<div style="text-align: center;">';
 +    html += '<div style="width: 80px; height: 60px; background-color: #4CAF50; border-radius: 10px; margin: 0 auto 5px auto; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; text-align: center;">LOGO<br>REGIONE<br>LOMBARDIA</div>';
 +    html += '<div style="font-size: 10px; color: #2c3e50;">Sistema Socio Sanitario<br><strong>Regione Lombardia<br>ASST Lecco</strong></div>';
 +    html += '</td>';
 +    html += '<td class="medical-header-right">';
 +    html += '<div style="text-align: center;">';
 +    html += '<div style="width: 60px; height: 60px; background-color: #9C27B0; border-radius: 50%; margin: 0 auto 5px auto; display: flex; align-items: center; justify-content: center; color: white; font-size: 8px; text-align: center;">LOGO<br>BANCA<br>LATTE</div>';
 +    html += '<div style="font-size: 9px; color: #9C27B0;"><strong>Banca del<br>Latte<br>Lecco</strong></div>';
 +    html += '</td>';
 +    html += '</tr>';
 +    html += '</table>';
 +    
 +    // TITOLO E DATA
 +    html += '<div style="border-bottom: 2px solid #000; padding-bottom: 10px; margin-bottom: 20px;">';
 +    html += '<div style="display: flex; justify-content: space-between; align-items: center;">';
 +    html += '<h2 style="margin: 0; font-size: 14px;">CALCOLO NUTRIZIONALE PARENTERALE Data: ' + currentDate + '</h2>';
 +    html += '</div>';
     html += '</div>';     html += '</div>';
          
-    html += '<div style="text-align: center; font-size: 20px; font-weight: bold; color: #2c3e50; margin: 20px 0; text-transformuppercase;">RICETTA PER PREPARAZIONE NPT</div>';+    html += '<h3 style="margin: 20px 0 10px 0; font-size14px;">FOGLIO DI LAVORO</h3>';
          
-    html += '<div style="background-color: #f8f9fa; padding: 15pxborder-left4px solid #3498dbmargin20px 0;">'; +    // INFO PAZIENTE 
-    html += '<h3 style="margin-top0color#2c3e50;">INFORMAZIONI PAZIENTE</h3>'; +    html += '<div style="border: 2px solid #000; margin: 10px 0;">'; 
-    html += '<p><strong>Data e Ora:</strong> ' + currentDate + ' ' + currentTime + '</p>'; +    html += '<div style="background-color: #000; color: white; padding: 5pxfont-weightboldfont-size12px;">INFO Paziente</div>'; 
-    html += '<p><strong>Cartella:</strong> ' + (patientData.medicalRecord || 'N/A') + '</p>'; +    html += '<table style="width: 100%; font-size11pxborder-collapsecollapse;">'; 
-    html += '<p><strong>Peso:</strong> ' + patientData.currentWeight + '(' + worksheetPatientWeightKg.toFixed(3) + ' kg)</p>'; +    html += '<tr><td style="padding: 3px; width: 200px;">Medico Prescrittore</td><td style="padding: 3px;">' + doctorName + '</td></tr>'; 
-    html += '<p><strong>Giorni di vita:</strong> ' + patientData.daysOfLife + '</p>';+    html += '<tr><td style="padding: 3px;">Data Prescrizione</td><td style="padding: 3px;">' + currentDate + '</td></tr>'
 +    html += '<tr><td style="padding: 3px;">Data Somministrazione</td><td style="padding: 3px;">' + currentDate + '</td></tr>'; 
 +    if (worksheetPreparationID) { 
 +    html += '<tr><td style="padding: 3px;"><strong>ID Prescrizione</strong></td><td style="padding: 3px; font-weight: bold; font-family: monospace;">' + worksheetPreparationID + '</td></tr>'; 
 +    } 
 +    html += '<tr><td style="padding: 3px;">ID Paziente</td><td style="padding: 3px;">' + (patientData.medicalRecord || 'PAZIENTE') + '</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Data di Nascita</td><td style="padding3px;">' + birthDate.toLocaleDateString('it-IT') + '</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Giorni di Vita</td><td style="padding: 3px;">' + patientData.daysOfLife + '</td></tr>'; 
 +         
 +    if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) { 
 +    const gestDays = patientData.gestationalDays || 0; 
 +    html += '<tr><td style="padding: 3px;">Età Gestazionale</td><td style="padding: 3px;">' + patientData.gestationalWeeks + '+' + gestDays + ' settimane</td></tr>'; 
 +    if (patientData.postConceptionalAge && patientData.postConceptionalAge.format
 +        html +'<tr><td style="padding: 3px;">Età Post-concezionale</td><td style="padding: 3px;">' + patientData.postConceptionalAge.format + ' settimane</td></tr>'; 
 +    } 
 +    } 
 +    html += '<tr><td style="padding3px;">Peso (g)</td><td style="padding: 3px;">' + patientData.currentWeight + '</td></tr>'; 
 +    html += '</table>';
     html += '</div>';     html += '</div>';
          
-    html += '<div style="background-color: #fff3cd; border: 1px solid #ffc107border-radius5px; padding: 15pxmargin20px 0;">'; +    // COMPOSIZIONE PARENTERALE - FORMATO FOGLIO DI LAVORO 
-    html += '<h4 style="margin-top: 0; color: #856404;">PARAMETRI NUTRIZIONALI</h4>'; +    html += '<div style="border: 2px solid #000; margin: 10px 0;">'; 
-    html += '<p><strong>GIR:</strong> ' + calc.gir.toFixed(1) + ' mg/kg/min</p>'; +    html += '<div style="background-color: #000; color: white; padding: 5px; font-weight: bold; font-size: 12px;">Composizione Parenterale (numero sacche: 1)</div>'; 
-    html += '<p><strong>Velocità infusione:</strong> ' + (calc.totalVolume / 24).toFixed(2) + ' ml/h</p>'; +    html += '<table style="width: 100%; font-size: 11px; border-collapse: collapse;">'; 
-    html += '<p><strong>Durata:</strong24 ore continue</p>';+    html += '<tr style="border-bottom: 1px solid #000;"><td style="padding: 3px; font-weightbold;"></td><td style="padding: 3pxfont-weightbold; text-align: center;">Teorici</td><td style="padding: 3px; font-weight: bold; text-align: center;">Con Deflussore</td></tr>'; 
 +     
 +    // Ordine esatto come nel PDF del foglio di lavoro 
 +    html += '<tr><td style="padding: 3px;">Acqua bidistillata</td><td style="padding: 3px; text-align: center;">' + calc.waterVolume.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + (calc.waterVolume * 1.063).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">glucosata 50% (parenterale)</td><td style="padding: 3px; text-align: center;">' + calc.glucose50Volume.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + (calc.glucose50Volume * 1.063).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Calcio gluconato (1g/10mL,0.44mEq/mL)</td><td style="padding: 3px; text-align: center;">' + (calc.electrolyteAdditions.ca_gluconato || 19.83).toFixed(2) + '</td><td style="padding: 3pxtext-align: center;"><strong>' + ((calc.electrolyteAdditions.ca_gluconato || 19.83) * 1.063).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +     
 +    html += '<tr style="border-top: 1px solid #000;"><td style="padding: 3px;">Sodio cloruro (3mEq/mL)</td><td style="padding: 3px; text-align: center;">' + (calc.electrolyteAdditions.nacl || 1.09).toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + ((calc.electrolyteAdditions.nacl || 1.09) * 1.063).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Potassio cloruro (2mEq/mL)</td><td style="padding: 3px; text-align: center;">' + (calc.electrolyteAdditions.kcl || 2.94).toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + ((calc.electrolyteAdditions.kcl || 2.94) * 1.063).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Magnesio solfato (2g/10mL,1.6mEq/mL)</td><td style="padding: 3px; text-align: center;">' + (calc.electrolyteAdditions.mg_sulfate || 0.64).toFixed(2) + '</td><td style="padding: 3pxtext-aligncenter;"><strong>' + ((calc.electrolyteAdditions.mg_sulfate || 0.64) * 1.063).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +     
 +    html += '<tr style="border-top: 1px solid #000;"><td style="padding: 3px;">Carnitene f</td><td style="padding: 3px; text-align: center;">0.36</td><td style="padding: 3px; text-align: center;"><strong>0.38</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Trophamine 6%</td><td style="padding: 3px; text-align: center;">' + calc.proteinVolume.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + (calc.proteinVolume * 1.063).toFixed(2) + '</strong></td><td style="padding3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Esafosfina f 5g</td><td style="padding: 3px; text-align: center;">' + (calc.electrolyteAdditions.esafosfina || 9.96).toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>'((calc.electrolyteAdditions.esafosfina || 9.96) * 1.063).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Peditrace</td><td style="padding: 3px; text-align: center;">3.55</td><td style="padding: 3px; text-align: center;"><strong>3.77</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Soluvit</td><td style="padding: 3px; text-align: center;">7.1</td><td style="padding: 3px; text-align: center;"><strong>7.55</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Vitalipid N</td><td style="padding: 3px; text-align: center;">17.75</td><td style="padding: 3px; text-align: center;"><strong>18.87</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Intralipid 20%</td><td style="padding: 3px; text-align: center;">' + calc.lipidVolume.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + (calc.lipidVolume * 1.063).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +     
 +    html += '<tr style="border-top: 2px solid #000; font-weight: bold;"><td style="padding: 3px;">Totale</td><td style="padding: 3px; text-align: center;">' + calc.totalVolume.toFixed(2) + '</td><td style="padding: 3px; text-align: center;"><strong>' + (calc.totalVolume * 1.063).toFixed(2) + '</strong></td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Deflussore</td><td style="padding: 3px; text-align: center;">30</td><td style="padding: 3px; text-align: center;">-</td><td style="padding: 3px;">ml</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Velocità infusione</td><td style="padding: 3px; text-align: center;">' + (calc.totalVolume / 24).toFixed(2) + '</td><td style="padding: 3px; text-align: center;">-</td><td style="padding: 3px;">ml/h</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Osmolalità Totale</td><td style="padding3px; text-align: center;">' + (window.nptCalculation && window.nptCalculation.osmolarityData ? window.nptCalculation.osmolarityData.total : '---') + '</td><td style="padding: 3px; text-align: center;">-</td><td style="padding: 3px;">mOsm/L</td></tr>'; 
 +    html += '</table>';
     html += '</div>';     html += '</div>';
          
-    html += '<table style="width: 100%; border-collapse: collapse; margin: 20px 0; font-size: 13px;">'; +    html += '</div>';
-    html += '<thead><tr style="background-color: #34495e; color: white;">'; +
-    html += '<th style="border: 1px solid #2c3e50; padding: 10px;">COMPONENTE</th>'; +
-    html += '<th style="border: 1px solid #2c3e50; padding: 10px;">CONCENTRAZIONE</th>'; +
-    html += '<th style="border: 1px solid #2c3e50; padding: 10px;">VOLUME PRESCRIZIONE</th>'; +
-    html += '<th style="border: 1px solid #2c3e50; padding: 10px;">VOLUME PREPARAZIONE</th>'; +
-    html += '<th style="border: 1px solid #2c3e50; padding: 10px;">ORDINE</th>'; +
-    html += '</tr></thead><tbody>';+
          
-    html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;">Acqua Bidistillata</td><td style="border: 1px solid #2c3e50; padding: 10px;">-</td><td style="border: 1px solid #2c3e50; padding: 10px;">+ Math.max(0, calc.waterVolume).toFixed(1) + ' ml</td><td style="border: 1px solid #2c3e50padding: 10px;">' + Math.max(0, calc.waterVolume * ratio).toFixed(1+ ' ml</td><td style="border: 1px solid #2c3e50padding: 10px;">1°</td></tr>';+    document.getElementById('reportOutput').innerHTML html; 
 +
 + 
 +function generateLabel() { 
 +    if (!window.residualNeeds || !patientData.currentWeight
 +        alert('Prima completare tutti i calcoli precedenti'); 
 +        return; 
 +    }
          
-    if (calc.neededGlucose > 0{ +    const currentDate = new Date().toLocaleDateString('it-IT'); 
-        html += '<tr><td style="border1px solid #2c3e50; padding10px;">Glucosio</td><td style="border: 1px solid #2c3e50; padding: 10px;">50%</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + calc.glucose50Volume.toFixed(1) + ' ml</td><td style="border: 1px solid #2c3e50padding: 10px;">'(calc.glucose50Volume * ratio).toFixed(1+ ' ml</td><td style="border: 1px solid #2c3e50padding: 10px;">2°</td></tr>';+    const currentTime new Date().toLocaleTimeString('it-IT', { hour'2-digit', minute'2-digit' }); 
 +    const calc window.nptCalculation; 
 +     
 +    if (!calc) 
 +        alert('Prima calcolare la NPT nel TAB 4'); 
 +        return;
     }     }
          
-    html +'<tr><td style="border: 1px solid #2c3e50; padding: 10px;">Trophamine</td><td style="border: 1px solid #2c3e50; padding: 10px;">6%</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + calc.proteinVolume.toFixed(1+ ' ml</td><td style="border: 1px solid #2c3e50padding: 10px;">'(calc.proteinVolume * ratio).toFixed(1+ ' ml</td><td style="border: 1px solid #2c3e50; padding: 10px;">3°</td></tr>';+    const birthDate new Date(); 
 +    birthDate.setDate(birthDate.getDate(- patientData.daysOfLife);
          
-    html += '<tr><td style="border: 1px solid #2c3e50; padding: 10px;">Intralipid</td><td style="border: 1px solid #2c3e50; padding: 10px;">20%</td><td style="border: 1px solid #2c3e50; padding: 10px;">' + calc.lipidVolume.toFixed(1) + ml</td><td style="border: 1px solid #2c3e50; padding: 10px;">+ (calc.lipidVolume * ratio).toFixed(1) + ' ml</td><td style="border1px solid #2c3e50; padding: 10px;"><strong>4° ULTIMO</strong></td></tr>';+    // Recupera il medico attualmente selezionato 
 +    const currentPrescribingDoctor document.getElementById('prescribingDoctor').value; 
 +    const doctorName currentPrescribingDoctor && doctorsData[currentPrescribingDoctor] ?  
 +              doctorsData[currentPrescribingDoctor].fullName  
 +              (patientData.prescribingDoctorName || 'Medico non specificato');
          
-    html += '<tr style="background-color: #e8f5e8; font-weight: bold; border-top: 2px solid #27ae60;"><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>TOTALE</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;">-</td><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>' + calc.totalVolume + ' ml</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;"><strong>' + totalVolumeWithDeflector + ' ml</strong></td><td style="border: 1px solid #2c3e50; padding: 10px;">-</td></tr>'+    // Usa lo stesso ID prescrizione della sessione 
-    html +'</tbody></table>';+    if (!window.currentPrescriptionID) { 
 +        window.currentPrescriptionID generatePreparationID()
 +    
 +    const labelPreparationID window.currentPrescriptionID;
          
-    html += '<div style="background-color#fff3cd; border: 1px solid #ffc107border-radius5pxpadding: 15px; margin: 20px 0;">'; +    let html = '<div class="report-output">'; 
-    html += '<h4 style="margin-top: 0; color#856404;">AVVERTENZE</h4>'+     
-    html += '<ul>'; +    // INTESTAZIONE COMPATTA PER ETICHETTA 
-    html +'<li>Preparazione sterile in cappa a flusso laminare</li>'; +    html += '<div style="text-aligncenter; border-bottom3px solid #000padding-bottom10pxmargin-bottom: 15px;">'; 
-    html += '<li>Seguire rigorosamente l\'ordine di aggiunta</li>'; +    html += '<h1 style="margin: 0; font-size20px; font-weight: bold;">'clinicalConfig.hospitalName + '</h1>'; 
-    html +'<li>Intralipid sempre per ultimo</li>'; +    html += '<h2 style="margin: 5px 0; font-size: 16px;">' + clinicalConfig.departmentName + '</h2>'; 
-    html += '<li>Conservare a 2-8°C, usare entro 24 ore</li>'; +    html += '<h3 style="margin: 5px 0; font-size: 14pxcolor: #d32f2f; font-weight: bold;">🏷️ ETICHETTA SACCA NPT</h3>';
-    html += '</ul>';+
     html += '</div>';     html += '</div>';
          
-    html += '<div style="margin-top: 40pxdisplayflexjustify-contentspace-between;">'; +     
-    html += '<div style="text-align: centerwidth200px;">'; +    // SEZIONE IDENTIFICAZIONE PAZIENTE - GRANDE E VISIBILE 
-    html += '<div style="border-bottom1px solid #2c3e50margin-bottom: 5px; height40px;"></div>'; +    html += '<div style="border: 4px solid #d32f2f; background-color: #ffebee; padding: 15px; margin: 15px 0; text-align: center;">'; 
-    html += '<p><strong>Preparato da</strong><br>Farmacista</p>';+    html += '<h2 style="margin: 0 0 10px 0; font-size: 18px; color: #d32f2f;">👤 IDENTIFICAZIONE PAZIENTE</h2>'; 
 + 
 +    // CODICE A BARRE per cartella clinica 
 +    if (patientData.medicalRecord && patientData.medicalRecord.trim() !== '') { 
 +        html += '<div style="margin: 15px 0; padding: 10px; background-color: white; border: 2px solid #d32f2f; border-radius: 5px;">'; 
 +        html += '<canvas id="barcodeCanvas" style="max-width: 100%; height: 60px;"></canvas>'; 
 +        html += '<div style="font-size: 12px; color: #666; margin-top: 5px;">Codice a barre cartella clinica</div>'; 
 +        html += '</div>'; 
 +    } 
 + 
 +    html += '<table style="width100%font-size14px; font-weight: bold;">'; 
 +    html += '<tr><td style="text-align: leftpadding5px;">CARTELLA CLINICA:</td><td style="text-align: right; padding: 5px; font-family: monospace; font-size: 16px;">' + (patientData.medicalRecord || 'N/A') + '</td></tr>'; 
 + 
 +    if (labelPreparationID) { 
 +        html += '<tr><td style="text-align: left; padding: 5px;">ID PRESCRIZIONE:</td><td style="text-align: right; padding: 5px; font-family: monospace; font-size: 16px; color: #d32f2f;">' + labelPreparationID + '</td></tr>'; 
 +    } 
 + 
 +    html += '<tr><td style="text-align: left; padding: 5px;">PESO:</td><td style="text-align: right; padding: 5px;">' + patientData.currentWeight + ' g</td></tr>'; 
 +    html += '<tr><td style="text-align: left; padding: 5px;">GIORNI DI VITA:</td><td style="text-align: right; padding: 5px;">' + patientData.daysOfLife + '</td></tr>'; 
 + 
 +    if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) { 
 +        const gestDays = patientData.gestationalDays || 0; 
 +        html += '<tr><td style="text-align: left; padding: 5px;">ETÀ GESTAZIONALE:</td><td style="text-align: right; padding: 5px;">' + patientData.gestationalWeeks + '+' + gestDays + ' sett.</td></tr>'; 
 +        if (patientData.postConceptionalAge && patientData.postConceptionalAge.format) { 
 +            html += '<tr><td style="text-align: left; padding: 5px;">ETÀ POST-CONCEZ.:</td><td style="text-align: right; padding: 5px;">' + patientData.postConceptionalAge.format + ' sett.</td></tr>'; 
 +        } 
 +    } 
 + 
 +    html += '<tr><td style="text-align: left; padding: 5px;">DATA NASCITA:</td><td style="text-align: right; padding: 5px;">' + birthDate.toLocaleDateString('it-IT') + '</td></tr>';   
 +    html += '</table>';
     html += '</div>';     html += '</div>';
-    html += '<div style="text-aligncenterwidth200px;">'; +     
-    html += '<div style="border-bottom1px solid #2c3e50margin-bottom5pxheight40px;"></div>'; +    // SEZIONE PRESCRIZIONE 
-    html += '<p><strong>Controllato da</strong><br>Infermiere</p>';+    html += '<div style="border: 3px solid #1976d2; background-color#e3f2fdpadding: 15px; margin15px 0;">'; 
 +    html += '<h3 style="margin: 0 0 10px 0; font-size: 16px; color: #1976d2;">📋 DATI PRESCRIZIONE</h3>'; 
 +    html += '<table style="width: 100%; font-size13px;">'; 
 +    html += '<tr><td style="padding3px; width: 40%;">Medico Prescrittore:</td><td style="padding: 3px; font-weight: bold;">' + doctorName + '</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Data Prescrizione:</td><td style="padding: 3px; font-weight: bold;">' + (patientData.prescriptionDate || currentDate) + '</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Data Preparazione:</td><td style="padding: 3px; font-weight: bold;">' + currentDate + '</td></tr>'; 
 +    html += '<tr><td style="padding: 3px;">Ora Preparazione:</td><td style="padding: 3px; font-weight: bold;">' + currentTime + '</td></tr>'; 
 +    html += '</table>';
     html += '</div>';     html += '</div>';
 +    
 +    // SEZIONE CONTENUTO SACCA - COMPATTA
 +    html += '<div style="border: 3px solid #388e3c; background-color: #e8f5e8; padding: 15px; margin: 15px 0;">';
 +    html += '<h3 style="margin: 0 0 10px 0; font-size: 16px; color: #388e3c;">💉 CONTENUTO SACCA NPT</h3>';
 +    html += '<table style="width: 100%; font-size: 12px; border-collapse: collapse;">';
 +    html += '<tr style="background-color: #c8e6c9; font-weight: bold;"><td style="padding: 5px; border: 1px solid #4caf50;">COMPONENTE</td><td style="padding: 5px; border: 1px solid #4caf50; text-align: center;">VOLUME (ml)</td></tr>';
 +    
 +    // Solo componenti principali per l'etichetta
 +    if (calc.neededGlucose > 0) {
 +        html += '<tr><td style="padding: 4px; border: 1px solid #4caf50;">Glucosio 50%</td><td style="padding: 4px; border: 1px solid #4caf50; text-align: center; font-weight: bold;">' + calc.glucose50Volume.toFixed(1) + '</td></tr>';
 +    }
 +    html += '<tr><td style="padding: 4px; border: 1px solid #4caf50;">Trophamine 6%</td><td style="padding: 4px; border: 1px solid #4caf50; text-align: center; font-weight: bold;">' + calc.proteinVolume.toFixed(1) + '</td></tr>';
 +    html += '<tr><td style="padding: 4px; border: 1px solid #4caf50;">Intralipid 20%</td><td style="padding: 4px; border: 1px solid #4caf50; text-align: center; font-weight: bold;">' + calc.lipidVolume.toFixed(1) + '</td></tr>';
 +    html += '<tr><td style="padding: 4px; border: 1px solid #4caf50;">Acqua Bidistillata</td><td style="padding: 4px; border: 1px solid #4caf50; text-align: center; font-weight: bold;">' + calc.waterVolume.toFixed(1) + '</td></tr>';
 +    
 +    // Elettroliti principali
 +    if (calc.electrolyteAdditions.ca_gluconato > 0) {
 +        html += '<tr><td style="padding: 4px; border: 1px solid #4caf50;">Calcio Gluconato</td><td style="padding: 4px; border: 1px solid #4caf50; text-align: center; font-weight: bold;">' + calc.electrolyteAdditions.ca_gluconato.toFixed(1) + '</td></tr>';
 +    }
 +    if (calc.electrolyteAdditions.esafosfina > 0) {
 +        html += '<tr><td style="padding: 4px; border: 1px solid #4caf50;">Esafosfina</td><td style="padding: 4px; border: 1px solid #4caf50; text-align: center; font-weight: bold;">' + calc.electrolyteAdditions.esafosfina.toFixed(1) + '</td></tr>';
 +    }
 +    
 +    html += '<tr style="background-color: #4caf50; color: white; font-weight: bold;"><td style="padding: 6px; border: 1px solid #2e7d32;">VOLUME TOTALE</td><td style="padding: 6px; border: 1px solid #2e7d32; text-align: center; font-size: 14px;">' + calc.totalVolume + ' ml</td></tr>';
 +    html += '</table>';
     html += '</div>';     html += '</div>';
 +    
     html += '</div>';     html += '</div>';
          
     document.getElementById('reportOutput').innerHTML = html;     document.getElementById('reportOutput').innerHTML = html;
 +// Genera il codice a barre se presente la cartella clinica
 +if (patientData.medicalRecord && patientData.medicalRecord.trim() !== '') {
 +    setTimeout(() => {
 +        const canvas = document.getElementById('barcodeCanvas');
 +        if (canvas && window.SimpleBarcode) {
 +            try {
 +                window.SimpleBarcode.generate(canvas, patientData.medicalRecord, {
 +                    width: 2,
 +                    height: 60,
 +                    margin: 5,
 +                    background: "#ffffff",
 +                    lineColor: "#000000"
 +                });
 +                console.log('✅ Codice a barre generato per cartella:', patientData.medicalRecord);
 +            } catch (error) {
 +                console.error('❌ Errore generazione codice a barre:', error);
 +                // Fallback: mostra solo il testo
 +                const ctx = canvas.getContext('2d');
 +                ctx.fillStyle = '#000000';
 +                ctx.font = '14px monospace';
 +                ctx.textAlign = 'center';
 +                ctx.fillText(patientData.medicalRecord, canvas.width/2, canvas.height/2);
 +            }
 +        } else {
 +            console.error('❌ SimpleBarcode non disponibile');
 +        }
 +    }, 100);
 +}
 +
 +
 +// Genera il codice a barre se presente la cartella clinica
 +if (patientData.medicalRecord && patientData.medicalRecord.trim() !== '') {
 +    setTimeout(() => {
 +        const canvas = document.getElementById('barcodeCanvas');
 +        if (canvas && window.JsBarcode) {
 +            try {
 +                window.JsBarcode(canvas, patientData.medicalRecord, {
 +                    format: "CODE128",
 +                    displayValue: false,
 +                    width: 2,
 +                    height: 60,
 +                    margin: 5,
 +                    background: "#ffffff",
 +                    lineColor: "#000000"
 +                });
 +                console.log('Codice a barre generato per:', patientData.medicalRecord);
 +            } catch (error) {
 +                console.error('Errore generazione codice a barre:', error);
 +                canvas.style.display = 'none';
 +            }
 +        }
 +    }, 100);
 +}
 +
 } }
  
-// FUNZIONE GENERAZIONE PDF (DA VERSIONE 17)+// FUNZIONE GENERAZIONE PDF COMPLETA
 function generatePDF(type) { function generatePDF(type) {
     if (!window.residualNeeds || !patientData.currentWeight) {     if (!window.residualNeeds || !patientData.currentWeight) {
Linea 2981: Linea 4611:
          
     if (type === 'foglio_lavoro') {     if (type === 'foglio_lavoro') {
-        generateFoglioLavoroPDF(doc);+        generateWorksheetPDFContent(doc);
     } else if (type === 'report_parenterale') {     } else if (type === 'report_parenterale') {
-        generateReportParenteralePDF(doc);+        generatePrescriptionPDFContent(doc); 
 +    } else if (type === 'etichetta_sacca') { 
 +        generateLabelPDFContent(doc);
     }     }
          
     // Salva il PDF     // Salva il PDF
-    const fileName = type === 'foglio_lavoro'Foglio_Lavoro_NPT.pdf' : 'Report_Parenterale_NPT.pdf';+    let fileName = ''; 
 +    switch(type) { 
 +        case 'foglio_lavoro': 
 +            fileName 'Foglio_Lavoro_NPT_' + currentDate.replace(/\//g, '-') + '.pdf'; 
 +            break; 
 +        case 'report_parenterale': 
 +            fileName 'Report_Parenterale_NPT_' + currentDate.replace(/\//g, '-') + '.pdf'; 
 +            break; 
 +        case 'etichetta_sacca': 
 +            fileName = 'Etichetta_Sacca_NPT_+ currentDate.replace(/\//g, '-') + '.pdf'
 +            break; 
 +        default: 
 +            fileName = 'NPT_Document.pdf'; 
 +    } 
 +    
     doc.save(fileName);     doc.save(fileName);
 } }
- +// CONTENUTO PDF PRESCRIZIONE MEDICA 
-function generateFoglioLavoroPDF(doc) { +function generatePrescriptionPDFContent(doc) { 
-    // Implementazione semplificata del PDF+    const currentDate = new Date().toLocaleDateString('it-IT'); 
 +    const calc = window.nptCalculation; 
 +    const prescriptionPatientWeightKg = patientData.currentWeight 1000; 
 +     
 +    // Recupera il medico attualmente selezionato 
 +    const currentPrescribingDoctor = document.getElementById('prescribingDoctor').value; 
 +    const doctorName = currentPrescribingDoctor && doctorsData[currentPrescribingDoctor] ?  
 +                  doctorsData[currentPrescribingDoctor].fullName :  
 +                  (patientData.prescribingDoctorName || 'Non specificato'); 
 +     
 +    const birthDate = new Date(); 
 +    birthDate.setDate(birthDate.getDate() - patientData.daysOfLife); 
 +     
 +    if (!window.currentPrescriptionID) { 
 +        window.currentPrescriptionID = generatePreparationID(); 
 +    } 
 +    const prescriptionID = window.currentPrescriptionID; 
 +    
     let yPos = 50;     let yPos = 50;
          
     doc.setFontSize(12);     doc.setFontSize(12);
-    doc.text('FOGLIO DI LAVORO NPT', 20, yPos);+    doc.text('REPORT PARENTERALE', 20, yPos);
     yPos += 20;     yPos += 20;
          
Linea 3005: Linea 4668:
     yPos += 10;     yPos += 10;
     doc.text('Giorni di vita: ' + patientData.daysOfLife, 20, yPos);     doc.text('Giorni di vita: ' + patientData.daysOfLife, 20, yPos);
 +    yPos += 10;
 +    doc.text('Medico: ' + doctorName, 20, yPos);
     yPos += 20;     yPos += 20;
          
-    const calc window.nptCalculation;+    if (prescriptionID) { 
 +        doc.text('ID Prescrizione: ' + prescriptionID, 20, yPos); 
 +        yPos +10; 
 +    } 
 +     
 +    // COMPOSIZIONE NPT 
 +    doc.text('COMPOSIZIONE NPT:', 20, yPos); 
 +    yPos += 15; 
 +    
     doc.text('Volume totale NPT: ' + calc.totalVolume + ' ml', 20, yPos);     doc.text('Volume totale NPT: ' + calc.totalVolume + ' ml', 20, yPos);
     yPos += 10;     yPos += 10;
     doc.text('GIR: ' + calc.gir.toFixed(1) + ' mg/kg/min', 20, yPos);     doc.text('GIR: ' + calc.gir.toFixed(1) + ' mg/kg/min', 20, yPos);
     yPos += 10;     yPos += 10;
-    doc.text('Velocita infusione: ' + (calc.totalVolume / 24).toFixed(2) + ' ml/h', 20, yPos);+    doc.text('Velocità infusione: ' + (calc.totalVolume / 24).toFixed(2) + ' ml/h', 20, yPos); 
 +    yPos += 10; 
 +     
 +    if (calc.osmolarityData) { 
 +        doc.text('Osmolarità: ' + calc.osmolarityData.total + ' mOsm/L', 20, yPos); 
 +        yPos += 10; 
 +    } 
 +     
 +    // Componenti principali 
 +    yPos += 10; 
 +    doc.text('COMPONENTI PRINCIPALI:', 20, yPos); 
 +    yPos += 15; 
 +     
 +    if (calc.neededGlucose > 0) { 
 +        doc.text('Glucosio 50%: ' + calc.glucose50Volume.toFixed(1) + ' ml', 20, yPos); 
 +        yPos += 8; 
 +    } 
 +     
 +    doc.text('Trophamine 6%: ' + calc.proteinVolume.toFixed(1) + ' ml', 20, yPos); 
 +    yPos += 8; 
 +    doc.text('Intralipid 20%: ' + calc.lipidVolume.toFixed(1) + ' ml', 20, yPos); 
 +    yPos += 8; 
 +    doc.text('Acqua Bidistillata: ' + calc.waterVolume.toFixed(1) + ' ml', 20, yPos); 
 +    yPos += 15; 
 +     
 +    // Fabbisogni per kg 
 +    const totalProteinPerKg = (enteralData ? enteralData.protein : 0) + window.residualNeeds.protein; 
 +    const totalLipidsPerKg = (enteralData ? enteralData.lipids : 0) + window.residualNeeds.lipids; 
 +    const totalCarbsPerKg = (enteralData ? enteralData.carbs : 0) + window.residualNeeds.carbs; 
 +    const totalEnergyPerKg = window.residualNeeds.totalEnergyRequirement; 
 +     
 +    doc.text('FABBISOGNI PER KG/DIE:', 20, yPos); 
 +    yPos += 15; 
 +    doc.text('Proteine: ' + totalProteinPerKg.toFixed(2) + ' g/kg/die', 20, yPos); 
 +    yPos += 8; 
 +    doc.text('Lipidi: ' + totalLipidsPerKg.toFixed(2) + ' g/kg/die', 20, yPos); 
 +    yPos += 8; 
 +    doc.text('Glucidi: ' + totalCarbsPerKg.toFixed(2) + ' g/kg/die', 20, yPos); 
 +    yPos += 8; 
 +    doc.text('Energia: ' + totalEnergyPerKg.toFixed(0) + ' kcal/kg/die', 20, yPos);
 } }
  
-function generateReportParenteralePDF(doc) { +// CONTENUTO PDF FOGLIO DI LAVORO 
-    // Implementazione semplificata del PDF+function generateWorksheetPDFContent(doc) { 
 +    const calc = window.nptCalculation; 
 +    
     let yPos = 50;     let yPos = 50;
          
     doc.setFontSize(12);     doc.setFontSize(12);
-    doc.text('REPORT PARENTERALE', 20, yPos);+    doc.text('FOGLIO DI LAVORO NPT', 20, yPos);
     yPos += 20;     yPos += 20;
          
     doc.setFontSize(10);     doc.setFontSize(10);
-    doc.text('SistemaNPT Calculator v3.0 UNIFIED', 20, yPos);+    doc.text('Paziente' + (patientData.medicalRecord || 'N/A'), 20, yPos);
     yPos += 10;     yPos += 10;
-    doc.text('Data: ' + new Date().toLocaleDateString('it-IT'), 20, yPos);+    doc.text('Peso: ' + patientData.currentWeight + 'g', 20, yPos); 
 +    yPos += 10; 
 +    doc.text('Giorni di vita: ' + patientData.daysOfLife, 20, yPos)
 +    yPos += 20; 
 +     
 +    doc.text('PREPARAZIONE NPT:', 20, yPos)
 +    yPos += 15; 
 +     
 +    const deflectorVolume = parseInt(document.getElementById('deflectorVolume').value) || 30; 
 +    const ratio = (calc.totalVolume + deflectorVolume) / calc.totalVolume; 
 +     
 +    doc.text('Volume prescrizione: ' + calc.totalVolume + ' ml', 20, yPos); 
 +    yPos += 8; 
 +    doc.text('Volume deflussore: +' + deflectorVolume + ' ml', 20, yPos); 
 +    yPos += 8; 
 +    doc.text('Volume totale preparazione: ' + (calc.totalVolume + deflectorVolume) + ' ml', 20, yPos); 
 +    yPos += 15; 
 +     
 +    doc.text('COMPONENTI DA PREPARARE:', 20, yPos); 
 +    yPos += 15; 
 +     
 +    if (calc.neededGlucose > 0) { 
 +        doc.text('Glucosio 50%: ' + (calc.glucose50Volume * ratio).toFixed(1) + ' ml', 20, yPos); 
 +        yPos += 8; 
 +    } 
 +     
 +    doc.text('Trophamine 6%: ' + (calc.proteinVolume * ratio).toFixed(1) + ' ml', 20, yPos); 
 +    yPos += 8; 
 +    doc.text('Intralipid 20%: ' + (calc.lipidVolume * ratio).toFixed(1) + ' ml', 20, yPos); 
 +    yPos += 8; 
 +    doc.text('Acqua Bidistillata: ' + (calc.waterVolume * ratio).toFixed(1) + ' ml', 20, yPos); 
 +    yPos += 15; 
 +     
 +    if (calc.electrolyteAdditions.ca_gluconato > 0) { 
 +        doc.text('Calcio Gluconato: ' + (calc.electrolyteAdditions.ca_gluconato * ratio).toFixed(1) + ' ml', 20, yPos); 
 +        yPos += 8; 
 +    } 
 +     
 +    if (calc.electrolyteAdditions.esafosfina > 0) { 
 +        doc.text('Esafosfina: ' + (calc.electrolyteAdditions.esafosfina * ratio).toFixed(1) + ' ml', 20, yPos); 
 +        yPos += 8; 
 +    } 
 +     
 +    doc.text('Velocità infusione: ' + (calc.totalVolume / 24).toFixed(2) + ' ml/h', 20, yPos); 
 +    yPos += 8; 
 +     
 +    if (calc.osmolarityData) { 
 +        doc.text('Osmolarità: ' + calc.osmolarityData.total + ' mOsm/L', 20, yPos); 
 +        if (calc.osmolarityData.isHypertonic) { 
 +            yPos += 8; 
 +            doc.text('ATTENZIONE: SOLO ACCESSO VENOSO CENTRALE', 20, yPos); 
 +        } 
 +    }
 } }
 +
 +// CONTENUTO PDF ETICHETTA SACCA
 +function generateLabelPDFContent(doc) {
 +    const currentDate = new Date().toLocaleDateString('it-IT');
 +    const currentTime = new Date().toLocaleTimeString('it-IT', { hour: '2-digit', minute: '2-digit' });
 +    const calc = window.nptCalculation;
 +    
 +    const birthDate = new Date();
 +    birthDate.setDate(birthDate.getDate() - patientData.daysOfLife);
 +    
 +    // Recupera il medico attualmente selezionato
 +    const currentPrescribingDoctor = document.getElementById('prescribingDoctor').value;
 +    const doctorName = currentPrescribingDoctor && doctorsData[currentPrescribingDoctor] ? 
 +              doctorsData[currentPrescribingDoctor].fullName : 
 +              (patientData.prescribingDoctorName || 'Medico non specificato');
 +    
 +    if (!window.currentPrescriptionID) {
 +        window.currentPrescriptionID = generatePreparationID();
 +    }
 +    const labelPreparationID = window.currentPrescriptionID;
 +    
 +    let yPos = 50;
 +    
 +    doc.setFontSize(14);
 +    doc.setFont(undefined, 'bold');
 +    doc.text('ETICHETTA SACCA NPT', 20, yPos);
 +    yPos += 20;
 +    
 +    // IDENTIFICAZIONE PAZIENTE
 +    doc.setFontSize(12);
 +    doc.setFont(undefined, 'bold');
 +    doc.text('IDENTIFICAZIONE PAZIENTE', 20, yPos);
 +    yPos += 15;
 +    
 +    doc.setFontSize(10);
 +    doc.setFont(undefined, 'normal');
 +    doc.text('Cartella Clinica: ' + (patientData.medicalRecord || 'N/A'), 20, yPos);
 +    yPos += 10;
 +    
 +    if (labelPreparationID) {
 +        doc.text('ID Prescrizione: ' + labelPreparationID, 20, yPos);
 +        yPos += 10;
 +    }
 +    
 +    doc.text('Peso: ' + patientData.currentWeight + 'g', 20, yPos);
 +    yPos += 10;
 +    doc.text('Giorni di vita: ' + patientData.daysOfLife, 20, yPos);
 +    yPos += 10;
 +    
 +    if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) {
 +        const gestDays = patientData.gestationalDays || 0;
 +        doc.text('Età Gestazionale: ' + patientData.gestationalWeeks + '+' + gestDays + ' sett.', 20, yPos);
 +        yPos += 10;
 +        if (patientData.postConceptionalAge && patientData.postConceptionalAge.format) {
 +            doc.text('Età Post-concez.: ' + patientData.postConceptionalAge.format + ' sett.', 20, yPos);
 +            yPos += 10;
 +        }
 +    }
 +    
 +    doc.text('Data Nascita: ' + birthDate.toLocaleDateString('it-IT'), 20, yPos);
 +    yPos += 20;
 +    
 +    // DATI PRESCRIZIONE
 +    doc.setFontSize(12);
 +    doc.setFont(undefined, 'bold');
 +    doc.text('DATI PRESCRIZIONE', 20, yPos);
 +    yPos += 15;
 +    
 +    doc.setFontSize(10);
 +    doc.setFont(undefined, 'normal');
 +    doc.text('Medico Prescrittore: ' + doctorName, 20, yPos);
 +    yPos += 8;
 +    doc.text('Data Prescrizione: ' + (patientData.prescriptionDate || currentDate), 20, yPos);
 +    yPos += 8;
 +    doc.text('Data Preparazione: ' + currentDate, 20, yPos);
 +    yPos += 8;
 +    doc.text('Ora Preparazione: ' + currentTime, 20, yPos);
 +    yPos += 20;
 +    
 +    // CONTENUTO SACCA
 +    doc.setFontSize(12);
 +    doc.setFont(undefined, 'bold');
 +    doc.text('CONTENUTO SACCA NPT', 20, yPos);
 +    yPos += 15;
 +    
 +    doc.setFontSize(10);
 +    doc.setFont(undefined, 'normal');
 +    
 +    if (calc.neededGlucose > 0) {
 +        doc.text('Glucosio 50%: ' + calc.glucose50Volume.toFixed(1) + ' ml', 20, yPos);
 +        yPos += 8;
 +    }
 +    
 +    doc.text('Trophamine 6%: ' + calc.proteinVolume.toFixed(1) + ' ml', 20, yPos);
 +    yPos += 8;
 +    doc.text('Intralipid 20%: ' + calc.lipidVolume.toFixed(1) + ' ml', 20, yPos);
 +    yPos += 8;
 +    doc.text('Acqua Bidistillata: ' + calc.waterVolume.toFixed(1) + ' ml', 20, yPos);
 +    yPos += 15;
 +    
 +    doc.setFont(undefined, 'bold');
 +    doc.text('VOLUME TOTALE: ' + calc.totalVolume + ' ml', 20, yPos);
 +    yPos += 10;
 +    doc.text('Velocità infusione: ' + (calc.totalVolume / 24).toFixed(2) + ' ml/h', 20, yPos);
 +    
 +    // Osmolarità se disponibile
 +    if (calc.osmolarityData) {
 +        yPos += 15;
 +        doc.setFontSize(11);
 +        doc.text('Osmolarità: ' + calc.osmolarityData.total + ' mOsm/L', 20, yPos);
 +        
 +        if (calc.osmolarityData.isHypertonic) {
 +            yPos += 10;
 +            doc.setTextColor(255, 0, 0); // Rosso
 +            doc.text('ATTENZIONE: SOLO ACCESSO VENOSO CENTRALE', 20, yPos);
 +            doc.setTextColor(0, 0, 0); // Torna nero
 +        }
 +    }
 +}
 +
 +
  
 // FUNZIONI PLACEHOLDER // FUNZIONI PLACEHOLDER
Linea 3041: Linea 4928:
     alert('Aggiungi nuovo componente parenterale - Implementazione completa nel codice sorgente');     alert('Aggiungi nuovo componente parenterale - Implementazione completa nel codice sorgente');
 } }
 +
  
 function showAddDoctorForm() { function showAddDoctorForm() {
-    alert('Aggiungi nuovo medico - Implementazione completa nel codice sorgente');+    const name = prompt('Inserisci il nome del medico:'); 
 +    if (!name || name.trim() === '') return; 
 +     
 +    const surname = prompt('Inserisci il cognome del medico:'); 
 +    if (!surname || surname.trim() === '') return; 
 +     
 +    const title = prompt('Inserisci il titolo (Dr. o Dr.ssa):'); 
 +    if (!title || title.trim() === '') return; 
 +     
 +    const key = 'dr_' + surname.toLowerCase().replace(/\s+/g, '_') + '_' + Date.now(); 
 +    const fullName = title.trim() + ' ' + name.trim() + ' ' + surname.trim(); 
 +     
 +    doctorsData[key] = { 
 +        name: name.trim(), 
 +        surname: surname.trim(), 
 +        title: title.trim(), 
 +        fullName: fullName 
 +    }; 
 +     
 +    populateDoctorsConfigTable(); 
 +    updateDoctorsDropdown(); 
 +    alert('Medico aggiunto con successo!\n+ fullName);
 } }
 +
 +function showAddNurseForm() {
 +    const name = prompt('Inserisci il nome dell\'infermiera:');
 +    if (!name || name.trim() === '') return;
 +    
 +    const surname = prompt('Inserisci il cognome dell\'infermiera:');
 +    if (!surname || surname.trim() === '') return;
 +    
 +    const title = prompt('Inserisci il titolo (Inf., Inf. Coord., Inf. Spec.):');
 +    if (!title || title.trim() === '') return;
 +    
 +    const key = 'inf_' + surname.toLowerCase().replace(/\s+/g, '_') + '_' + Date.now();
 +    const fullName = title.trim() + ' ' + name.trim() + ' ' + surname.trim();
 +    
 +    nursesData[key] = {
 +        name: name.trim(),
 +        surname: surname.trim(),
 +        title: title.trim(),
 +        fullName: fullName
 +    };
 +    
 +    populateNursesConfigTable();
 +    alert('Infermiera aggiunta con successo!\n' + fullName);
 +}
 +
 +function showAddPharmacistForm() {
 +    const name = prompt('Inserisci il nome del farmacista:');
 +    if (!name || name.trim() === '') return;
 +    
 +    const surname = prompt('Inserisci il cognome del farmacista:');
 +    if (!surname || surname.trim() === '') return;
 +    
 +    const title = prompt('Inserisci il titolo (Dr. Farm., Dr.ssa Farm., Farm.):');
 +    if (!title || title.trim() === '') return;
 +    
 +    const key = 'farm_' + surname.toLowerCase().replace(/\s+/g, '_') + '_' + Date.now();
 +    const fullName = title.trim() + ' ' + name.trim() + ' ' + surname.trim();
 +    
 +    pharmacistsData[key] = {
 +        name: name.trim(),
 +        surname: surname.trim(),
 +        title: title.trim(),
 +        fullName: fullName
 +    };
 +    
 +    populatePharmacistsConfigTable();
 +    alert('Farmacista aggiunto con successo!\n' + fullName);
 +}
 +
 +function showAddTechnicianForm() {
 +    const name = prompt('Inserisci il nome del tecnico:');
 +    if (!name || name.trim() === '') return;
 +    
 +    const surname = prompt('Inserisci il cognome del tecnico:');
 +    if (!surname || surname.trim() === '') return;
 +    
 +    const title = prompt('Inserisci il titolo (Tec., Tec. Spec., Coord. Tec.):');
 +    if (!title || title.trim() === '') return;
 +    
 +    const key = 'tec_' + surname.toLowerCase().replace(/\s+/g, '_') + '_' + Date.now();
 +    const fullName = title.trim() + ' ' + name.trim() + ' ' + surname.trim();
 +    
 +    technicianData[key] = {
 +        name: name.trim(),
 +        surname: surname.trim(),
 +        title: title.trim(),
 +        fullName: fullName
 +    };
 +    
 +    populateTechniciansConfigTable();
 +    alert('Tecnico aggiunto con successo!\n' + fullName);
 +}
 +
  
 function removeEnteralFormula(key) { function removeEnteralFormula(key) {
Linea 3065: Linea 5047:
  
 function removeDoctor(key) { function removeDoctor(key) {
-    if (confirm('Sei sicuro di voler rimuovere questo medico?')) { +    if (confirm('Sei sicuro di voler rimuovere questo medico?\n\n+ doctorsData[key].fullName)) { 
-        alert('Rimozione medico - Implementazione completa nel codice sorgente');+        delete doctorsData[key]; 
 +        populateDoctorsConfigTable(); 
 +        updateDoctorsDropdown(); 
 +        alert('Medico rimosso con successo!');
     }     }
 +}
 +
 +function removeNurse(key) {
 +    if (confirm('Sei sicuro di voler rimuovere questa infermiera?\n\n' + nursesData[key].fullName)) {
 +        delete nursesData[key];
 +        populateNursesConfigTable();
 +        alert('Infermiera rimossa con successo!');
 +    }
 +}
 +
 +function removePharmacist(key) {
 +    if (confirm('Sei sicuro di voler rimuovere questo farmacista?\n\n' + pharmacistsData[key].fullName)) {
 +        delete pharmacistsData[key];
 +        populatePharmacistsConfigTable();
 +        alert('Farmacista rimosso con successo!');
 +    }
 +}
 +
 +function removeTechnician(key) {
 +    if (confirm('Sei sicuro di voler rimuovere questo tecnico?\n\n' + technicianData[key].fullName)) {
 +        delete technicianData[key];
 +        populateTechniciansConfigTable();
 +        alert('Tecnico rimosso con successo!');
 +    }
 +}
 +
 +// FUNZIONI VALIDAZIONE E ARCHIVIAZIONE PREPARAZIONE
 +function updatePreparationStaffDropdowns() {
 +    console.log('Popolamento dropdown personale preparazione');
 +    
 +    // Farmacisti
 +    const pharmacistSelect = document.getElementById('validatingPharmacist');
 +    if (pharmacistSelect) {
 +        pharmacistSelect.innerHTML = '<option value="">Seleziona farmacista responsabile</option>';
 +        Object.keys(pharmacistsData).forEach(key => {
 +            const option = document.createElement('option');
 +            option.value = key;
 +            option.textContent = pharmacistsData[key].fullName;
 +            pharmacistSelect.appendChild(option);
 +        });
 +        console.log('Dropdown farmacisti popolata:', Object.keys(pharmacistsData).length, 'farmacisti');
 +    }
 +    
 +    // Tecnici (per entrambe le dropdown)
 +    ['preparingTechnician1', 'preparingTechnician2'].forEach(selectId => {
 +        const select = document.getElementById(selectId);
 +        if (select) {
 +            select.innerHTML = '<option value="">Seleziona tecnico</option>';
 +            Object.keys(technicianData).forEach(key => {
 +                const option = document.createElement('option');
 +                option.value = key;
 +                option.textContent = technicianData[key].fullName;
 +                select.appendChild(option);
 +            });
 +        }
 +    });
 +    console.log('Dropdown tecnici popolate:', Object.keys(technicianData).length, 'tecnici');
 +}
 +
 +// =====================================================
 +// SISTEMA VALIDAZIONE E PREPARAZIONE IN DUE FASI
 +// =====================================================
 +
 +// FASE 1: Validazione Farmacista
 +function validatePrescription() {
 +    const pharmacist = document.getElementById('validatingPharmacist').value;
 +    
 +    if (!pharmacist) {
 +        alert('⚠️ Errore: Selezionare il farmacista validatore');
 +        return;
 +    }
 +    
 +    if (!window.residualNeeds || !window.nptCalculation || !patientData.currentWeight) {
 +        alert('❌ Errore: Prima completare tutti i calcoli NPT (TAB 1-4)');
 +        return;
 +    }
 +    
 +    // Validazione completata
 +    document.getElementById('validatePrescriptionBtn').className = 'button config-update-completed';
 +    document.getElementById('validatePrescriptionBtn').innerHTML = '✅ PRESCRIZIONE VALIDATA';
 +    document.getElementById('validatePrescriptionBtn').disabled = true;
 +    
 +    // Mostra status validazione
 +    const pharmacistName = pharmacistsData[pharmacist].fullName;
 +    const validationHtml = '<div class="info">' +
 +        '<strong>✅ VALIDAZIONE COMPLETATA</strong><br>' +
 +        '<strong>Farmacista:</strong> ' + pharmacistName + '<br>' +
 +        '<strong>Data/Ora:</strong> ' + new Date().toLocaleString('it-IT') + '<br>' +
 +        '<strong>Status:</strong> Prescrizione validata per allestimento' +
 +        '</div>';
 +    
 +    document.getElementById('validationStatus').innerHTML = validationHtml;
 +    document.getElementById('validationStatus').style.display = 'block';
 +    
 +    // Abilita fase 2 - Allestimento
 +    enablePreparationPhase();
 +    
 +    alert('✅ Prescrizione validata dal farmacista!\nOra puoi procedere con l\'allestimento.');
 +}
 +
 +// Abilita la fase di allestimento tecnici
 +function enablePreparationPhase() {
 +    const tech1Select = document.getElementById('preparingTechnician1');
 +    const tech2Select = document.getElementById('preparingTechnician2');
 +    
 +    // Abilita le dropdown tecnici
 +    tech1Select.disabled = false;
 +    tech2Select.disabled = false;
 +    
 +    // Popola le dropdown tecnici
 +    [tech1Select, tech2Select].forEach(select => {
 +        select.innerHTML = '<option value="">Seleziona tecnico</option>';
 +        Object.keys(technicianData).forEach(key => {
 +            const option = document.createElement('option');
 +            option.value = key;
 +            option.textContent = technicianData[key].fullName;
 +            select.appendChild(option);
 +        });
 +    });
 +    
 +    // Abilita il pulsante conferma (ma ancora non attivo finché non si selezionano i tecnici)
 +    document.getElementById('confirmPreparationBtn').disabled = false;
 +    document.getElementById('confirmPreparationBtn').innerHTML = '🧪 CONFERMA ALLESTIMENTO';
 +    
 +    // Event listeners per controllare quando entrambi i tecnici sono selezionati
 +    [tech1Select, tech2Select].forEach(select => {
 +        select.addEventListener('change', checkTechniciansSelection);
 +    });
 +}
 +
 +// Controlla se entrambi i tecnici sono selezionati
 +function checkTechniciansSelection() {
 +    const tech1 = document.getElementById('preparingTechnician1').value;
 +    const tech2 = document.getElementById('preparingTechnician2').value;
 +    const confirmBtn = document.getElementById('confirmPreparationBtn');
 +    
 +    if (tech1 && tech2 && tech1 !== tech2) {
 +        confirmBtn.className = 'button';
 +        confirmBtn.innerHTML = '🧪 CONFERMA ALLESTIMENTO';
 +    } else if (tech1 === tech2 && tech1 !== '') {
 +        confirmBtn.className = 'button config-update-pending';
 +        confirmBtn.innerHTML = '⚠️ TECNICI DEVONO ESSERE DIVERSI';
 +    } else {
 +        confirmBtn.className = 'button';
 +        confirmBtn.innerHTML = '🧪 CONFERMA ALLESTIMENTO (seleziona tecnici)';
 +    }
 +}
 +
 +// FASE 2: Conferma Allestimento
 +function confirmPreparation() {
 +    const tech1 = document.getElementById('preparingTechnician1').value;
 +    const tech2 = document.getElementById('preparingTechnician2').value;
 +    
 +    if (!tech1 || !tech2) {
 +        alert('⚠️ Errore: Selezionare entrambi i tecnici preparatori');
 +        return;
 +    }
 +    
 +    if (tech1 === tech2) {
 +        alert('⚠️ Errore: I due tecnici devono essere persone diverse per il controllo incrociato');
 +        return;
 +    }
 +    
 +    // Allestimento confermato
 +    document.getElementById('confirmPreparationBtn').className = 'button config-update-completed';
 +    document.getElementById('confirmPreparationBtn').innerHTML = '🧪 ALLESTIMENTO COMPLETATO ✓';
 +    document.getElementById('confirmPreparationBtn').disabled = true;
 +    
 +    // Mostra status preparazione
 +    const tech1Name = technicianData[tech1].fullName;
 +    const tech2Name = technicianData[tech2].fullName;
 +    const preparationHtml = '<div class="info">' +
 +        '<strong>🧪 ALLESTIMENTO COMPLETATO</strong><br>' +
 +        '<strong>Tecnico 1:</strong> ' + tech1Name + '<br>' +
 +        '<strong>Tecnico 2:</strong> ' + tech2Name + '<br>' +
 +        '<strong>Data/Ora:</strong> ' + new Date().toLocaleString('it-IT') + '<br>' +
 +        '<strong>Status:</strong> NPT pronta per somministrazione' +
 +        '</div>';
 +    
 +    document.getElementById('preparationStatus').innerHTML = preparationHtml;
 +    document.getElementById('preparationStatus').style.display = 'block';
 +    
 +    // Abilita download JSON
 +document.getElementById('downloadBtn').disabled = false;
 +document.getElementById('downloadBtn').className = 'button';
 +
 +    // Abilita pulsante blocco prescrizione
 +    document.getElementById('lockPrescriptionBtn').disabled = false;
 +    document.getElementById('lockPrescriptionBtn').className = 'button';
 +    document.getElementById('lockPrescriptionBtn').style.backgroundColor = '#e74c3c';
 +
 +    // Genera e salva l'ID preparazione per il sistema di blocco
 +    if (!window.currentPrescriptionID) {
 +        window.currentPrescriptionID = generatePreparationID();
 +    }
 +    window.lastPreparationID = window.currentPrescriptionID;
 +
 +    console.log('ID Preparazione assegnato:', window.currentPrescriptionID);
 +
 +
 +
 +    alert('🧪 Allestimento completato!\Puoi ora archiviare la preparazione e bloccarla definitivamente.');
 +    }
 +
 +// =====================================================
 +// SISTEMA BLOCCO PRESCRIZIONE
 +// =====================================================
 +
 +// Variabile globale per stato blocco
 +window.prescriptionLocked = false;
 +
 +// Funzione per bloccare la prescrizione
 +function lockPrescription() {
 +    const confirmed = confirm(
 +        '🔒 ATTENZIONE: BLOCCO PRESCRIZIONE\n\n' +
 +        'Questa operazione bloccherà DEFINITIVAMENTE la prescrizione NPT corrente.\n\n' +
 +        '• Non sarà più possibile modificare i dati\n' +
 +        '• La preparazione sarà considerata FINALIZZATA\n' +
 +        '• Per modifiche servirà una NUOVA prescrizione\n\n' +
 +        'Sei sicuro di voler procedere?'
 +    );
 +    
 +    if (!confirmed) {
 +        return;
 +    }
 +    
 +    // Blocca la prescrizione
 +    window.prescriptionLocked = true;
 +    
 +    // Aggiorna interfaccia
 +    document.getElementById('lockPrescriptionBtn').className = 'button config-update-completed';
 +    document.getElementById('lockPrescriptionBtn').innerHTML = '🔒 PRESCRIZIONE BLOCCATA ✓';
 +    document.getElementById('lockPrescriptionBtn').disabled = true;
 +
 +    // Assicurati che l'ID preparazione sia disponibile per il banner
 +    if (!window.lastPreparationID && window.currentPrescriptionID) {
 +        window.lastPreparationID = window.currentPrescriptionID;
 +    }
 +    // Mostra banner di stato
 +    showPrescriptionLockedBanner();
 +    
 +    // Disabilita tutti i controlli di input
 +    disableAllInputs();
 +    
 +    alert('🔒 PRESCRIZIONE BLOCCATA!\n\n' +
 +          'La prescrizione NPT è ora finalizzata e non può essere modificata.\n' +
 +          'Per eventuali modifiche sarà necessaria una nuova prescrizione.');
 +}
 +
 +// Mostra banner di prescrizione bloccata
 +function showPrescriptionLockedBanner() {
 +    const currentDateTime = new Date().toLocaleString('it-IT');
 +    const preparationID = window.lastPreparationID || window.currentPrescriptionID || 'N/A';
 +    const bannerHtml = '<div class="alert-critical" style="text-align: center; margin: 20px 0;">' +
 +        '<strong>🔒 PRESCRIZIONE NPT BLOCCATA E FINALIZZATA</strong><br>' +
 +        '<strong>Data/Ora blocco:</strong> ' + currentDateTime + '<br>' +
 +        '<strong>ID Preparazione:</strong> ' + preparationID + '<br>' +
 +        '<strong>Status:</strong> NPT pronta per somministrazione - NESSUNA MODIFICA CONSENTITA<br>' +
 +        '<button class="button secondary" onclick="startNewPrescription()" style="margin-top: 10px;">📋 NUOVA PRESCRIZIONE NPT</button>' +
 +        '</div>';
 +    
 +    document.getElementById('prescriptionStatusBanner').innerHTML = bannerHtml;
 +    document.getElementById('prescriptionStatusBanner').style.display = 'block';
 +}
 +
 +// Disabilita tutti gli input quando prescrizione è bloccata
 +function disableAllInputs() {
 +    // Disabilita TAB 2-4, mantieni TAB 1 accessibile per consultazione
 +    const tabButtons = document.querySelectorAll('.tab');
 +    tabButtons.forEach((tab, index) => {
 +        if (index > 0 && index < 4) { // Solo TAB 2-4, NON TAB 1 (index 0)
 +        tab.style.opacity = '0.5';
 +        tab.style.pointerEvents = 'none';
 +        tab.style.cursor = 'not-allowed';
 +    }
 +});
 +    
 +  // Disabilita input solo nei TAB 2-4, mantieni TAB 1 consultabile
 +    const inputElements = document.querySelectorAll('#enteral input, #enteral select, #enteral button, ' +
 +                                               '#nutrition-calc input, #nutrition-calc select, #nutrition-calc button, ' +
 +                                               '#parenteral input, #parenteral select, #parenteral button');
 +
 +    inputElements.forEach(element => {
 +        element.disabled = true;
 +        element.style.opacity = '0.5';
 +});
 +
 +// TAB 1: disabilita solo i pulsanti di modifica, mantieni visibili i dati
 +const tab1Buttons = document.querySelectorAll('#patient-data button');
 +tab1Buttons.forEach(button => {
 +    button.disabled = true;
 +    button.style.opacity = '0.5';
 +});
 +    
 +    // Mostra overlay sui TAB bloccati
 +    addLockedOverlay();
 +}
 +
 +// Aggiunge overlay visivo sui TAB bloccati
 +function addLockedOverlay() {
 +    const lockedTabs = ['enteral', 'nutrition-calc', 'parenteral']; // RIMUOVI 'patient-data'
 +        lockedTabs.forEach(tabId => {
 +        const tabElement = document.getElementById(tabId);
 +        if (tabElement && !tabElement.querySelector('.locked-overlay')) {
 +            const overlay = document.createElement('div');
 +            overlay.className = 'locked-overlay';
 +            overlay.style.cssText = `
 +                position: absolute;
 +                top: 0;
 +                left: 0;
 +                width: 100%;
 +                height: 100%;
 +                background-color: rgba(231, 76, 60, 0.1);
 +                z-index: 1000;
 +                display: flex;
 +                align-items: center;
 +                justify-content: center;
 +                font-size: 24px;
 +                font-weight: bold;
 +                color: #e74c3c;
 +                pointer-events: none;
 +            `;
 +            overlay.innerHTML = '🔒 PRESCRIZIONE BLOCCATA';
 +            
 +            tabElement.style.position = 'relative';
 +            tabElement.appendChild(overlay);
 +        }
 +    });
 +}
 +
 +// Funzione per iniziare nuova prescrizione
 +function startNewPrescription() {
 +    const confirmed = confirm(
 +        '📋 NUOVA PRESCRIZIONE NPT\n\n' +
 +        'Questa operazione:\n' +
 +        '• Resetterà tutti i dati correnti\n' +
 +        '• Permetterà di iniziare una nuova prescrizione\n' +
 +        '• La prescrizione precedente rimarrà archiviata\n\n' +
 +        'Vuoi procedere?'
 +    );
 +    
 +    if (!confirmed) {
 +        return;
 +    }
 +    
 +    // Reset completo dell'applicazione
 +    resetToNewPrescription();
 +}
 +
 +// Reset per nuova prescrizione
 +function resetToNewPrescription() {
 +    // Reset variabili globali
 +    window.prescriptionLocked = false;
 +    window.residualNeeds = null;
 +    window.nptCalculation = null;
 +    window.monthlyPreparations = [];
 +    window.currentPrescriptionID = null;
 +    patientData = {};
 +    enteralData = null;
 +    currentRequirements = null;
 +    
 +    // Riabilita tutti gli input
 +    enableAllInputs();
 +    
 +    // Reset tutti i form
 +    resetAllForms();
 +    
 +    // Nascondi banner
 +    document.getElementById('prescriptionStatusBanner').style.display = 'none';
 +    
 +    // Vai al TAB 1
 +    showTab('patient-data');
 +    
 +    // Imposta nuova data
 +    const today = new Date().toISOString().split('T')[0];
 +    document.getElementById('prescriptionDate').value = today;
 +    
 +    alert('📋 Nuova prescrizione iniziata!\nPuoi ora inserire i dati del nuovo paziente.');
 +}
 +
 +// Funzioni di supporto per reset completo
 +function enableAllInputs() {
 +    // Riabilita tutti i TAB
 +    const tabButtons = document.querySelectorAll('.tab');
 +    tabButtons.forEach(tab => {
 +        tab.style.opacity = '1';
 +        tab.style.pointerEvents = 'auto';
 +        tab.style.cursor = 'pointer';
 +    });
 +    
 +    // Riabilita tutti gli input
 +    const inputElements = document.querySelectorAll('#patient-data input, #patient-data select, #patient-data button, ' +
 +                                                   '#enteral input, #enteral select, #enteral button, ' +
 +                                                   '#nutrition-calc input, #nutrition-calc select, #nutrition-calc button, ' +
 +                                                   '#parenteral input, #parenteral select, #parenteral button');
 +    
 +    inputElements.forEach(element => {
 +        element.disabled = false;
 +        element.style.opacity = '1';
 +    });
 +    
 +    // Rimuovi overlay bloccati
 +    removeLockedOverlays();
 +}
 +
 +function removeLockedOverlays() {
 +    const overlays = document.querySelectorAll('.locked-overlay');
 +    overlays.forEach(overlay => {
 +        overlay.remove();
 +    });
 +}
 +
 +function resetAllForms() {
 +    // Reset TAB 1 - Dati Paziente
 +    document.getElementById('medicalRecord').value = new Date().getFullYear().toString();
 +    document.getElementById('birthWeight').value = '1000';
 +    document.getElementById('currentWeight').value = '1000';
 +    document.getElementById('daysOfLife').value = '9';
 +    document.getElementById('gestationalWeeks').value = '';
 +    document.getElementById('gestationalDays').value = '';
 +    document.getElementById('postConceptionalAge').value = '';
 +    document.getElementById('bun').value = '';
 +    document.getElementById('glucose').value = '';
 +    document.getElementById('sodium').value = '';
 +    document.getElementById('ph').value = '';
 +    document.getElementById('baseExcess').value = '';
 +    document.getElementById('diuresis').value = '';
 +    document.getElementById('prescribingDoctor').value = '';
 +    
 +    // Reset pulsanti TAB 1
 +    const phaseBtn = document.getElementById('calculatePhaseBtn');
 +    if (phaseBtn) {
 +        phaseBtn.className = 'button calculate-phase-pending';
 +        phaseBtn.innerHTML = 'CALCOLA FASE NUTRIZIONALE';
 +        phaseBtn.disabled = false;
 +    }
 +    
 +    // Nascondi risultati fase
 +    const phaseResults = document.getElementById('phaseResults');
 +    if (phaseResults) {
 +        phaseResults.classList.add('hidden');
 +    }
 +    
 +    // Reset TAB 2 - Nutrizione Enterale
 +    document.getElementById('formulaType').value = 'none';
 +    document.getElementById('dailyVolume').value = '0';
 +    document.getElementById('additionalFluids').value = '0';
 +    document.getElementById('fluidType').value = 'saline';
 +    document.getElementById('fluidRoute').value = 'iv';
 +    
 +    // Reset pulsanti TAB 2
 +    const enteralBtn = document.getElementById('calculateEnteralBtn');
 +    if (enteralBtn) {
 +        enteralBtn.className = 'button calculate-nutrition-pending';
 +        enteralBtn.innerHTML = 'Calcola Apporti Enterali';
 +    }
 +    
 +    // Nascondi risultati enterali
 +    const enteralResults = document.getElementById('enteralResults');
 +    if (enteralResults) {
 +        enteralResults.classList.add('hidden');
 +    }
 +    
 +    // Reset TAB 3 - Fabbisogni
 +    document.getElementById('targetDay').value = '9';
 +    document.getElementById('weightCategory').value = '';
 +    resetNutritionFields();
 +    
 +    // Reset pulsanti TAB 3
 +    const loadBtn = document.getElementById('loadDefaultsBtn');
 +    const nutritionBtn = document.getElementById('calculateNutritionBtn');
 +    if (loadBtn) {
 +        loadBtn.className = 'button load-defaults-pending';
 +        loadBtn.innerHTML = 'Carica Valori Standard';
 +    }
 +    if (nutritionBtn) {
 +        nutritionBtn.className = 'button calculate-nutrition-pending';
 +        nutritionBtn.innerHTML = 'CALCOLA FABBISOGNI';
 +    }
 +    
 +    // Nascondi risultati nutrizione
 +    const nutritionResults = document.getElementById('nutritionResults');
 +    if (nutritionResults) {
 +        nutritionResults.classList.add('hidden');
 +    }
 +    
 +    // Reset TAB 4 - Parenterale
 +    resetParenteralFields();
 +    
 +    // Reset TAB 5 - Report
 +    resetReportFields();
 +    
 +    updateFortifierOptions();
 +}
 +
 +function resetNutritionFields() {
 +    const nutritionFields = [
 +        'reqLiquids', 'reqProtein', 'reqCarbs', 'reqLipids',
 +        'reqCalcium', 'reqPhosphorus', 'reqMagnesium', 'reqSodium', 'reqPotassium',
 +        'reqVitalipid', 'reqSoluvit', 'reqPeditrace', 'reqCarnitine'
 +    ];
 +    
 +    nutritionFields.forEach(fieldId => {
 +        const field = document.getElementById(fieldId);
 +        if (field) {
 +            field.value = '0';
 +        }
 +    });
 +    
 +    // Reset unità carboidrati
 +    document.getElementById('carbUnit').value = 'g';
 +    document.getElementById('carbLabel').textContent = 'Glucidi (g/kg/die):';
 +    
 +    // Reset tipo sodio
 +    document.getElementById('sodiumType').value = 'nacl';
 +    
 +    // Nascondi raccomandazione sodio
 +    const sodiumRec = document.getElementById('sodiumRecommendation');
 +    if (sodiumRec) {
 +        sodiumRec.classList.add('hidden');
 +    }
 +}
 +
 +function resetParenteralFields() {
 +    document.getElementById('calculatedTotalVolume').value = "Premere 'Calcola NPT'";
 +    document.getElementById('suggestedGlucose').value = "Premere 'Calcola NPT'";
 +    document.getElementById('calculatedProteinVol').value = "--";
 +    document.getElementById('calculatedLipidVol').value = "--";
 +    
 +    const parenteralBtn = document.getElementById('calculateParenteralBtn');
 +    if (parenteralBtn) {
 +        parenteralBtn.className = 'button';
 +        parenteralBtn.innerHTML = 'CALCOLA NPT AUTOMATICA';
 +    }
 +    
 +    const parenteralResults = document.getElementById('parenteralResults');
 +    if (parenteralResults) {
 +        parenteralResults.classList.add('hidden');
 +    }
 +}
 +
 +function resetReportFields() {
 +    // Reset dropdown personale
 +    document.getElementById('validatingPharmacist').value = '';
 +    document.getElementById('preparingTechnician1').value = '';
 +    document.getElementById('preparingTechnician2').value = '';
 +    
 +    // Reset pulsanti validazione/preparazione
 +    const validateBtn = document.getElementById('validatePrescriptionBtn');
 +    const confirmBtn = document.getElementById('confirmPreparationBtn');
 +    const downloadBtn = document.getElementById('downloadBtn');
 +    const lockBtn = document.getElementById('lockPrescriptionBtn');
 +    
 +    if (validateBtn) {
 +        validateBtn.className = 'button';
 +        validateBtn.innerHTML = '✅ VALIDA PRESCRIZIONE';
 +        validateBtn.disabled = false;
 +    }
 +    
 +    if (confirmBtn) {
 +        confirmBtn.className = 'button';
 +        confirmBtn.innerHTML = '🧪 CONFERMA ALLESTIMENTO';
 +        confirmBtn.disabled = true;
 +    }
 +    
 +    if (downloadBtn) {
 +        downloadBtn.className = 'button secondary';
 +        downloadBtn.innerHTML = '💾 ARCHIVIA PREPARAZIONE (JSON)';
 +        downloadBtn.disabled = true;
 +    }
 +    
 +    if (lockBtn) {
 +        lockBtn.className = 'button';
 +        lockBtn.innerHTML = '🔒 BLOCCA PRESCRIZIONE';
 +        lockBtn.disabled = true;
 +        lockBtn.style.backgroundColor = '#e74c3c';
 +    }
 +    
 +    // Nascondi status
 +    const validationStatus = document.getElementById('validationStatus');
 +    const preparationStatus = document.getElementById('preparationStatus');
 +    if (validationStatus) validationStatus.style.display = 'none';
 +    if (preparationStatus) preparationStatus.style.display = 'none';
 +    
 +    // Reset area report
 +    document.getElementById('reportOutput').innerHTML = '';
 +}
 +
 +
 +// SISTEMA DI ARCHIVIAZIONE JSON
 +function generatePreparationID() {
 +    const medicalRecord = patientData.medicalRecord;
 +    let prescriptionDate = patientData.prescriptionDate; // ✅ Cambiato da const a let
 +    
 +    if (!medicalRecord || medicalRecord.trim() === '') {
 +        return null;
 +    }
 +    
 +    if (!prescriptionDate || prescriptionDate.trim() === '') {
 +        // Usa data odierna se non specificata
 +        const today = new Date().toISOString().split('T')[0];
 +        prescriptionDate = today; // ✅ Ora funziona correttamente
 +    }
 +    
 +    // Converte la data da YYYY-MM-DD a DDMMYYYY
 +    const dateObj = new Date(prescriptionDate);
 +    const day = dateObj.getDate().toString().padStart(2, '0');
 +    const month = (dateObj.getMonth() + 1).toString().padStart(2, '0');
 +    const year = dateObj.getFullYear().toString();
 +    const formattedDate = day + month + year;
 +    
 +    // Crea chiave univoca per cartella + data
 +    const counterKey = medicalRecord + '_' + formattedDate;
 +    
 +    // Inizializza il contatore se non esiste
 +    if (!window.preparationCounter) {
 +        window.preparationCounter = {};
 +    }
 +    
 +    if (!window.preparationCounter[counterKey]) {
 +        window.preparationCounter[counterKey] = 0;
 +    }
 +    
 +    // Incrementa il contatore
 +    window.preparationCounter[counterKey]++;
 +    
 +    // Genera l'ID con formato: CARTELLA_DDMMYYYY_NN
 +    const counter = window.preparationCounter[counterKey].toString().padStart(2, '0');
 +    const preparationID = medicalRecord + '_' + formattedDate + '_' + counter;
 +    
 +    return preparationID;
 +}
 +function createPreparationJSON() {
 +    if (!window.residualNeeds || !window.nptCalculation || !patientData.currentWeight) {
 +        alert('❌ Errore: Prima completare tutti i calcoli NPT (TAB 1-4)');
 +        return null;
 +    }
 +    
 +    // Genera ID preparazione
 +    const preparationID = generatePreparationID();
 +    if (!preparationID) {
 +        alert('❌ Errore: Impossibile generare ID preparazione. Verificare cartella clinica e data.');
 +        return null;
 +    }
 +    
 +    // Recupera dati personale
 +    const pharmacistKey = document.getElementById('validatingPharmacist').value;
 +    const tech1Key = document.getElementById('preparingTechnician1').value;
 +    const tech2Key = document.getElementById('preparingTechnician2').value;
 +    
 +    const pharmacistName = pharmacistKey ? pharmacistsData[pharmacistKey].fullName : 'NON SPECIFICATO';
 +    const tech1Name = tech1Key ? technicianData[tech1Key].fullName : 'NON SPECIFICATO';
 +    const tech2Name = tech2Key ? technicianData[tech2Key].fullName : 'NON SPECIFICATO';
 +    
 +    // Crea oggetto JSON completo
 +    const preparationData = {
 +        // IDENTIFICAZIONE
 +        preparationID: preparationID,
 +        cartellaClinica: patientData.medicalRecord,
 +        dataPrescrizione: patientData.prescriptionDate,
 +        dataCreazione: new Date().toISOString(),
 +        
 +       // DATI PAZIENTE
 +        paziente: {
 +            pesoAttuale: patientData.currentWeight,
 +            pesoNascita: patientData.birthWeight || 0,
 +            giorniVita: patientData.daysOfLife || 0,
 +            etaGestazionale: {
 +            settimane: patientData.gestationalWeeks || null,
 +            giorni: patientData.gestationalDays || null,
 +            formato: patientData.gestationalWeeks && patientData.gestationalWeeks > 0 ? 
 +            patientData.gestationalWeeks + '+' + (patientData.gestationalDays || 0) : null
 +            }
 +        },
 +        
 +        // DATI CLINICI
 +        parametriClinici: {
 +            bun: patientData.bun || null,
 +            glicemia: patientData.glucose || null,
 +            natremia: patientData.sodium || null,
 +            ph: patientData.ph || null,
 +            baseExcess: patientData.baseExcess || null,
 +            diuresi: patientData.diuresis || null
 +        },
 +        
 +        // COMPOSIZIONE NPT
 +        npt: {
 +            volumeTotale: window.nptCalculation.totalVolume,
 +            energia: window.residualNeeds.energy.toFixed(1),
 +            proteine: window.residualNeeds.protein.toFixed(2),
 +            lipidi: window.residualNeeds.lipids.toFixed(2),
 +            glucidi: window.residualNeeds.carbs.toFixed(2),
 +            gir: window.nptCalculation.gir.toFixed(1),
 +            osmolarita: window.nptCalculation.osmolarityData ? window.nptCalculation.osmolarityData.total : 0,
 +            velocitaInfusione: (window.nptCalculation.totalVolume / 24).toFixed(2)
 +        },
 +        
 +        // COMPONENTI DETTAGLIATI
 +        componenti: {
 +            glucosio50: window.nptCalculation.glucose50Volume.toFixed(1),
 +            trophamine: window.nptCalculation.proteinVolume.toFixed(1),
 +            intralipid: window.nptCalculation.lipidVolume.toFixed(1),
 +            acquaBidistillata: window.nptCalculation.waterVolume.toFixed(1),
 +            elettroliti: window.nptCalculation.electrolyteAdditions
 +        },
 +        
 +        // PERSONALE
 +        personale: {
 +            medicoPrescrittore: patientData.prescribingDoctorName || 'NON SPECIFICATO',
 +            farmacistValidatore: pharmacistName,
 +            tecnico1: tech1Name,
 +            tecnico2: tech2Name
 +        },
 +        
 +        // METADATA
 +        sistema: {
 +            versione: "NPT Calculator v3.0 UNIFIED",
 +            dataCalcolo: new Date().toISOString()
 +        }
 +    };
 +    
 +    return preparationData;
 +}
 +
 +function downloadPreparationJSON() {
 +    console.log('Inizio generazione JSON preparazione...');
 +    
 +    const preparationData = createPreparationJSON();
 +    if (!preparationData) {
 +        return; // Errore già mostrato in createPreparationJSON
 +    }
 +    
 +    try {
 +        // Crea il file JSON
 +        const jsonString = JSON.stringify(preparationData, null, 2);
 +        const blob = new Blob([jsonString], { type: 'application/json' });
 +        
 +        // Nome file: NPT_[ID].json
 +        const filename = `NPT_${preparationData.preparationID}.json`;
 +        
 +        // Download automatico
 +        const url = URL.createObjectURL(blob);
 +        const a = document.createElement('a');
 +        a.href = url;
 +        a.download = filename;
 +        document.body.appendChild(a);
 +        a.click();
 +        document.body.removeChild(a);
 +        URL.revokeObjectURL(url);
 +        
 +        // Feedback successo
 +        document.getElementById('downloadBtn').className = 'button config-update-completed';
 +        document.getElementById('downloadBtn').innerHTML = '💾 ARCHIVIAZIONE COMPLETATA ✓';
 +        
 +        alert(`✅ Preparazione archiviata con successo!\n\n` +
 +              `📋 ID: ${preparationData.preparationID}\n` +
 +              `📁 File: ${filename}\n` +
 +              `📊 Dati: ${Object.keys(preparationData).length} sezioni salvate`);
 +        // Salva ID per il sistema di blocco
 +        window.lastPreparationID = preparationData.preparationID;
 +        
 +        console.log('JSON generato con successo:', preparationData);
 +        
 +    } catch (error) {
 +        console.error('Errore nella generazione JSON:', error);
 +        alert('❌ Errore nella generazione del file JSON:\n' + error.message);
 +    }
 +}
 +
 +
 +// =====================================================
 +// SISTEMA ARCHIVIAZIONE MENSILE EXCEL
 +// =====================================================
 +
 +// Variabile globale per i dati mensili
 +window.monthlyPreparations = [];
 +
 +// Funzione per inizializzare il mese corrente
 +function initializeMonthlySection() {
 +    const now = new Date();
 +    const currentMonth = now.getFullYear() + '-' + (now.getMonth() + 1).toString().padStart(2, '0');
 +    document.getElementById('selectedMonth').value = currentMonth;
 +}
 +
 +// Funzione anteprima dati mensili
 +function previewMonthlyData() {
 +    const fileInput = document.getElementById('jsonFilesInput');
 +    const files = fileInput.files;
 +    
 +    if (!files || files.length === 0) {
 +        alert('⚠️ Seleziona prima i file JSON da consolidare');
 +        return;
 +    }
 +    
 +    // Reset dati precedenti
 +    window.monthlyPreparations = [];
 +    
 +    let processedFiles = 0;
 +    const totalFiles = files.length;
 +    
 +    // Processa tutti i file JSON
 +    Array.from(files).forEach((file, index) => {
 +        const reader = new FileReader();
 +        
 +        reader.onload = function(e) {
 +            try {
 +                const jsonData = JSON.parse(e.target.result);
 +                
 +                // Valida che sia un file NPT valido
 +                if (validateNPTJson(jsonData)) {
 +                    window.monthlyPreparations.push(jsonData);
 +                } else {
 +                    console.warn('File non valido ignorato:', file.name);
 +                }
 +                
 +                processedFiles++;
 +                
 +                // Quando tutti i file sono processati, mostra l'anteprima
 +                if (processedFiles === totalFiles) {
 +                    showMonthlyPreview();
 +                }
 +                
 +            } catch (error) {
 +                console.error('Errore parsing JSON:', file.name, error);
 +                processedFiles++;
 +                
 +                if (processedFiles === totalFiles) {
 +                    showMonthlyPreview();
 +                }
 +            }
 +        };
 +        
 +        reader.readAsText(file);
 +    });
 +}
 +
 +// Funzione di validazione JSON NPT
 +function validateNPTJson(data) {
 +    return data && 
 +           data.preparationID && 
 +           data.cartellaClinica && 
 +           data.npt && 
 +           data.paziente &&
 +           data.sistema &&
 +           data.sistema.versione;
 +}
 +
 +// Funzione per mostrare l'anteprima
 +function showMonthlyPreview() {
 +    const statsDiv = document.getElementById('monthlyStats');
 +    const selectedMonth = document.getElementById('selectedMonth').value;
 +    const monthName = new Date(selectedMonth + '-01').toLocaleDateString('it-IT',
 +        year: 'numeric', 
 +        month: 'long' 
 +    });
 +    
 +    if (window.monthlyPreparations.length === 0) {
 +        statsDiv.innerHTML = '<div class="error">❌ Nessun file NPT valido trovato</div>';
 +        statsDiv.style.display = 'block';
 +        return;
 +    }
 +    
 +    // Calcola statistiche
 +    const stats = calculateMonthlyStats(window.monthlyPreparations);
 +    
 +    let html = '<div class="info">';
 +    html += '<h4 style="margin-top: 0;">📊 ANTEPRIMA - ' + monthName + '</h4>';
 +    html += '<p><strong>File NPT trovati:</strong> ' + window.monthlyPreparations.length + '</p>';
 +    html += '<p><strong>Pazienti unici:</strong> ' + stats.uniquePatients + '</p>';
 +    html += '<p><strong>Peso medio:</strong> ' + stats.averageWeight.toFixed(0) + 'g</p>';
 +    html += '<p><strong>GIR medio:</strong> ' + stats.averageGIR.toFixed(1) + ' mg/kg/min</p>';
 +    html += '<p><strong>Volume medio NPT:</strong> ' + stats.averageVolume.toFixed(0) + ' ml</p>';
 +    html += '</div>';
 +    
 +    html += '<div class="warning" style="font-size: 12px; margin-top: 10px;">';
 +    html += '<strong>📋 File da processare:</strong><br>';
 +    window.monthlyPreparations.forEach(prep => {
 +        html += '• ' + prep.preparationID + ' (Cartella: ' + prep.cartellaClinica + ')<br>';
 +    });
 +    html += '</div>';
 +    
 +    statsDiv.innerHTML = html;
 +    statsDiv.style.display = 'block';
 +    
 +    // Abilita il pulsante Excel
 +    document.getElementById('generateExcelBtn').disabled = false;
 +    document.getElementById('generateExcelBtn').className = 'button';
 +    document.getElementById('generateExcelBtn').innerHTML = '📊 GENERA EXCEL MENSILE (' + window.monthlyPreparations.length + ' NPT)';
 +}
 +
 +// Funzione per calcolare statistiche mensili
 +function calculateMonthlyStats(preparations) {
 +    const uniquePatients = new Set(preparations.map(p => p.cartellaClinica)).size;
 +    const totalWeight = preparations.reduce((sum, p) => sum + (p.paziente.pesoAttuale || 0), 0);
 +    const totalGIR = preparations.reduce((sum, p) => sum + (parseFloat(p.npt.gir) || 0), 0);
 +    const totalVolume = preparations.reduce((sum, p) => sum + (p.npt.volumeTotale || 0), 0);
 +    
 +    return {
 +        uniquePatients: uniquePatients,
 +        averageWeight: totalWeight / preparations.length,
 +        averageGIR: totalGIR / preparations.length,
 +        averageVolume: totalVolume / preparations.length
 +    };
 +}
 +
 +// Funzione principale per generare Excel mensile
 +function generateMonthlyExcel() {
 +    if (!window.monthlyPreparations || window.monthlyPreparations.length === 0) {
 +        alert('⚠️ Prima esegui l\'anteprima per caricare i dati');
 +        return;
 +    }
 +    
 +    try {
 +        // Crea un nuovo workbook
 +        const wb = XLSX.utils.book_new();
 +        
 +        // FOGLIO 1: Riepilogo Mensile
 +        const summaryData = createSummarySheet(window.monthlyPreparations);
 +        const ws_summary = XLSX.utils.aoa_to_sheet(summaryData);
 +        XLSX.utils.book_append_sheet(wb, ws_summary, "Riepilogo Mensile");
 +        
 +        // FOGLIO 2: Dettaglio Preparazioni
 +        const detailData = createDetailSheet(window.monthlyPreparations);
 +        const ws_detail = XLSX.utils.aoa_to_sheet(detailData);
 +        XLSX.utils.book_append_sheet(wb, ws_detail, "Dettaglio Preparazioni");
 +        
 +        // FOGLIO 3: Statistiche Cliniche
 +        const statsData = createStatsSheet(window.monthlyPreparations);
 +        const ws_stats = XLSX.utils.aoa_to_sheet(statsData);
 +        XLSX.utils.book_append_sheet(wb, ws_stats, "Statistiche Cliniche");
 +        
 +        // FOGLIO 4: Componenti NPT
 +        const componentsData = createComponentsSheet(window.monthlyPreparations);
 +        const ws_components = XLSX.utils.aoa_to_sheet(componentsData);
 +        XLSX.utils.book_append_sheet(wb, ws_components, "Componenti NPT");
 +        
 +        // Genera nome file
 +        const selectedMonth = document.getElementById('selectedMonth').value;
 +        const monthYear = selectedMonth.replace('-', '_');
 +        const fileName = `NPT_Consolidato_${monthYear}.xlsx`;
 +        
 +        // Salva il file
 +        XLSX.writeFile(wb, fileName);
 +        
 +        // Feedback successo
 +        document.getElementById('generateExcelBtn').className = 'button config-update-completed';
 +        document.getElementById('generateExcelBtn').innerHTML = '📊 EXCEL GENERATO ✓';
 +        
 +        alert(`✅ Excel generato con successo!\n\n` +
 +              `📁 File: ${fileName}\n` +
 +              `📊 Preparazioni: ${window.monthlyPreparations.length}\n` +
 +              `📋 Fogli: 4 (Riepilogo, Dettaglio, Statistiche, Componenti)`);
 +        
 +    } catch (error) {
 +        console.error('Errore generazione Excel:', error);
 +        alert('❌ Errore nella generazione Excel:\n' + error.message);
 +    }
 +}
 +
 +// Crea foglio riepilogo mensile
 +function createSummarySheet(preparations) {
 +    const selectedMonth = document.getElementById('selectedMonth').value;
 +    const monthName = new Date(selectedMonth + '-01').toLocaleDateString('it-IT',
 +        year: 'numeric', 
 +        month: 'long' 
 +    });
 +    
 +    const stats = calculateMonthlyStats(preparations);
 +    
 +    const data = [
 +        [`REPORT MENSILE NPT - ${monthName.toUpperCase()}`, '', '', ''],
 +        [`Generato il: ${new Date().toLocaleDateString('it-IT')}`, '', '', ''],
 +        [`Sistema: NPT Calculator v3.0 UNIFIED`, '', '', ''],
 +        ['', '', '', ''],
 +        ['STATISTICHE GENERALI', '', '', ''],
 +        ['Totale preparazioni NPT:', preparations.length, '', ''],
 +        ['Pazienti unici trattati:', stats.uniquePatients, '', ''],
 +        ['Peso medio pazienti:', `${stats.averageWeight.toFixed(0)}g`, '', ''],
 +        ['GIR medio:', `${stats.averageGIR.toFixed(1)} mg/kg/min`, '', ''],
 +        ['Volume medio NPT:', `${stats.averageVolume.toFixed(0)} ml`, '', ''],
 +        ['', '', '', ''],
 +        ['DISTRIBUZIONE PER PESO', '', '', ''],
 +        ['ELBW (≤1000g):', preparations.filter(p => p.paziente.pesoAttuale <= 1000).length, '', ''],
 +        ['VLBW (1001-1500g):', preparations.filter(p => p.paziente.pesoAttuale > 1000 && p.paziente.pesoAttuale <= 1500).length, '', ''],
 +        ['LBW (1501-2500g):', preparations.filter(p => p.paziente.pesoAttuale > 1500 && p.paziente.pesoAttuale <= 2500).length, '', ''],
 +        ['NBW (>2500g):', preparations.filter(p => p.paziente.pesoAttuale > 2500).length, '', ''],
 +        ['', '', '', ''],
 +        ['DISTRIBUZIONE PER ETÀ', '', '', ''],
 +        ['0-7 giorni:', preparations.filter(p => p.paziente.giorniVita <= 7).length, '', ''],
 +        ['8-14 giorni:', preparations.filter(p => p.paziente.giorniVita > 7 && p.paziente.giorniVita <= 14).length, '', ''],
 +        ['15-30 giorni:', preparations.filter(p => p.paziente.giorniVita > 14 && p.paziente.giorniVita <= 30).length, '', ''],
 +        ['>30 giorni:', preparations.filter(p => p.paziente.giorniVita > 30).length, '', '']
 +    ];
 +    
 +    return data;
 +}
 +
 +// Crea foglio dettaglio preparazioni
 +function createDetailSheet(preparations) {
 +    const header = [
 +        'ID Preparazione', 'Cartella Clinica', 'Data Prescrizione', 'Medico Prescrittore',
 +        'Peso (g)', 'Giorni Vita', 'Volume NPT (ml)', 'GIR (mg/kg/min)', 
 +        'Proteine (g/kg/die)', 'Lipidi (g/kg/die)', 'Energia (kcal/kg/die)',
 +        'Osmolarità (mOsm/L)', 'Farmacista', 'Tecnico 1', 'Tecnico 2'
 +    ];
 +    
 +    const data = [header];
 +    
 +    preparations.forEach(prep => {
 +        const row = [
 +            prep.preparationID || '',
 +            prep.cartellaClinica || '',
 +            prep.dataPrescrizione || '',
 +            prep.personale?.medicoPrescrittore || '',
 +            prep.paziente?.pesoAttuale || 0,
 +            prep.paziente?.giorniVita || 0,
 +            prep.npt?.volumeTotale || 0,
 +            prep.npt?.gir || 0,
 +            prep.npt?.proteine || 0,
 +            prep.npt?.lipidi || 0,
 +            prep.npt?.energia || 0,
 +            prep.npt?.osmolarita || 0,
 +            prep.personale?.farmacistValidatore || '',
 +            prep.personale?.tecnico1 || '',
 +            prep.personale?.tecnico2 || ''
 +        ];
 +        data.push(row);
 +    });
 +    
 +    return data;
 +}
 +
 +// Crea foglio statistiche cliniche
 +function createStatsSheet(preparations) {
 +    const header = [
 +        'PARAMETRO', 'MEDIA', 'MIN', 'MAX', 'DEVIAZIONE STD', 'N° CAMPIONI'
 +    ];
 +    
 +    const data = [
 +        ['STATISTICHE CLINICHE DETTAGLIATE', '', '', '', '', ''],
 +        ['', '', '', '', '', ''],
 +        header
 +    ];
 +    
 +    // Calcola statistiche per ogni parametro clinico
 +    const parameters = [
 +        { name: 'Peso (g)', values: preparations.map(p => p.paziente.pesoAttuale).filter(v => v > 0) },
 +        { name: 'Giorni di vita', values: preparations.map(p => p.paziente.giorniVita).filter(v => v > 0) },
 +        { name: 'Volume NPT (ml)', values: preparations.map(p => p.npt.volumeTotale).filter(v => v > 0) },
 +        { name: 'GIR (mg/kg/min)', values: preparations.map(p => parseFloat(p.npt.gir)).filter(v => !isNaN(v) && v > 0) },
 +        { name: 'Proteine (g/kg/die)', values: preparations.map(p => parseFloat(p.npt.proteine)).filter(v => !isNaN(v) && v > 0) },
 +        { name: 'Lipidi (g/kg/die)', values: preparations.map(p => parseFloat(p.npt.lipidi)).filter(v => !isNaN(v) && v > 0) },
 +        { name: 'Energia (kcal/kg/die)', values: preparations.map(p => parseFloat(p.npt.energia)).filter(v => !isNaN(v) && v > 0) },
 +        { name: 'Osmolarità (mOsm/L)', values: preparations.map(p => p.npt.osmolarita).filter(v => v > 0) }
 +    ];
 +    
 +    parameters.forEach(param => {
 +        if (param.values.length > 0) {
 +            const avg = param.values.reduce((a, b) => a + b, 0) / param.values.length;
 +            const min = Math.min(...param.values);
 +            const max = Math.max(...param.values);
 +            const variance = param.values.reduce((acc, val) => acc + Math.pow(val - avg, 2), 0) / param.values.length;
 +            const stdDev = Math.sqrt(variance);
 +            
 +            data.push([
 +                param.name,
 +                avg.toFixed(2),
 +                min.toFixed(2),
 +                max.toFixed(2),
 +                stdDev.toFixed(2),
 +                param.values.length
 +            ]);
 +        }
 +    });
 +    
 +    // Aggiungi sezione parametri ematochimici se disponibili
 +    data.push(['', '', '', '', '', '']);
 +    data.push(['PARAMETRI EMATOCHIMICI (quando disponibili)', '', '', '', '', '']);
 +    data.push(['', '', '', '', '', '']);
 +    
 +    const bloodParams = [
 +        { name: 'BUN (mg/dL)', values: preparations.map(p => parseFloat(p.parametriClinici?.bun)).filter(v => !isNaN(v)) },
 +        { name: 'Glicemia (mg/dL)', values: preparations.map(p => parseFloat(p.parametriClinici?.glicemia)).filter(v => !isNaN(v)) },
 +        { name: 'Natremia (mEq/L)', values: preparations.map(p => parseFloat(p.parametriClinici?.natremia)).filter(v => !isNaN(v)) },
 +        { name: 'pH', values: preparations.map(p => parseFloat(p.parametriClinici?.ph)).filter(v => !isNaN(v)) }
 +    ];
 +    
 +    bloodParams.forEach(param => {
 +        if (param.values.length > 0) {
 +            const avg = param.values.reduce((a, b) => a + b, 0) / param.values.length;
 +            const min = Math.min(...param.values);
 +            const max = Math.max(...param.values);
 +            const variance = param.values.reduce((acc, val) => acc + Math.pow(val - avg, 2), 0) / param.values.length;
 +            const stdDev = Math.sqrt(variance);
 +            
 +            data.push([
 +                param.name,
 +                avg.toFixed(2),
 +                min.toFixed(2),
 +                max.toFixed(2),
 +                stdDev.toFixed(2),
 +                param.values.length
 +            ]);
 +        }
 +    });
 +    
 +    return data;
 +}
 +
 +// Crea foglio componenti NPT
 +function createComponentsSheet(preparations) {
 +    const header = [
 +        'ID Preparazione', 'Cartella', 'Glucosio 50% (ml)', 'Trophamine (ml)', 
 +        'Intralipid (ml)', 'Acqua Bid. (ml)', 'Ca Gluconato (ml)', 'Esafosfina (ml)',
 +        'Mg Solfato (ml)', 'NaCl (ml)', 'Na Acetato (ml)', 'KCl (ml)',
 +        'Vitalipid (ml)', 'Soluvit (ml)', 'Peditrace (ml)', 'Carnitene (ml)'
 +    ];
 +    
 +    const data = [
 +        ['DETTAGLIO COMPONENTI NPT', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''],
 +        ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''],
 +        header
 +    ];
 +    
 +    preparations.forEach(prep => {
 +        const comp = prep.componenti || {};
 +        const row = [
 +            prep.preparationID || '',
 +            prep.cartellaClinica || '',
 +            comp.glucosio50 || '0.0',
 +            comp.trophamine || '0.0',
 +            comp.intralipid || '0.0',
 +            comp.acquaBidistillata || '0.0',
 +            comp.elettroliti?.ca_gluconato?.toFixed(1) || '0.0',
 +            comp.elettroliti?.esafosfina?.toFixed(1) || '0.0',
 +            comp.elettroliti?.mg_sulfate?.toFixed(1) || '0.0',
 +            comp.elettroliti?.nacl?.toFixed(1) || '0.0',
 +            comp.elettroliti?.sodium_acetate?.toFixed(1) || '0.0',
 +            comp.elettroliti?.kcl?.toFixed(1) || '0.0',
 +            '0.0', // Vitalipid - calcolato dai residual needs
 +            '0.0', // Soluvit - calcolato dai residual needs  
 +            '0.0', // Peditrace - calcolato dai residual needs
 +            '0.0'  // Carnitene - calcolato dai residual needs
 +        ];
 +        data.push(row);
 +    });
 +    
 +    // Aggiungi statistiche componenti
 +    data.push(['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']);
 +    data.push(['STATISTICHE COMPONENTI', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']);
 +    data.push(['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']);
 +    
 +    // Calcola medie componenti
 +    const avgGlucose = preparations.reduce((sum, p) => sum + (parseFloat(p.componenti?.glucosio50) || 0), 0) / preparations.length;
 +    const avgProtein = preparations.reduce((sum, p) => sum + (parseFloat(p.componenti?.trophamine) || 0), 0) / preparations.length;
 +    const avgLipid = preparations.reduce((sum, p) => sum + (parseFloat(p.componenti?.intralipid) || 0), 0) / preparations.length;
 +    const avgWater = preparations.reduce((sum, p) => sum + (parseFloat(p.componenti?.acquaBidistillata) || 0), 0) / preparations.length;
 +    
 +    data.push(['MEDIE COMPONENTI PRINCIPALI', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']);
 +    data.push(['Glucosio 50% medio:', avgGlucose.toFixed(1), 'ml', '', '', '', '', '', '', '', '', '', '', '', '', '']);
 +    data.push(['Trophamine medio:', avgProtein.toFixed(1), 'ml', '', '', '', '', '', '', '', '', '', '', '', '', '']);
 +    data.push(['Intralipid medio:', avgLipid.toFixed(1), 'ml', '', '', '', '', '', '', '', '', '', '', '', '', '']);
 +    data.push(['Acqua Bid. media:', avgWater.toFixed(1), 'ml', '', '', '', '', '', '', '', '', '', '', '', '', '']);
 +    
 +    return data;
 +}
 +
 +// =====================================================
 +// SISTEMA KNOWLEDGE BASE
 +// =====================================================
 +
 +// Funzione per mostrare sezioni Knowledge Base
 +function showKnowledgeSection(sectionId) {
 +    // Nascondi tutte le sezioni knowledge
 +    document.querySelectorAll('.knowledge-section').forEach(section => {
 +        section.classList.remove('active');
 +        section.classList.add('hidden');
 +    });
 +    
 +    // Rimuovi classe active da tutti i tab knowledge
 +    const knowledgeTabs = document.querySelectorAll('#knowledge-base .tabs .tab');
 +    knowledgeTabs.forEach(tab => {
 +        tab.classList.remove('active');
 +    });
 +    
 +    // Mostra la sezione selezionata
 +    const targetSection = document.getElementById(sectionId);
 +    if (targetSection) {
 +        targetSection.classList.remove('hidden');
 +        targetSection.classList.add('active');
 +    }
 +    
 +    // Attiva il tab cliccato
 +    const clickedTab = event.target.closest('.tab');
 +    if (clickedTab) {
 +        clickedTab.classList.add('active');
 +    }
 +    
 +    console.log('Knowledge Base: mostrando sezione', sectionId);
 +}
 +
 +// Database delle regole di calcolo (expandibile)
 +const knowledgeBase = {
 +    calculationRules: {
 +        gir: {
 +            name: "GIR (Glucose Infusion Rate)",
 +            formula: "(Glucidi g/kg/die × 1000) ÷ 1440",
 +            unit: "mg/kg/min",
 +            normalRange: "4-12",
 +            alerts: [
 +                { condition: "> 12", action: "Ridurre concentrazione glucosio", severity: "warning" },
 +                { condition: "> 15", action: "Sospendere temporaneamente NPT", severity: "critical" }
 +            ],
 +            rationale: "Il GIR elevato può causare iperglicemia e richiede monitoraggio glicemico frequente"
 +        },
 +        osmolarity: {
 +            name: "Osmolarità NPT",
 +            formula: "Σ(Volume componente × Osmolarità componente) ÷ Volume totale",
 +            unit: "mOsm/L",
 +            thresholds: [
 +                { range: "< 600", access: "Periferico possibile", color: "green" },
 +                { range: "600-900", access: "CVC raccomandato", color: "orange" },
 +                { range: "> 900", access: "Solo CVC (ipertonica)", color: "red" }
 +            ],
 +            rationale: "L'osmolarità determina la via di accesso vascolare per evitare flebiti"
 +        },
 +        proteinAdjustment: {
 +            name: "Aggiustamento Proteine (BUN-driven)",
 +            rules: [
 +                { bun: "< 9 mg/dL", action: "Aumenta proteine +1 g/kg/die", rationale: "BUN basso indica catabolismo insufficiente" },
 +                { bun: "9-14 mg/dL", action: "Mantieni proteine attuali", rationale: "Range ottimale per neonati" },
 +                { bun: "> 14 mg/dL", action: "Riduci proteine -1 g/kg/die", rationale: "BUN elevato indica sovraccarico azotato" }
 +            ],
 +            monitoring: "Controllo BUN ogni 48-72h durante NPT"
 +        }
 +    },
 +    
 +    clinicalGuidelines: {
 +        ageProtocols: {
 +            elbw: { name: "ELBW ≤1000g", protocols: [] },
 +            vlbw: { name: "VLBW 1001-1500g", protocols: [] },
 +            lbw: { name: "LBW 1501-2500g", protocols: [] },
 +            term: { name: "Term >2500g", protocols: [] }
 +        }
 +    },
 +    
 +    alerts: {
 +        critical: [],
 +        warning: [],
 +        info: []
 +    }
 +};
 +
 +// Funzione per ottenere spiegazione di una regola
 +function getCalculationExplanation(parameter, value) {
 +    const rules = knowledgeBase.calculationRules;
 +    let explanation = "";
 +    
 +    switch(parameter) {
 +        case 'gir':
 +            if (value > 12) {
 +                explanation = "⚠️ GIR elevato: Rischio iperglicemia. Considera riduzione glucosio o aumento velocità.";
 +            } else if (value < 4) {
 +                explanation = "⚠️ GIR basso: Possibile ipoglicemia. Verifica apporti glucidici.";
 +            } else {
 +                explanation = "✅ GIR ottimale: Range di sicurezza per neonati.";
 +            }
 +            break;
 +            
 +        case 'osmolarity':
 +            if (value > 900) {
 +                explanation = "🔴 Osmolarità ipertonica: OBBLIGATORIO accesso venoso centrale.";
 +            } else if (value > 600) {
 +                explanation = "🟠 Osmolarità elevata: Raccomandato accesso venoso centrale.";
 +            } else {
 +                explanation = "🟢 Osmolarità normale: Compatibile con accesso periferico.";
 +            }
 +            break;
 +            
 +        default:
 +            explanation = "Parametro monitorato dal sistema.";
 +    }
 +    
 +    return explanation;
 +}
 +
 +// Funzione per mostrare tooltip informativi
 +function showKnowledgeTooltip(element, content) {
 +    // Crea tooltip dinamico
 +    const tooltip = document.createElement('div');
 +    tooltip.className = 'knowledge-tooltip';
 +    tooltip.innerHTML = content;
 +    tooltip.style.cssText = `
 +        position: absolute;
 +        background-color: #2c3e50;
 +        color: white;
 +        padding: 10px;
 +        border-radius: 5px;
 +        font-size: 12px;
 +        max-width: 300px;
 +        z-index: 1000;
 +        box-shadow: 0 2px 10px rgba(0,0,0,0.3);
 +    `;
 +    
 +    document.body.appendChild(tooltip);
 +    
 +    // Posiziona tooltip
 +    const rect = element.getBoundingClientRect();
 +    tooltip.style.left = rect.left + 'px';
 +    tooltip.style.top = (rect.bottom + 5) + 'px';
 +    
 +    // Rimuovi dopo 3 secondi
 +    setTimeout(() => {
 +        if (tooltip.parentNode) {
 +            tooltip.remove();
 +        }
 +    }, 3000);
 +}
 +
 +// Aggiorna la funzione showTab esistente per gestire il knowledge base
 +function showTabOriginal(tabId) {
 +    // Funzione originale già esistente - non modificare
 +    // Questa è solo per referenza
 } }
  
Linea 3131: Linea 6439:
     document.getElementById('departmentName').value = clinicalConfig.departmentName;     document.getElementById('departmentName').value = clinicalConfig.departmentName;
     document.getElementById('directorName').value = clinicalConfig.directorName;     document.getElementById('directorName').value = clinicalConfig.directorName;
-    +       
     updateFortifierOptions();     updateFortifierOptions();
 +   // Inizializza tutte le dropdown e tabelle
     updateDoctorsDropdown();     updateDoctorsDropdown();
 +    console.log('Dropdown medici inizializzata con', Object.keys(doctorsData).length, 'medici');
 +    // Test per verificare che la dropdown sia stata popolata
 +    setTimeout(() => {
 +        const prescribingDoctorSelect = document.getElementById('prescribingDoctor');
 +        if (prescribingDoctorSelect) {
 +            console.log('Opzioni dropdown medici:', prescribingDoctorSelect.options.length);
 +        }
 +    }, 500);
 +
 +// Inizializza sezione mensile
 +    initializeMonthlySection();
     console.log('NPT Calculator v3.0 UNIFIED pronto');     console.log('NPT Calculator v3.0 UNIFIED pronto');
 }); });
docuneo/programma_npt.1754163976.txt.gz · Ultima modifica: da neoadmin