Differenze
Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
| Entrambe le parti precedenti la revisioneRevisione precedente | |||
| docuneo:programma_npt [2025/08/02 21:46] – neoadmin | docuneo:programma_npt [2025/08/11 15:34] (versione attuale) – neoadmin | ||
|---|---|---|---|
| Linea 5: | Linea 5: | ||
| < | < | ||
| <script src=" | <script src=" | ||
| + | <script src=" | ||
| + | | ||
| + | < | ||
| + | // Simple Barcode Generator - CODE128 - Versione Embedded | ||
| + | window.SimpleBarcode = (function() { | ||
| + | | ||
| + | // Patterns per CODE128 | ||
| + | const patterns = { | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | }; | ||
| + | | ||
| + | function generateCode128(text) { | ||
| + | // START B (per caratteri ASCII normali) | ||
| + | let result = patterns[' | ||
| + | let checksum = 104; | ||
| + | | ||
| + | // Aggiungi ogni carattere | ||
| + | for (let i = 0; i < text.length; | ||
| + | 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[' | ||
| + | | ||
| + | return result; | ||
| + | } | ||
| + | | ||
| + | function drawBarcode(canvas, | ||
| + | const ctx = canvas.getContext(' | ||
| + | const data = generateCode128(text); | ||
| + | | ||
| + | // Opzioni default | ||
| + | const opts = { | ||
| + | width: options.width || 2, | ||
| + | height: options.height || 60, | ||
| + | margin: options.margin || 5, | ||
| + | background: options.background || '# | ||
| + | lineColor: options.lineColor || '# | ||
| + | }; | ||
| + | | ||
| + | // 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, | ||
| + | | ||
| + | // Background | ||
| + | ctx.fillStyle = opts.background; | ||
| + | ctx.fillRect(0, | ||
| + | | ||
| + | // Disegna le barre | ||
| + | ctx.fillStyle = opts.lineColor; | ||
| + | let x = opts.margin; | ||
| + | | ||
| + | for (let i = 0; i < data.length; | ||
| + | if (data[i] === ' | ||
| + | ctx.fillRect(x, | ||
| + | } | ||
| + | x += barWidth; | ||
| + | } | ||
| + | | ||
| + | console.log(' | ||
| + | } | ||
| + | | ||
| + | return { | ||
| + | generate: drawBarcode | ||
| + | }; | ||
| + | })(); | ||
| + | </ | ||
| + | | ||
| < | < | ||
| + | * { | ||
| + | font-family: | ||
| + | } | ||
| body { | body { | ||
| - | | + | |
| - | margin: 0; | + | margin: 0; |
| - | padding: 20px; | + | padding: 20px; |
| - | background-color: | + | background-color: |
| - | } | + | } |
| .container { | .container { | ||
| Linea 23: | Linea 131: | ||
| h1 { | h1 { | ||
| - | | + | |
| - | color: #2c3e50; | + | |
| - | border-bottom: 3px solid #3498db; | + | color: |
| - | padding-bottom: 10px; | + | background: linear-gradient(135deg, |
| + | border: | ||
| + | padding: 20px; | ||
| + | border-radius: 10px; | ||
| + | margin-bottom: | ||
| + | text-shadow: | ||
| + | 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: | ||
| + | } | ||
| + | .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: | ||
| + | background-color: | ||
| + | transform: none !important; | ||
| + | } | ||
| + | |||
| + | .config-tab.active { | ||
| + | background-color: | ||
| + | color: white; | ||
| + | transform: none !important; | ||
| } | } | ||
| Linea 397: | Linea 543: | ||
| margin-top: 30px; | margin-top: 30px; | ||
| background-color: | background-color: | ||
| - | font-family: | + | font-family: |
| line-height: | line-height: | ||
| } | } | ||
| Linea 440: | Linea 586: | ||
| box-shadow: none; | box-shadow: none; | ||
| } | } | ||
| + | | ||
| + | | ||
| } | } | ||
| + | |||
| + | /* NUOVA INTESTAZIONE MEDICA ASST LECCO */ | ||
| + | .medical-header-table { | ||
| + | width: 100%; | ||
| + | border-collapse: | ||
| + | border: 2px solid #2c3e50; | ||
| + | margin-bottom: | ||
| + | } | ||
| + | |||
| + | .medical-header-table td { | ||
| + | border: 1px solid #2c3e50; | ||
| + | padding: 10px; | ||
| + | vertical-align: | ||
| + | } | ||
| + | |||
| + | .medical-header-left { | ||
| + | width: 45%; | ||
| + | background-color: | ||
| + | } | ||
| + | |||
| + | .medical-header-center { | ||
| + | width: 30%; | ||
| + | text-align: center; | ||
| + | background-color: | ||
| + | } | ||
| + | |||
| + | .medical-header-right { | ||
| + | width: 25%; | ||
| + | text-align: center; | ||
| + | background-color: | ||
| + | } | ||
| + | |||
| + | .medical-header-left h2 { | ||
| + | font-size: 14px; | ||
| + | font-weight: | ||
| + | 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: | ||
| + | border: 2px solid #2c3e50; | ||
| + | margin-bottom: | ||
| + | } | ||
| + | |||
| + | .medical-header-table td { | ||
| + | border: 1px solid #2c3e50; | ||
| + | padding: 10px; | ||
| + | vertical-align: | ||
| + | } | ||
| + | |||
| + | .medical-header-left { | ||
| + | width: 45%; | ||
| + | background-color: | ||
| + | } | ||
| + | |||
| + | .medical-header-center { | ||
| + | width: 30%; | ||
| + | text-align: center; | ||
| + | background-color: | ||
| + | } | ||
| + | |||
| + | .medical-header-right { | ||
| + | width: 25%; | ||
| + | text-align: center; | ||
| + | background-color: | ||
| + | } | ||
| + | |||
| + | .medical-header-left h2 { | ||
| + | font-size: 14px; | ||
| + | font-weight: | ||
| + | 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: | ||
| + | color: white; | ||
| + | padding: 10px; | ||
| + | border-radius: | ||
| + | font-size: 12px; | ||
| + | max-width: 300px; | ||
| + | z-index: 1000; | ||
| + | box-shadow: 0 2px 10px rgba(0, | ||
| + | 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: | ||
| + | padding-bottom: | ||
| + | margin-bottom: | ||
| + | } | ||
| + | |||
| + | .knowledge-section h4 { | ||
| + | color: #34495e; | ||
| + | margin-top: 20px; | ||
| + | margin-bottom: | ||
| + | } | ||
| + | |||
| + | /* STILI SPECIFICI PER ETICHETTA SACCA */ | ||
| + | .label-section { | ||
| + | border: 3px solid #2c3e50; | ||
| + | background-color: | ||
| + | padding: 15px; | ||
| + | margin: 15px 0; | ||
| + | border-radius: | ||
| + | } | ||
| + | |||
| + | .label-patient-id { | ||
| + | border: 4px solid #d32f2f; | ||
| + | background-color: | ||
| + | padding: 15px; | ||
| + | margin: 15px 0; | ||
| + | text-align: center; | ||
| + | border-radius: | ||
| + | } | ||
| + | |||
| + | .label-content { | ||
| + | border: 3px solid #388e3c; | ||
| + | background-color: | ||
| + | padding: 15px; | ||
| + | margin: 15px 0; | ||
| + | border-radius: | ||
| + | } | ||
| + | |||
| + | .label-header { | ||
| + | text-align: center; | ||
| + | border-bottom: | ||
| + | padding-bottom: | ||
| + | margin-bottom: | ||
| + | } | ||
| + | |||
| + | .label-volume-total { | ||
| + | background-color: | ||
| + | color: white; | ||
| + | font-weight: | ||
| + | font-size: 16px; | ||
| + | } | ||
| + | |||
| </ | </ | ||
| </ | </ | ||
| Linea 446: | Linea 775: | ||
| <div class=" | <div class=" | ||
| - | <h1>Programma NPT Neonatale | + | <h1>Gestione della Nutrizione del Neonato (GNN v3.0)</ |
| - | <div class=" | + | |
| - | < | + | < |
| - | </ | + | </ |
| | | ||
| <!-- TAB ORIZZONTALI CORRETTI --> | <!-- TAB ORIZZONTALI CORRETTI --> | ||
| <div class=" | <div class=" | ||
| - | | + | |
| - | <span style=" | + | <span style=" |
| - | </ | + | </ |
| - | + | ||
| - | <!-- SEZIONE CONFIGURAZIONE COMPONENTI (DA VERSIONE 17) --> | + | <!-- SEZIONE CONFIGURAZIONE COMPONENTI (DA VERSIONE 17) --> |
| - | <div class=" | + | <div class=" |
| - | <span style=" | + | <span style=" |
| - | </ | + | </ |
| - | <div class=" | + | <div class=" |
| - | <span style=" | + | <span style=" |
| - | </ | + | </ |
| - | <div class=" | + | <div class=" |
| - | <span style=" | + | <span style=" |
| - | </ | + | </ |
| - | <div class=" | + | <div class=" |
| - | <span style=" | + | <span style=" |
| - | </ | + | </ |
| - | <div class=" | + | <div class=" |
| - | <span style=" | + | <span style=" |
| - | </ | + | </ |
| + | <div class=" | ||
| + | | ||
| + | | ||
| </ | </ | ||
| <!-- TAB 1: DATI PAZIENTE (VERSIONE 17 ORIGINALE) --> | <!-- TAB 1: DATI PAZIENTE (VERSIONE 17 ORIGINALE) --> | ||
| <div id=" | <div id=" | ||
| - | | + | <div class=" |
| - | < | + | < |
| - | < | + | < |
| - | </ | + | |
| + | </ | ||
| <div class=" | <div class=" | ||
| < | < | ||
| Linea 527: | Linea 860: | ||
| <input type=" | <input type=" | ||
| </ | </ | ||
| + | |||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <div style=" | ||
| + | <input type=" | ||
| + | < | ||
| + | <input type=" | ||
| + | < | ||
| + | <span style=" | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <div style=" | ||
| + | <input type=" | ||
| + | <span style=" | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| </ | </ | ||
| <div class=" | <div class=" | ||
| Linea 845: | Linea 1202: | ||
| <div id=" | <div id=" | ||
| | | ||
| + | |||
| <div style=" | <div style=" | ||
| <button class=" | <button class=" | ||
| <button class=" | <button class=" | ||
| + | <button class=" | ||
| </ | </ | ||
| </ | </ | ||
| </ | </ | ||
| + | |||
| <!-- TAB 5: REPORT FINALE (SPOSTATO DA TAB 6) --> | <!-- TAB 5: REPORT FINALE (SPOSTATO DA TAB 6) --> | ||
| Linea 857: | Linea 1217: | ||
| < | < | ||
| < | < | ||
| + | </ | ||
| + | |||
| + | <!-- Banner stato prescrizione --> | ||
| + | <div id=" | ||
| + | <!-- Popolato dinamicamente --> | ||
| + | </ | ||
| + | <div class=" | ||
| + | < | ||
| + | <button class=" | ||
| + | <button class=" | ||
| + | <button class=" | ||
| + | <button class=" | ||
| + | <!-- Report appare subito qui sotto i pulsanti --> | ||
| + | <div id=" | ||
| + | </ | ||
| + | |||
| + | <!-- SEZIONE 2A: VALIDAZIONE FARMACISTA --> | ||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Il farmacista deve validare la prescrizione medica prima dell' | ||
| + | </ | ||
| + | | ||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <select id=" | ||
| + | <option value=""> | ||
| + | <!-- Popolato dinamicamente da pharmacistsData --> | ||
| + | </ | ||
| + | </ | ||
| + | <div class=" | ||
| + | < | ||
| + | </ | ||
| </ | </ | ||
| | | ||
| - | <div class=" | + | <div class=" |
| - | <h2>Genera Documentazione</ | + | |
| - | <button | + | 📝 VALIDA PRESCRIZIONE |
| - | <button | + | </ |
| - | <button | + | <div id=" |
| + | <!-- Status validazione --> | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <!-- SEZIONE 2B: ALLESTIMENTO TECNICI --> | ||
| + | <div class=" | ||
| + | | ||
| + | <div class=" | ||
| + | < | ||
| + | Due tecnici qualificati preparano la sacca NPT secondo protocolli GMP con controllo incrociato. | ||
| + | </ | ||
| + | |||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <label for="preparingTechnician1">Primo Tecnico Preparatore: | ||
| + | <select id=" | ||
| + | <option value=""> | ||
| + | <!-- Popolato dinamicamente da technicianData --> | ||
| + | </select> | ||
| + | </div> | ||
| + | |||
| + | < | ||
| + | <label for="preparingTechnician2">Secondo Tecnico Preparatore: | ||
| + | <select id=" | ||
| + | <option value=""> | ||
| + | <!-- Popolato dinamicamente da technicianData --> | ||
| + | </select> | ||
| + | </div> | ||
| + | < | ||
| + | < | ||
| + | </div> | ||
| </ | </ | ||
| | | ||
| - | <div id="reportOutput"></ | + | < |
| + | <button class=" | ||
| + | 🧪 CONFERMA ALLESTIMENTO | ||
| + | </ | ||
| + | < | ||
| + | 💾 ARCHIVIA PREPARAZIONE (JSON) | ||
| + | </ | ||
| + | <button class=" | ||
| + | 🔒 BLOCCA PRESCRIZIONE | ||
| + | </ | ||
| + | <div id=" | ||
| + | <!-- Status preparazione --> | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <!-- SEZIONE ARCHIVIAZIONE MENSILE --> | ||
| + | |||
| + | < | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Genera report Excel mensile con tutte le preparazioni NPT archiviate come JSON. | ||
| + | </ | ||
| + | |||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <input type=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | <label for=" | ||
| + | <input type=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <div class=" | ||
| + | <button class=" | ||
| + | 📊 GENERA EXCEL MENSILE | ||
| + | </ | ||
| + | <button class=" | ||
| + | 👁️ ANTEPRIMA DATI | ||
| + | </ | ||
| + | |||
| + | <div id=" | ||
| + | <!-- Statistiche mensili popolate dinamicamente --> | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | <!-- TAB 6: KNOWLEDGE BASE --> | ||
| + | <div id=" | ||
| + | <div class=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <!-- NAVIGAZIONE INTERNA KNOWLEDGE BASE --> | ||
| + | <div class=" | ||
| + | <div class=" | ||
| + | 🧮 Regole Calcolo | ||
| + | </ | ||
| + | <div class=" | ||
| + | 👩⚕️ Linee Guida | ||
| + | </ | ||
| + | <div class=" | ||
| + | 🚨 Sistema Alert | ||
| + | </ | ||
| + | <div class=" | ||
| + | 📖 Evidenze | ||
| + | </ | ||
| + | <div class=" | ||
| + | 🎯 Decision Support | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <!-- SEZIONE 1: REGOLE DI CALCOLO --> | ||
| + | <div id=" | ||
| + | <div class=" | ||
| + | < | ||
| + | |||
| + | <div class=" | ||
| + | < | ||
| + | |||
| + | <div class=" | ||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | < | ||
| + | • < 600 mOsm/L: Accesso periferico possibile< | ||
| + | • 600-900 mOsm/L: CVC raccomandato< | ||
| + | • > 900 mOsm/L: Solo CVC (soluzione ipertonica) | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <div class=" | ||
| + | < | ||
| + | <div style=" | ||
| + | <table class=" | ||
| + | < | ||
| + | < | ||
| + | <th style=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <!-- SEZIONE 2: LINEE GUIDA CLINICHE (placeholder per ora) --> | ||
| + | <div id=" | ||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Questa sezione conterrà protocolli per età, patologie e tempistiche. | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <!-- SEZIONE 3: SISTEMA ALERT (placeholder per ora) --> | ||
| + | <div id=" | ||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Questa sezione spiegherà soglie di allarme e azioni consigliate. | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <!-- SEZIONE 4: EVIDENZE (placeholder per ora) --> | ||
| + | <div id=" | ||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Questa sezione conterrà bibliografia e riferimenti scientifici. | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <!-- SEZIONE 5: DECISION SUPPORT (placeholder per ora) --> | ||
| + | <div id=" | ||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Questa sezione conterrà configurazione regole e simulatore. | ||
| + | </ | ||
| + | </div> | ||
| + | | ||
| </ | </ | ||
| Linea 983: | Linea 1647: | ||
| <table class=" | <table class=" | ||
| < | < | ||
| - | | + | |
| - | <th style=" | + | <th style=" |
| - | < | + | < |
| - | < | + | < |
| - | < | + | < |
| - | < | + | < |
| - | < | + | < |
| - | < | + | < |
| - | < | + | < |
| - | < | + | < |
| - | < | + | < |
| - | < | + | < |
| - | <th style=" | + | < |
| - | < | + | |
| - | </ | + | < |
| - | </ | + | </ |
| + | </ | ||
| <tbody id=" | <tbody id=" | ||
| <!-- Popolato dinamicamente --> | <!-- Popolato dinamicamente --> | ||
| Linea 1044: | Linea 1709: | ||
| </ | </ | ||
| </ | </ | ||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Gestisci la lista delle infermiere del reparto. Le modifiche si applicano automaticamente. | ||
| + | </ | ||
| + | <div style=" | ||
| + | <table class=" | ||
| + | < | ||
| + | <tr> | ||
| + | <th style=" | ||
| + | <th style=" | ||
| + | <th style=" | ||
| + | <th style=" | ||
| + | < | ||
| + | </tr> | ||
| + | </ | ||
| + | <tbody id=" | ||
| + | <!-- Popolato dinamicamente --> | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <button id=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | <button class=" | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Gestisci la lista dei farmacisti ospedalieri. Le modifiche si applicano automaticamente. | ||
| + | </ | ||
| + | <div style=" | ||
| + | <table class=" | ||
| + | < | ||
| + | <tr> | ||
| + | <th style=" | ||
| + | <th style=" | ||
| + | <th style=" | ||
| + | <th style=" | ||
| + | < | ||
| + | </tr> | ||
| + | </ | ||
| + | <tbody id=" | ||
| + | <!-- Popolato dinamicamente --> | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <button id=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | <button class=" | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <div class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Gestisci la lista dei tecnici di farmacia. Le modifiche si applicano automaticamente. | ||
| + | </ | ||
| + | <div style=" | ||
| + | <table class=" | ||
| + | < | ||
| + | <tr> | ||
| + | <th style=" | ||
| + | <th style=" | ||
| + | <th style=" | ||
| + | <th style=" | ||
| + | < | ||
| + | </tr> | ||
| + | </ | ||
| + | <tbody id=" | ||
| + | <!-- Popolato dinamicamente --> | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | <div class=" | ||
| + | <div class=" | ||
| + | <button id=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | <button class=" | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| </ | </ | ||
| 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: | description: | ||
| notes: " | notes: " | ||
| 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: | description: | ||
| - | notes: " | + | notes: " |
| }, | }, | ||
| 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: | description: | ||
| - | notes: " | + | notes: " |
| }, | }, | ||
| 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: | description: | ||
| - | notes: "8.4 mg Ca/ml. Non precipita con fosfati" | + | notes: "8.4 mg Ca/ml. Non precipita con fosfati. Osmolarità: |
| }, | }, | ||
| 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: | description: | ||
| - | 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à: |
| }, | }, | ||
| 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: | description: | ||
| - | notes: "8 mEq Mg/ml. Cofattore enzimatico" | + | notes: "8 mEq Mg/ml. Cofattore enzimatico. Osmolarità: |
| }, | }, | ||
| 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: | description: | ||
| - | notes: "10 mEq Na/ml. Prima scelta per supplementazione sodio" | + | notes: "10 mEq Na/ml. Prima scelta per supplementazione sodio. Osmolarità: |
| }, | }, | ||
| sodium_acetate: | sodium_acetate: | ||
| - | name: "Sodio Acetato (2 mEq/ | + | name: "Sodio Acetato (3 mEq/ |
| 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: | description: | ||
| - | 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à: |
| }, | }, | ||
| 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: | description: | ||
| - | notes: "10 mEq K/ml. Max velocità infusione: 0.5 mEq/ | + | notes: "10 mEq K/ml. Max velocità infusione: 0.5 mEq/kg/h. Osmolarità: |
| }, | }, | ||
| 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: | description: | ||
| - | notes: "100 mg/ml. Indicata per NPT > 1 mese. Dose: 5 mg/ | + | notes: "100 mg/ml. Indicata per NPT > 1 mese. Dose: 5 mg/kg/die. Osmolarità: |
| } | } | ||
| }; | }; | ||
| Linea 1324: | Linea 2094: | ||
| dr_aquisti: { name: " | dr_aquisti: { name: " | ||
| }; | }; | ||
| + | |||
| + | // Database infermiere dinamico | ||
| + | let nursesData = { | ||
| + | inf_rossi: { name: " | ||
| + | inf_bianchi: | ||
| + | inf_verdi: { name: " | ||
| + | inf_ferrari: | ||
| + | inf_moretti: | ||
| + | inf_conti: { name: " | ||
| + | }; | ||
| + | |||
| + | // Database farmacisti dinamico | ||
| + | let pharmacistsData = { | ||
| + | farm_lombardi: | ||
| + | farm_ricci: { name: " | ||
| + | farm_marino: | ||
| + | farm_greco: { name: " | ||
| + | farm_bruno: { name: " | ||
| + | }; | ||
| + | |||
| + | // Database tecnici di farmacia dinamico | ||
| + | let technicianData = { | ||
| + | tec_russo: { name: " | ||
| + | tec_gallo: { name: " | ||
| + | tec_costa: { name: " | ||
| + | tec_rizzo: { name: " | ||
| + | tec_longo: { name: " | ||
| + | tec_giordano: | ||
| + | }; | ||
| + | |||
| + | |||
| // VARIABILI GLOBALI | // VARIABILI GLOBALI | ||
| Linea 1339: | Linea 2140: | ||
| maxProtein: 4.5, | maxProtein: 4.5, | ||
| hospitalName: | hospitalName: | ||
| - | departmentName: | + | departmentName: |
| - | directorName: | + | directorName: |
| }; | }; | ||
| Linea 1381: | Linea 2182: | ||
| } | } | ||
| } | } | ||
| + | |||
| + | |||
| + | // SISTEMA PROTEZIONE CONFIGURAZIONE | ||
| + | function checkConfigAccess() { | ||
| + | // Password predefinita (modificabile) | ||
| + | const ADMIN_PASSWORD = " | ||
| + | | ||
| + | // Controlla se l' | ||
| + | if (window.configAccessGranted === true) { | ||
| + | return true; | ||
| + | } | ||
| + | | ||
| + | // Richiedi password | ||
| + | const userPassword = prompt( | ||
| + | "🔐 ACCESSO CONFIGURAZIONE RISERVATO\n\n" | ||
| + | " | ||
| + | ); | ||
| + | | ||
| + | // Se utente cancella | ||
| + | if (userPassword === null) { | ||
| + | return false; | ||
| + | } | ||
| + | | ||
| + | // Verifica password | ||
| + | if (userPassword === ADMIN_PASSWORD) { | ||
| + | window.configAccessGranted = true; | ||
| + | alert(" | ||
| + | return true; | ||
| + | } else { | ||
| + | alert(" | ||
| + | return false; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Funzione per logout configurazione | ||
| + | function logoutConfig() { | ||
| + | window.configAccessGranted = false; | ||
| + | alert(" | ||
| + | // Torna al TAB 1 | ||
| + | showTab(' | ||
| + | } | ||
| + | |||
| // FUNZIONE CORRETTA PER CAMBIO TAB | // FUNZIONE CORRETTA PER CAMBIO TAB | ||
| Linea 1406: | Linea 2249: | ||
| } | } | ||
| | | ||
| - | // Popola le tabelle | + | // Sistema |
| if (tabId === ' | if (tabId === ' | ||
| + | if (!checkConfigAccess()) { | ||
| + | return; // Blocca l' | ||
| + | } | ||
| 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 === ' | ||
| + | setTimeout(() => { | ||
| + | updatePreparationStaffDropdowns(); | ||
| + | }, 100); | ||
| + | } | ||
| + | |||
| } | } | ||
| Linea 1462: | Linea 2319: | ||
| function updateDoctorsDropdown() { | function updateDoctorsDropdown() { | ||
| + | console.log(' | ||
| const prescribingDoctorSelect = document.getElementById(' | const prescribingDoctorSelect = document.getElementById(' | ||
| - | if (!prescribingDoctorSelect) return; | + | |
| + | |||
| + | | ||
| + | console.error(' | ||
| + | | ||
| + | } | ||
| + | |||
| + | console.log(' | ||
| + | console.log(' | ||
| | | ||
| 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(' | ||
| const option = document.createElement(' | const option = document.createElement(' | ||
| option.value = key; | option.value = key; | ||
| Linea 1480: | Linea 2347: | ||
| prescribingDoctorSelect.value = currentValue; | prescribingDoctorSelect.value = currentValue; | ||
| } | } | ||
| + | | ||
| + | console.log(' | ||
| + | } | ||
| + | |||
| + | // FUNZIONE CALCOLO ETÀ POST-CONCEZIONALE | ||
| + | function calculatePostConceptionalAge() { | ||
| + | const gestWeeks = parseInt(document.getElementById(' | ||
| + | const gestDays = parseInt(document.getElementById(' | ||
| + | const daysOfLife = parseInt(document.getElementById(' | ||
| + | | ||
| + | if (gestWeeks === 0 || daysOfLife === 0) { | ||
| + | document.getElementById(' | ||
| + | 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 + ' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | return { weeks: pcWeeks, days: pcDays, format: pcAge }; | ||
| } | } | ||
| Linea 1501: | Linea 2395: | ||
| doctorsData[prescribingDoctorValue].fullName : ''; | doctorsData[prescribingDoctorValue].fullName : ''; | ||
| | | ||
| - | | + | |
| - | medicalRecord: | + | // Recupera età gestazionale per i report |
| - | birthWeight: | + | const gestationalWeeks = parseInt(document.getElementById(' |
| - | currentWeight: | + | const gestationalDays = parseInt(document.getElementById(' |
| - | daysOfLife: daysOfLife, | + | |
| - | bun: bun, | + | // Calcola età post-concezionale |
| - | glucose: glucose, | + | const postConceptionalAge = calculatePostConceptionalAge(); |
| - | sodium: sodium, | + | |
| - | ph: ph, | + | patientData = { |
| - | baseExcess: baseExcess, | + | medicalRecord: |
| - | diuresis: diuresis, | + | birthWeight: |
| - | prescriptionDate: | + | currentWeight: |
| - | prescribingDoctor: | + | daysOfLife: daysOfLife, |
| - | prescribingDoctorName: | + | |
| - | }; | + | gestationalDays: |
| + | postConceptionalAge: | ||
| + | | ||
| + | glucose: glucose, | ||
| + | sodium: sodium, | ||
| + | ph: ph, | ||
| + | baseExcess: baseExcess, | ||
| + | diuresis: diuresis, | ||
| + | prescriptionDate: | ||
| + | prescribingDoctor: | ||
| + | prescribingDoctorName: | ||
| + | }; | ||
| | | ||
| document.getElementById(' | document.getElementById(' | ||
| Linea 1605: | Linea 2510: | ||
| phaseInfoHtml += '< | phaseInfoHtml += '< | ||
| phaseInfoHtml += '< | phaseInfoHtml += '< | ||
| + | | ||
| + | if (gestationalWeeks && gestationalWeeks > 0) { | ||
| + | const gestDaysDisplay = gestationalDays || 0; | ||
| + | phaseInfoHtml += '< | ||
| + | if (postConceptionalAge && postConceptionalAge.format) { | ||
| + | phaseInfoHtml += '< | ||
| + | } | ||
| + | } | ||
| phaseInfoHtml += '< | phaseInfoHtml += '< | ||
| phaseInfoHtml += '</ | phaseInfoHtml += '</ | ||
| Linea 2158: | Linea 3071: | ||
| | | ||
| return additions; | return additions; | ||
| + | } | ||
| + | |||
| + | |||
| + | // FUNZIONE CALCOLO OSMOLARITÀ NPT (MIGLIORATA) | ||
| + | function calculateNPTOsmolarity(calc, | ||
| + | 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: ' | ||
| + | volume: calc.glucose50Volume, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | // Trophamine 6% | ||
| + | const proteinOsmol = (calc.proteinVolume * parenteralConfig.trophamine.osmolarity) / calc.totalVolume; | ||
| + | osmolarityBreakdown.protein = proteinOsmol; | ||
| + | totalOsmolarity += proteinOsmol; | ||
| + | componentDetails.push({ | ||
| + | name: ' | ||
| + | volume: calc.proteinVolume, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | | ||
| + | // Intralipid 20% | ||
| + | const lipidOsmol = (calc.lipidVolume * parenteralConfig.intralipid.osmolarity) / calc.totalVolume; | ||
| + | osmolarityBreakdown.lipid = lipidOsmol; | ||
| + | totalOsmolarity += lipidOsmol; | ||
| + | componentDetails.push({ | ||
| + | name: ' | ||
| + | volume: calc.lipidVolume, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | | ||
| + | // 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: ' | ||
| + | volume: calc.electrolyteAdditions.ca_gluconato, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | if (calc.electrolyteAdditions.esafosfina > 0) { | ||
| + | const pOsmol = (calc.electrolyteAdditions.esafosfina * parenteralConfig.esafosfina.osmolarity) / calc.totalVolume; | ||
| + | osmolarityBreakdown.phosphorus = pOsmol; | ||
| + | totalOsmolarity += pOsmol; | ||
| + | componentDetails.push({ | ||
| + | name: ' | ||
| + | volume: calc.electrolyteAdditions.esafosfina, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | 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: ' | ||
| + | volume: calc.electrolyteAdditions.mg_sulfate, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | 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: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | 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: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | if (calc.electrolyteAdditions.kcl > 0) { | ||
| + | const kclOsmol = (calc.electrolyteAdditions.kcl * parenteralConfig.kcl.osmolarity) / calc.totalVolume; | ||
| + | osmolarityBreakdown.kcl = kclOsmol; | ||
| + | totalOsmolarity += kclOsmol; | ||
| + | componentDetails.push({ | ||
| + | name: ' | ||
| + | volume: calc.electrolyteAdditions.kcl, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | // 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: ' | ||
| + | volume: vitalipidVolume, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | if (residualNeeds.soluvit > 0) { | ||
| + | const soluvitVolume = residualNeeds.soluvit * currentWeightKg; | ||
| + | const solOsmol = (soluvitVolume * 300) / calc.totalVolume; | ||
| + | vitaminsOsmol += solOsmol; | ||
| + | componentDetails.push({ | ||
| + | name: ' | ||
| + | volume: soluvitVolume, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | if (residualNeeds.peditrace > 0) { | ||
| + | const peditraceVolume = residualNeeds.peditrace * currentWeightKg; | ||
| + | const pedOsmol = (peditraceVolume * 350) / calc.totalVolume; | ||
| + | vitaminsOsmol += pedOsmol; | ||
| + | componentDetails.push({ | ||
| + | name: ' | ||
| + | volume: peditraceVolume, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | 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: ' | ||
| + | volume: carnitineVolume, | ||
| + | concentration: | ||
| + | contribution: | ||
| + | }); | ||
| + | } | ||
| + | | ||
| + | return { | ||
| + | total: Math.round(totalOsmolarity), | ||
| + | breakdown: osmolarityBreakdown, | ||
| + | details: componentDetails, | ||
| + | isHypertonic: | ||
| + | requiresCVC: | ||
| + | }; | ||
| } | } | ||
| Linea 2262: | Linea 3355: | ||
| } | } | ||
| if (electrolyteAdditions.sodium_acetate > 0) { | if (electrolyteAdditions.sodium_acetate > 0) { | ||
| - | resultHtml += '< | + | resultHtml += '< |
| } | } | ||
| if (electrolyteAdditions.kcl > 0) { | if (electrolyteAdditions.kcl > 0) { | ||
| resultHtml += '< | resultHtml += '< | ||
| } | } | ||
| - | | + | |
| // VITAMINE | // VITAMINE | ||
| if (residualNeeds.vitalipid > 0) { | if (residualNeeds.vitalipid > 0) { | ||
| Linea 2281: | Linea 3374: | ||
| resultHtml += '< | resultHtml += '< | ||
| } | } | ||
| + | | ||
| | | ||
| // CARNITINA | // CARNITINA | ||
| Linea 2297: | Linea 3391: | ||
| document.getElementById(' | document.getElementById(' | ||
| | | ||
| + | // CALCOLO OSMOLARITÀ | ||
| + | const osmolarityData = calculateNPTOsmolarity({ | ||
| + | totalVolume: | ||
| + | waterVolume: | ||
| + | glucose50Volume: | ||
| + | proteinVolume: | ||
| + | lipidVolume: | ||
| + | electrolyteAdditions: | ||
| + | }, currentWeightKg, | ||
| + | |||
| + | // AGGIUNGI SEZIONE OSMOLARITÀ | ||
| + | let osmolarityHtml = '< | ||
| + | if (osmolarityData.isHypertonic) { | ||
| + | osmolarityHtml += '# | ||
| + | } else if (osmolarityData.requiresCVC) { | ||
| + | osmolarityHtml += '# | ||
| + | } else { | ||
| + | osmolarityHtml += '# | ||
| + | } | ||
| + | osmolarityHtml += '">'; | ||
| + | osmolarityHtml += '< | ||
| + | osmolarityHtml += '< | ||
| + | osmolarityHtml += '< | ||
| + | osmolarityHtml += '< | ||
| + | |||
| + | if (osmolarityData.isHypertonic) { | ||
| + | osmolarityHtml += '<p style=" | ||
| + | } else if (osmolarityData.requiresCVC) { | ||
| + | osmolarityHtml += '<p style=" | ||
| + | } else { | ||
| + | osmolarityHtml += '<p style=" | ||
| + | } | ||
| + | |||
| + | osmolarityHtml += '</ | ||
| + | osmolarityHtml += '< | ||
| + | osmolarityHtml += '< | ||
| + | osmolarityData.details.forEach(function(detail) { | ||
| + | if (detail.contribution > 30) { // Mostra contributi > 30 mOsm/L | ||
| + | osmolarityHtml += '<p style=" | ||
| + | } | ||
| + | }); | ||
| + | osmolarityHtml += '</ | ||
| + | osmolarityHtml += '</ | ||
| + | osmolarityHtml += '</ | ||
| + | |||
| + | document.getElementById(' | ||
| + | |||
| // CREAZIONE RICETTA PER PREPARAZIONE | // CREAZIONE RICETTA PER PREPARAZIONE | ||
| const deflectorVolume = parseInt(document.getElementById(' | const deflectorVolume = parseInt(document.getElementById(' | ||
| Linea 2332: | Linea 3473: | ||
| } | } | ||
| if (electrolyteAdditions.sodium_acetate > 0) { | if (electrolyteAdditions.sodium_acetate > 0) { | ||
| - | preparationHtml += '< | + | preparationHtml += '< |
| } | } | ||
| if (electrolyteAdditions.kcl > 0) { | if (electrolyteAdditions.kcl > 0) { | ||
| Linea 2362: | Linea 3503: | ||
| | | ||
| preparationHtml += '< | preparationHtml += '< | ||
| + | preparationHtml += '< | ||
| + | preparationHtml += '< | ||
| + | |||
| + | // Aggiungi avvertenze osmolarità nella tabella di preparazione | ||
| + | if (osmolarityData.isHypertonic) { | ||
| + | preparationHtml += '< | ||
| + | } else if (osmolarityData.requiresCVC) { | ||
| + | preparationHtml += '< | ||
| + | } else { | ||
| + | preparationHtml += '< | ||
| + | } | ||
| preparationHtml += '</ | preparationHtml += '</ | ||
| | | ||
| Linea 2382: | Linea 3534: | ||
| vitaminsVolume: | vitaminsVolume: | ||
| carnitineVolume: | carnitineVolume: | ||
| - | deflectorVolume: | + | deflectorVolume: |
| + | osmolarityData: | ||
| }; | }; | ||
| } | } | ||
| Linea 2428: | Linea 3581: | ||
| '< | '< | ||
| '< | '< | ||
| + | '< | ||
| '< | '< | ||
| '< | '< | ||
| Linea 2451: | Linea 3605: | ||
| '< | '< | ||
| '< | '< | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | function populateNursesConfigTable() { | ||
| + | const tbody = document.getElementById(' | ||
| + | if (!tbody) return; | ||
| + | | ||
| + | tbody.innerHTML = ''; | ||
| + | Object.keys(nursesData).forEach(key => { | ||
| + | const nurse = nursesData[key]; | ||
| + | const row = tbody.insertRow(); | ||
| + | row.innerHTML = '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '</ | ||
| + | '< | ||
| + | '< | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | function populatePharmacistsConfigTable() { | ||
| + | const tbody = document.getElementById(' | ||
| + | if (!tbody) return; | ||
| + | | ||
| + | tbody.innerHTML = ''; | ||
| + | Object.keys(pharmacistsData).forEach(key => { | ||
| + | const pharmacist = pharmacistsData[key]; | ||
| + | const row = tbody.insertRow(); | ||
| + | row.innerHTML = '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '</ | ||
| + | '< | ||
| + | '< | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | function populateTechniciansConfigTable() { | ||
| + | const tbody = document.getElementById(' | ||
| + | if (!tbody) return; | ||
| + | | ||
| + | tbody.innerHTML = ''; | ||
| + | Object.keys(technicianData).forEach(key => { | ||
| + | const technician = technicianData[key]; | ||
| + | const row = tbody.insertRow(); | ||
| + | row.innerHTML = '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '</ | ||
| + | '< | ||
| + | '< | ||
| }); | }); | ||
| } | } | ||
| Linea 2474: | Linea 3688: | ||
| buttonId = ' | buttonId = ' | ||
| buttonText = 'SALVA MODIFICHE MEDICI'; | buttonText = 'SALVA MODIFICHE MEDICI'; | ||
| + | break; | ||
| + | case ' | ||
| + | buttonId = ' | ||
| + | buttonText = 'SALVA MODIFICHE INFERMIERE'; | ||
| + | break; | ||
| + | case ' | ||
| + | buttonId = ' | ||
| + | buttonText = 'SALVA MODIFICHE FARMACISTI'; | ||
| + | break; | ||
| + | case ' | ||
| + | buttonId = ' | ||
| + | buttonText = 'SALVA MODIFICHE TECNICI'; | ||
| break; | break; | ||
| case ' | case ' | ||
| Linea 2487: | Linea 3713: | ||
| } | } | ||
| } | } | ||
| + | |||
| function updateEnteralConfig() { | function updateEnteralConfig() { | ||
| Linea 2541: | Linea 3768: | ||
| parenteralConfig[key].energy = parseFloat(document.getElementById(' | parenteralConfig[key].energy = parseFloat(document.getElementById(' | ||
| parenteralConfig[key].water = parseFloat(document.getElementById(' | parenteralConfig[key].water = parseFloat(document.getElementById(' | ||
| + | parenteralConfig[key].osmolarity = parseFloat(document.getElementById(' | ||
| | | ||
| if (JSON.stringify(oldValues) !== JSON.stringify(parenteralConfig[key])) { | if (JSON.stringify(oldValues) !== JSON.stringify(parenteralConfig[key])) { | ||
| Linea 2618: | Linea 3846: | ||
| button.className = ' | button.className = ' | ||
| button.innerHTML = ' | button.innerHTML = ' | ||
| + | }, 3000); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function updateNursesConfig() { | ||
| + | let changesCount = 0; | ||
| + | | ||
| + | Object.keys(nursesData).forEach(key => { | ||
| + | const oldValues = Object.assign({}, | ||
| + | | ||
| + | const nameEl = document.getElementById(' | ||
| + | if (nameEl) { | ||
| + | const newName = nameEl.value.trim(); | ||
| + | const newSurname = document.getElementById(' | ||
| + | const newTitle = document.getElementById(' | ||
| + | | ||
| + | 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(' | ||
| + | if (button) { | ||
| + | button.className = ' | ||
| + | button.innerHTML = ' | ||
| + | setTimeout(() => { | ||
| + | button.className = ' | ||
| + | button.innerHTML = ' | ||
| + | }, 3000); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function updatePharmacistsConfig() { | ||
| + | let changesCount = 0; | ||
| + | | ||
| + | Object.keys(pharmacistsData).forEach(key => { | ||
| + | const oldValues = Object.assign({}, | ||
| + | | ||
| + | const nameEl = document.getElementById(' | ||
| + | if (nameEl) { | ||
| + | const newName = nameEl.value.trim(); | ||
| + | const newSurname = document.getElementById(' | ||
| + | const newTitle = document.getElementById(' | ||
| + | | ||
| + | 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(' | ||
| + | if (button) { | ||
| + | button.className = ' | ||
| + | button.innerHTML = ' | ||
| + | setTimeout(() => { | ||
| + | button.className = ' | ||
| + | button.innerHTML = ' | ||
| + | }, 3000); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function updateTechniciansConfig() { | ||
| + | let changesCount = 0; | ||
| + | | ||
| + | Object.keys(technicianData).forEach(key => { | ||
| + | const oldValues = Object.assign({}, | ||
| + | | ||
| + | const nameEl = document.getElementById(' | ||
| + | if (nameEl) { | ||
| + | const newName = nameEl.value.trim(); | ||
| + | const newSurname = document.getElementById(' | ||
| + | const newTitle = document.getElementById(' | ||
| + | | ||
| + | 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(' | ||
| + | if (button) { | ||
| + | button.className = ' | ||
| + | button.innerHTML = ' | ||
| + | setTimeout(() => { | ||
| + | button.className = ' | ||
| + | button.innerHTML = ' | ||
| }, 3000); | }, 3000); | ||
| } | } | ||
| Linea 2691: | Linea 4027: | ||
| autoSave: document.getElementById(' | autoSave: document.getElementById(' | ||
| decimalPlaces: | decimalPlaces: | ||
| - | clinicalConfig: | + | clinicalConfig: |
| + | doctorsData: | ||
| + | nursesData: nursesData, | ||
| + | pharmacistsData: | ||
| + | technicianData: | ||
| }; | }; | ||
| | | ||
| Linea 2701: | Linea 4041: | ||
| // Simula salvataggio configurazione | // Simula salvataggio configurazione | ||
| window.savedConfig = config; | window.savedConfig = config; | ||
| - | alert(' | + | alert(' |
| + | ' | ||
| + | '• ' + 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); | ||
| | | ||
| - | | + | // Genera ID prescrizione univoco (una sola volta per sessione) |
| - | | + | if (!window.currentPrescriptionID) { |
| - | | + | window.currentPrescriptionID = generatePreparationID(); |
| + | } | ||
| + | | ||
| + | |||
| + | // Recupera il medico attualmente selezionato | ||
| + | const currentPrescribingDoctor = document.getElementById(' | ||
| + | const doctorName = currentPrescribingDoctor | ||
| + | doctorsData[currentPrescribingDoctor].fullName : | ||
| + | (patientData.prescribingDoctorName || 'Non specificato' | ||
| | | ||
| let html = '< | let html = '< | ||
| | | ||
| - | // INTESTAZIONE MEDICA | + | // INTESTAZIONE MEDICA |
| html += '< | html += '< | ||
| | | ||
| Linea 2736: | Linea 4088: | ||
| html += '< | html += '< | ||
| html += '< | html += '< | ||
| - | html += '< | + | html += '< |
| html += '<p style=" | html += '<p style=" | ||
| html += '</ | html += '</ | ||
| Linea 2749: | Linea 4101: | ||
| // TITOLO DOCUMENTO | // TITOLO DOCUMENTO | ||
| html += '< | html += '< | ||
| - | html += '< | + | html += '< |
| - | html += '<p style=" | + | html += '<h3 style=" |
| html += '</ | html += '</ | ||
| | | ||
| - | // DATI PAZIENTE | + | // INFO PAZIENTE |
| - | html += '< | + | html += '< |
| - | html += '<h3 style=" | + | html += '<div style=" |
| - | html += '<div style=" | + | html += '<table style=" |
| - | html += '<div>'; | + | html += '<tr><td style=" |
| - | html += '<p>< | + | html += '<tr><td style=" |
| - | html += '<p><strong>Data Prescrizione:</strong> ' + (patientData.prescriptionDate || currentDate) + '</p>'; | + | html += '<tr><td style=" |
| - | html += '<p><strong>N° Cartella:</strong> ' + (patientData.medicalRecord || ' | + | html += '< |
| - | html += '</div>'; | + | |
| - | html += '<div>'; | + | |
| - | html += '<p><strong>Data Nascita:</strong> ' + birthDate.toLocaleDateString(' | + | } |
| - | html += '<p><strong> | + | |
| - | html += '<p><strong> | + | |
| - | html += '</div>'; | + | html += '<tr><td style=" |
| - | html += '</div>'; | + | html += '<tr><td style=" |
| + | |||
| + | if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) { | ||
| + | const gestDays = patientData.gestationalDays || 0; | ||
| + | html += '<tr><td style=" | ||
| + | if (patientData.postConceptionalAge && patientData.postConceptionalAge.format) { | ||
| + | html += '< | ||
| + | } | ||
| + | } | ||
| + | html += '< | ||
| + | html += '</table>'; | ||
| html += '</ | html += '</ | ||
| | | ||
| - | // COMPOSIZIONE NPT COMPLETA (TUTTI GLI ELEMENTI DAL TAB 4) | + | // LISTA DEGLI APPORTI PER LA GIORNATA CORRENTE |
| - | html += '<h3 style=" | + | html += '<div style=" |
| - | html += '<table style=" | + | html += '<div style=" |
| - | html += '<thead>< | + | html += '<table style=" |
| - | html += '<th style=" | + | html += '<tr>< |
| - | html += '< | + | |
| - | html += '<th style=" | + | |
| - | html += '<th style=" | + | |
| - | html += '</tr></ | + | |
| | | ||
| - | // ACQUA BIDISTILLATA | + | // Apporti enterali |
| - | if (calc.waterVolume | + | if (enteralData && enteralData.volume |
| - | html += '< | + | const formulaType = document.getElementById(' |
| + | const formulaName = formulaData[formulaType] ? formulaData[formulaType].name : ' | ||
| + | html += '< | ||
| } | } | ||
| | | ||
| - | // GLUCOSIO | + | // Altri liquidi |
| - | if (calc.neededGlucose | + | if (enteralData && enteralData.additionalFluids |
| - | | + | |
| + | let fluidName | ||
| + | switch(fluidType) { | ||
| + | case ' | ||
| + | case ' | ||
| + | case ' | ||
| + | case ' | ||
| + | } | ||
| + | html += '<tr><td style=" | ||
| } | } | ||
| | | ||
| - | // PROTEINE | + | // Se nessun apporto enterale |
| - | html += '< | + | |
| + | | ||
| + | } | ||
| | | ||
| - | // LIPIDI | + | |
| - | html += '<tr><td style=" | + | html += '</div>'; |
| + | |||
| + | // COMPOSIZIONE PARENTERALE (con deflussore) | ||
| + | const deflectorVolume = parseInt(document.getElementById(' | ||
| + | const totalVolumeWithDeflector = calc.totalVolume + deflectorVolume; | ||
| + | const ratio = totalVolumeWithDeflector / calc.totalVolume; | ||
| + | | ||
| + | html += '<div style=" | ||
| + | html += '<div style=" | ||
| + | html += '< | ||
| + | html += '< | ||
| + | |||
| + | // Componenti nell' | ||
| + | html += '< | ||
| + | |||
| + | if (calc.neededGlucose > 0) { | ||
| + | html += '< | ||
| + | } | ||
| | | ||
| - | // ELETTROLITI (SE PRESENTI) | ||
| if (calc.electrolyteAdditions.ca_gluconato > 0) { | if (calc.electrolyteAdditions.ca_gluconato > 0) { | ||
| - | html += '< | + | html += '< |
| - | } | + | |
| - | if (calc.electrolyteAdditions.esafosfina > 0) { | + | |
| - | html += '< | + | |
| - | } | + | |
| - | if (calc.electrolyteAdditions.mg_sulfate > 0) { | + | |
| - | html += '< | + | |
| } | } | ||
| + | | ||
| + | html += '< | ||
| if (calc.electrolyteAdditions.nacl > 0) { | if (calc.electrolyteAdditions.nacl > 0) { | ||
| - | html += '<tr><td style=" | + | html += '< |
| - | } | + | } else if (calc.electrolyteAdditions.sodium_acetate > 0) { |
| - | | + | html += '< |
| - | html += '<tr><td style=" | + | } else { |
| + | html += '</tr>< | ||
| } | } | ||
| + | | ||
| if (calc.electrolyteAdditions.kcl > 0) { | if (calc.electrolyteAdditions.kcl > 0) { | ||
| - | html += '< | + | html += '< |
| } | } | ||
| | | ||
| - | | + | if (calc.electrolyteAdditions.mg_sulfate |
| - | | + | html += '< |
| - | const vitalipidVolume = window.residualNeeds.vitalipid * prescriptionPatientWeightKg; | + | |
| - | html += '< | + | |
| } | } | ||
| - | if (window.residualNeeds.soluvit | + | |
| - | const soluvitVolume | + | html += '< |
| - | html += '<tr><td style=" | + | |
| + | const carnitineVolume | ||
| + | html += '< | ||
| + | } else { | ||
| + | html += '< | ||
| } | } | ||
| + | | ||
| + | html += '< | ||
| + | | ||
| + | if (calc.electrolyteAdditions.esafosfina > 0) { | ||
| + | html += '< | ||
| + | } | ||
| + | | ||
| if (window.residualNeeds.peditrace > 0) { | if (window.residualNeeds.peditrace > 0) { | ||
| const peditraceVolume = window.residualNeeds.peditrace * prescriptionPatientWeightKg; | const peditraceVolume = window.residualNeeds.peditrace * prescriptionPatientWeightKg; | ||
| - | html += '< | + | html += '< |
| + | } else { | ||
| + | html += '< | ||
| } | } | ||
| | | ||
| - | | + | if (window.residualNeeds.soluvit |
| - | | + | const soluvitVolume |
| - | const carnitineVolume | + | html += '< |
| - | html += '< | + | } else { |
| + | html += '< | ||
| + | } | ||
| + | |||
| + | if (window.residualNeeds.vitalipid > 0) { | ||
| + | const vitalipidVolume = window.residualNeeds.vitalipid | ||
| + | html += '< | ||
| + | } else { | ||
| + | html += '< | ||
| } | } | ||
| | | ||
| - | | + | html += '< |
| - | | + | |
| - | html += '</ | + | |
| | | ||
| - | // PARAMETRI CLINICI | + | // TOTALI |
| - | html += '<div style=" | + | html += '<tr style=" |
| - | html += '<h4 style=" | + | html += '<tr><td style=" |
| - | html += '<p><strong> | + | html += '<tr><td style=" |
| - | html += '<p><strong> | + | html += '<tr><td style=" |
| - | html += '<p><strong> | + | html += '</ |
| - | html += '<p><strong>Durata:</strong> 24 ore continue</p>'; | + | |
| html += '</ | html += '</ | ||
| | | ||
| - | // FIRMA | + | // TOTALE ELEMENTI PRO KILO |
| - | html += '< | + | html += '< |
| - | html += '<div style=" | + | html += '< |
| - | html += '<p><strong>Data:</strong> ' + currentDate | + | html += '<table style=" |
| - | html += '<p><strong>Ora:</strong> ' + currentTime | + | |
| - | html += '</div>'; | + | // Calcola valori totali (enterali + parenterali) per kg |
| - | html += '<div style=" | + | const totalLiquidsPerKg = window.residualNeeds.liquids; |
| - | html += '<div style=" | + | const totalProteinPerKg = (enteralData ? enteralData.protein : 0) + window.residualNeeds.protein; |
| - | html += '<p><strong>Medico Prescrittore</strong><br>' + doctorName | + | 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 += '< | ||
| + | html += '<tr><td style=" | ||
| + | html += '< | ||
| + | html += '<tr><td style=" | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '<tr>< | ||
| + | html += '<tr>< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '<tr><td style=" | ||
| + | html += '<tr>< | ||
| + | html += '</ | ||
| html += '</ | html += '</ | ||
| + | | ||
| html += '</ | html += '</ | ||
| | | ||
| Linea 2871: | Linea 4303: | ||
| } | } | ||
| | | ||
| + | const currentDate = new Date().toLocaleDateString(' | ||
| const calc = window.nptCalculation; | const calc = window.nptCalculation; | ||
| + | | ||
| if (!calc) { | if (!calc) { | ||
| alert(' | alert(' | ||
| return; | return; | ||
| } | } | ||
| - | | ||
| - | const currentDate = new Date().toLocaleDateString(' | ||
| - | const currentTime = new Date().toLocaleTimeString(' | ||
| - | 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); | ||
| | | ||
| - | | + | // Recupera il medico attualmente selezionato |
| - | const totalVolumeWithDeflector | + | |
| - | const ratio = totalVolumeWithDeflector / calc.totalVolume; | + | const doctorName |
| + | doctorsData[currentPrescribingDoctor].fullName : | ||
| + | | ||
| | | ||
| - | let html = '< | + | |
| - | html += '<div class=" | + | // Usa lo stesso ID prescrizione della sessione |
| - | html += '<h1>' + clinicalConfig.hospitalName + '</h1>'; | + | if (!window.currentPrescriptionID) { |
| - | html += '< | + | window.currentPrescriptionID = generatePreparationID(); |
| + | } | ||
| + | const worksheetPreparationID = window.currentPrescriptionID; | ||
| + | |||
| + | | ||
| + | |||
| + | // INTESTAZIONE ASST LECCO | ||
| + | html += '<table class=" | ||
| + | html += '<tr>'; | ||
| + | html += '<td class=" | ||
| + | html += '<h2>< | ||
| + | html += '< | ||
| html += '< | html += '< | ||
| + | html += '</ | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '</ | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '</ | ||
| + | html += '</ | ||
| + | html += '</ | ||
| + | | ||
| + | // TITOLO E DATA | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '</ | ||
| html += '</ | html += '</ | ||
| | | ||
| - | html += '<div style=" | + | html += '<h3 style=" |
| | | ||
| - | html += '< | + | |
| - | html += '<h3 style=" | + | html += '< |
| - | html += '<p><strong> | + | |
| - | html += '<p>< | + | html += '<table style=" |
| - | html += '<p><strong>Peso:</strong> ' + patientData.currentWeight | + | html += '< |
| - | html += '<p><strong> | + | html += '<tr><td style=" |
| + | html += '< | ||
| + | if (worksheetPreparationID) { | ||
| + | html += '<tr>< | ||
| + | } | ||
| + | html += '< | ||
| + | html += '<tr><td style=" | ||
| + | html += '< | ||
| + | |||
| + | if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) { | ||
| + | const gestDays = patientData.gestationalDays || 0; | ||
| + | html += '< | ||
| + | if (patientData.postConceptionalAge && patientData.postConceptionalAge.format) { | ||
| + | html += '< | ||
| + | } | ||
| + | } | ||
| + | html += '<tr><td style=" | ||
| + | html += '</ | ||
| html += '</ | html += '</ | ||
| | | ||
| - | html += '< | + | |
| - | html += '<h4 style=" | + | html += '< |
| - | html += '<p>< | + | |
| - | html += '<p>< | + | html += '< |
| - | html += '<p><strong>Durata:</strong> 24 ore continue</p>'; | + | html += '< |
| + | |||
| + | // Ordine esatto come nel PDF del foglio di lavoro | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | | ||
| + | html += '<tr style=" | ||
| + | html += '< | ||
| + | html += '< | ||
| + | |||
| + | html += '< | ||
| + | html += '<tr>< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | | ||
| + | html += '<tr style=" | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '<tr><td style=" | ||
| + | html += '</table>'; | ||
| html += '</ | html += '</ | ||
| | | ||
| - | html += '<table style=" | + | html += '</div>'; |
| - | html += '< | + | |
| - | html += '< | + | |
| - | html += '< | + | |
| - | html += '< | + | |
| - | html += '< | + | |
| - | html += '< | + | |
| - | html += '</ | + | |
| | | ||
| - | | + | |
| + | } | ||
| + | |||
| + | function generateLabel() { | ||
| + | if (!window.residualNeeds || !patientData.currentWeight) { | ||
| + | alert('Prima completare tutti i calcoli precedenti' | ||
| + | return; | ||
| + | } | ||
| | | ||
| - | | + | |
| - | html += '< | + | const currentTime |
| + | const calc = window.nptCalculation; | ||
| + | |||
| + | if (!calc) { | ||
| + | alert('Prima calcolare la NPT nel TAB 4'); | ||
| + | return; | ||
| } | } | ||
| | | ||
| - | | + | |
| + | birthDate.setDate(birthDate.getDate() - patientData.daysOfLife); | ||
| | | ||
| - | | + | // Recupera il medico attualmente selezionato |
| + | const currentPrescribingDoctor | ||
| + | const doctorName | ||
| + | doctorsData[currentPrescribingDoctor].fullName | ||
| + | (patientData.prescribingDoctorName || 'Medico non specificato' | ||
| | | ||
| - | | + | // Usa lo stesso ID prescrizione della sessione |
| - | | + | if (!window.currentPrescriptionID) { |
| + | window.currentPrescriptionID | ||
| + | | ||
| + | const labelPreparationID | ||
| | | ||
| - | html += '< | + | |
| - | html += '<h4 style=" | + | |
| - | html += '< | + | // INTESTAZIONE COMPATTA PER ETICHETTA |
| - | html += '< | + | |
| - | html += '<li>Seguire rigorosamente l\'ordine di aggiunta</ | + | html += '<h1 style=" |
| - | html += '< | + | html += '<h2 style=" |
| - | html += '<li> | + | html += '<h3 style=" |
| - | html += '</ul>'; | + | |
| html += '</ | html += '</ | ||
| | | ||
| - | html += '< | + | |
| - | html += '<div style=" | + | // SEZIONE IDENTIFICAZIONE PAZIENTE - GRANDE E VISIBILE |
| - | html += '<div style=" | + | |
| - | html += '<p><strong>Preparato da</strong><br>Farmacista</p>'; | + | html += '< |
| + | |||
| + | // CODICE A BARRE per cartella clinica | ||
| + | if (patientData.medicalRecord && patientData.medicalRecord.trim() !== '' | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '</ | ||
| + | } | ||
| + | |||
| + | html += '< | ||
| + | html += '<tr>< | ||
| + | |||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | html += '< | ||
| + | html += '<tr><td style=" | ||
| + | |||
| + | if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) { | ||
| + | const gestDays = patientData.gestationalDays || 0; | ||
| + | html += '< | ||
| + | if (patientData.postConceptionalAge && patientData.postConceptionalAge.format) { | ||
| + | html += '< | ||
| + | } | ||
| + | } | ||
| + | |||
| + | html += '< | ||
| + | html += '</table>'; | ||
| html += '</ | html += '</ | ||
| - | html += '< | + | |
| - | html += '<div style=" | + | // SEZIONE PRESCRIZIONE |
| - | html += '<p><strong>Controllato da</strong><br>Infermiere</p>'; | + | |
| + | html += '<h3 style=" | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '<tr><td style=" | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '</table>'; | ||
| html += '</ | html += '</ | ||
| + | | ||
| + | // SEZIONE CONTENUTO SACCA - COMPATTA | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | | ||
| + | // Solo componenti principali per l' | ||
| + | if (calc.neededGlucose > 0) { | ||
| + | html += '< | ||
| + | } | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | | ||
| + | // Elettroliti principali | ||
| + | if (calc.electrolyteAdditions.ca_gluconato > 0) { | ||
| + | html += '< | ||
| + | } | ||
| + | if (calc.electrolyteAdditions.esafosfina > 0) { | ||
| + | html += '< | ||
| + | } | ||
| + | | ||
| + | html += '< | ||
| + | html += '</ | ||
| html += '</ | html += '</ | ||
| + | | ||
| html += '</ | html += '</ | ||
| | | ||
| document.getElementById(' | document.getElementById(' | ||
| + | // Genera il codice a barre se presente la cartella clinica | ||
| + | if (patientData.medicalRecord && patientData.medicalRecord.trim() !== '' | ||
| + | setTimeout(() => { | ||
| + | const canvas = document.getElementById(' | ||
| + | if (canvas && window.SimpleBarcode) { | ||
| + | try { | ||
| + | window.SimpleBarcode.generate(canvas, | ||
| + | width: 2, | ||
| + | height: 60, | ||
| + | margin: 5, | ||
| + | background: "# | ||
| + | lineColor: "# | ||
| + | }); | ||
| + | console.log(' | ||
| + | } catch (error) { | ||
| + | console.error(' | ||
| + | // Fallback: mostra solo il testo | ||
| + | const ctx = canvas.getContext(' | ||
| + | ctx.fillStyle = '# | ||
| + | ctx.font = '14px monospace'; | ||
| + | ctx.textAlign = ' | ||
| + | ctx.fillText(patientData.medicalRecord, | ||
| + | } | ||
| + | } else { | ||
| + | console.error(' | ||
| + | } | ||
| + | }, 100); | ||
| + | } | ||
| + | |||
| + | |||
| + | // Genera il codice a barre se presente la cartella clinica | ||
| + | if (patientData.medicalRecord && patientData.medicalRecord.trim() !== '' | ||
| + | setTimeout(() => { | ||
| + | const canvas = document.getElementById(' | ||
| + | if (canvas && window.JsBarcode) { | ||
| + | try { | ||
| + | window.JsBarcode(canvas, | ||
| + | format: " | ||
| + | displayValue: | ||
| + | width: 2, | ||
| + | height: 60, | ||
| + | margin: 5, | ||
| + | background: "# | ||
| + | lineColor: "# | ||
| + | }); | ||
| + | console.log(' | ||
| + | } catch (error) { | ||
| + | console.error(' | ||
| + | canvas.style.display = ' | ||
| + | } | ||
| + | } | ||
| + | }, 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 === ' | if (type === ' | ||
| - | | + | |
| } else if (type === ' | } else if (type === ' | ||
| - | | + | |
| + | } else if (type === ' | ||
| + | generateLabelPDFContent(doc); | ||
| } | } | ||
| | | ||
| // Salva il PDF | // Salva il PDF | ||
| - | | + | |
| + | switch(type) { | ||
| + | case ' | ||
| + | fileName | ||
| + | break; | ||
| + | case ' | ||
| + | fileName | ||
| + | break; | ||
| + | case ' | ||
| + | fileName | ||
| + | break; | ||
| + | default: | ||
| + | fileName = 'NPT_Document.pdf'; | ||
| + | } | ||
| + | | ||
| doc.save(fileName); | doc.save(fileName); | ||
| } | } | ||
| - | + | // CONTENUTO PDF PRESCRIZIONE MEDICA | |
| - | function | + | function |
| - | // Implementazione semplificata del PDF | + | |
| + | const calc = window.nptCalculation; | ||
| + | const prescriptionPatientWeightKg = patientData.currentWeight | ||
| + | |||
| + | | ||
| + | const currentPrescribingDoctor = document.getElementById(' | ||
| + | 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(' | + | doc.text(' |
| yPos += 20; | yPos += 20; | ||
| | | ||
| Linea 3005: | Linea 4668: | ||
| yPos += 10; | yPos += 10; | ||
| doc.text(' | doc.text(' | ||
| + | yPos += 10; | ||
| + | doc.text(' | ||
| yPos += 20; | yPos += 20; | ||
| | | ||
| - | | + | |
| + | doc.text(' | ||
| + | yPos += 10; | ||
| + | } | ||
| + | |||
| + | // COMPOSIZIONE NPT | ||
| + | doc.text(' | ||
| + | yPos += 15; | ||
| + | | ||
| doc.text(' | doc.text(' | ||
| yPos += 10; | yPos += 10; | ||
| doc.text(' | doc.text(' | ||
| yPos += 10; | yPos += 10; | ||
| - | doc.text(' | + | doc.text(' |
| + | yPos += 10; | ||
| + | |||
| + | if (calc.osmolarityData) { | ||
| + | doc.text(' | ||
| + | yPos += 10; | ||
| + | } | ||
| + | |||
| + | // Componenti principali | ||
| + | yPos += 10; | ||
| + | doc.text(' | ||
| + | yPos += 15; | ||
| + | |||
| + | if (calc.neededGlucose > 0) { | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | } | ||
| + | |||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | 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(' | ||
| + | yPos += 15; | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| } | } | ||
| - | function | + | // CONTENUTO PDF FOGLIO DI LAVORO |
| - | | + | function |
| + | | ||
| + | | ||
| let yPos = 50; | let yPos = 50; | ||
| | | ||
| doc.setFontSize(12); | doc.setFontSize(12); | ||
| - | doc.text(' | + | doc.text(' |
| yPos += 20; | yPos += 20; | ||
| | | ||
| doc.setFontSize(10); | doc.setFontSize(10); | ||
| - | doc.text(' | + | doc.text(' |
| yPos += 10; | yPos += 10; | ||
| - | doc.text(' | + | doc.text(' |
| + | yPos += 10; | ||
| + | doc.text(' | ||
| + | yPos += 20; | ||
| + | |||
| + | doc.text('PREPARAZIONE NPT:', 20, yPos); | ||
| + | yPos += 15; | ||
| + | |||
| + | const deflectorVolume = parseInt(document.getElementById(' | ||
| + | const ratio = (calc.totalVolume + deflectorVolume) / calc.totalVolume; | ||
| + | |||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 15; | ||
| + | |||
| + | doc.text(' | ||
| + | yPos += 15; | ||
| + | |||
| + | if (calc.neededGlucose > 0) { | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | } | ||
| + | |||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 15; | ||
| + | |||
| + | if (calc.electrolyteAdditions.ca_gluconato > 0) { | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | } | ||
| + | |||
| + | if (calc.electrolyteAdditions.esafosfina > 0) { | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | } | ||
| + | |||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | |||
| + | if (calc.osmolarityData) { | ||
| + | doc.text(' | ||
| + | if (calc.osmolarityData.isHypertonic) { | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | } | ||
| + | } | ||
| } | } | ||
| + | |||
| + | // CONTENUTO PDF ETICHETTA SACCA | ||
| + | function generateLabelPDFContent(doc) { | ||
| + | const currentDate = new Date().toLocaleDateString(' | ||
| + | const currentTime = new Date().toLocaleTimeString(' | ||
| + | const calc = window.nptCalculation; | ||
| + | | ||
| + | const birthDate = new Date(); | ||
| + | birthDate.setDate(birthDate.getDate() - patientData.daysOfLife); | ||
| + | | ||
| + | // Recupera il medico attualmente selezionato | ||
| + | const currentPrescribingDoctor = document.getElementById(' | ||
| + | const doctorName = currentPrescribingDoctor && doctorsData[currentPrescribingDoctor] ? | ||
| + | doctorsData[currentPrescribingDoctor].fullName : | ||
| + | (patientData.prescribingDoctorName || ' | ||
| + | | ||
| + | if (!window.currentPrescriptionID) { | ||
| + | window.currentPrescriptionID = generatePreparationID(); | ||
| + | } | ||
| + | const labelPreparationID = window.currentPrescriptionID; | ||
| + | | ||
| + | let yPos = 50; | ||
| + | | ||
| + | doc.setFontSize(14); | ||
| + | doc.setFont(undefined, | ||
| + | doc.text(' | ||
| + | yPos += 20; | ||
| + | | ||
| + | // IDENTIFICAZIONE PAZIENTE | ||
| + | doc.setFontSize(12); | ||
| + | doc.setFont(undefined, | ||
| + | doc.text(' | ||
| + | yPos += 15; | ||
| + | | ||
| + | doc.setFontSize(10); | ||
| + | doc.setFont(undefined, | ||
| + | doc.text(' | ||
| + | yPos += 10; | ||
| + | | ||
| + | if (labelPreparationID) { | ||
| + | doc.text(' | ||
| + | yPos += 10; | ||
| + | } | ||
| + | | ||
| + | doc.text(' | ||
| + | yPos += 10; | ||
| + | doc.text(' | ||
| + | yPos += 10; | ||
| + | | ||
| + | if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) { | ||
| + | const gestDays = patientData.gestationalDays || 0; | ||
| + | doc.text(' | ||
| + | yPos += 10; | ||
| + | if (patientData.postConceptionalAge && patientData.postConceptionalAge.format) { | ||
| + | doc.text(' | ||
| + | yPos += 10; | ||
| + | } | ||
| + | } | ||
| + | | ||
| + | doc.text(' | ||
| + | yPos += 20; | ||
| + | | ||
| + | // DATI PRESCRIZIONE | ||
| + | doc.setFontSize(12); | ||
| + | doc.setFont(undefined, | ||
| + | doc.text(' | ||
| + | yPos += 15; | ||
| + | | ||
| + | doc.setFontSize(10); | ||
| + | doc.setFont(undefined, | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 20; | ||
| + | | ||
| + | // CONTENUTO SACCA | ||
| + | doc.setFontSize(12); | ||
| + | doc.setFont(undefined, | ||
| + | doc.text(' | ||
| + | yPos += 15; | ||
| + | | ||
| + | doc.setFontSize(10); | ||
| + | doc.setFont(undefined, | ||
| + | | ||
| + | if (calc.neededGlucose > 0) { | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | } | ||
| + | | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 8; | ||
| + | doc.text(' | ||
| + | yPos += 15; | ||
| + | | ||
| + | doc.setFont(undefined, | ||
| + | doc.text(' | ||
| + | yPos += 10; | ||
| + | doc.text(' | ||
| + | | ||
| + | // Osmolarità se disponibile | ||
| + | if (calc.osmolarityData) { | ||
| + | yPos += 15; | ||
| + | doc.setFontSize(11); | ||
| + | doc.text(' | ||
| + | | ||
| + | if (calc.osmolarityData.isHypertonic) { | ||
| + | yPos += 10; | ||
| + | doc.setTextColor(255, | ||
| + | doc.text(' | ||
| + | doc.setTextColor(0, | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| // FUNZIONI PLACEHOLDER | // FUNZIONI PLACEHOLDER | ||
| Linea 3041: | Linea 4928: | ||
| alert(' | alert(' | ||
| } | } | ||
| + | |||
| function showAddDoctorForm() { | function showAddDoctorForm() { | ||
| - | | + | |
| + | if (!name || name.trim() === '' | ||
| + | |||
| + | const surname = prompt(' | ||
| + | if (!surname || surname.trim() === '' | ||
| + | |||
| + | const title = prompt(' | ||
| + | if (!title || title.trim() === '' | ||
| + | |||
| + | const key = ' | ||
| + | const fullName = title.trim() + ' ' + name.trim() + ' ' + surname.trim(); | ||
| + | |||
| + | doctorsData[key] = { | ||
| + | name: name.trim(), | ||
| + | surname: surname.trim(), | ||
| + | title: title.trim(), | ||
| + | fullName: fullName | ||
| + | }; | ||
| + | |||
| + | populateDoctorsConfigTable(); | ||
| + | updateDoctorsDropdown(); | ||
| + | alert(' | ||
| } | } | ||
| + | |||
| + | function showAddNurseForm() { | ||
| + | const name = prompt(' | ||
| + | if (!name || name.trim() === '' | ||
| + | | ||
| + | const surname = prompt(' | ||
| + | if (!surname || surname.trim() === '' | ||
| + | | ||
| + | const title = prompt(' | ||
| + | if (!title || title.trim() === '' | ||
| + | | ||
| + | const key = ' | ||
| + | const fullName = title.trim() + ' ' + name.trim() + ' ' + surname.trim(); | ||
| + | | ||
| + | nursesData[key] = { | ||
| + | name: name.trim(), | ||
| + | surname: surname.trim(), | ||
| + | title: title.trim(), | ||
| + | fullName: fullName | ||
| + | }; | ||
| + | | ||
| + | populateNursesConfigTable(); | ||
| + | alert(' | ||
| + | } | ||
| + | |||
| + | function showAddPharmacistForm() { | ||
| + | const name = prompt(' | ||
| + | if (!name || name.trim() === '' | ||
| + | | ||
| + | const surname = prompt(' | ||
| + | if (!surname || surname.trim() === '' | ||
| + | | ||
| + | const title = prompt(' | ||
| + | if (!title || title.trim() === '' | ||
| + | | ||
| + | const key = ' | ||
| + | const fullName = title.trim() + ' ' + name.trim() + ' ' + surname.trim(); | ||
| + | | ||
| + | pharmacistsData[key] = { | ||
| + | name: name.trim(), | ||
| + | surname: surname.trim(), | ||
| + | title: title.trim(), | ||
| + | fullName: fullName | ||
| + | }; | ||
| + | | ||
| + | populatePharmacistsConfigTable(); | ||
| + | alert(' | ||
| + | } | ||
| + | |||
| + | function showAddTechnicianForm() { | ||
| + | const name = prompt(' | ||
| + | if (!name || name.trim() === '' | ||
| + | | ||
| + | const surname = prompt(' | ||
| + | if (!surname || surname.trim() === '' | ||
| + | | ||
| + | const title = prompt(' | ||
| + | if (!title || title.trim() === '' | ||
| + | | ||
| + | const key = ' | ||
| + | const fullName = title.trim() + ' ' + name.trim() + ' ' + surname.trim(); | ||
| + | | ||
| + | technicianData[key] = { | ||
| + | name: name.trim(), | ||
| + | surname: surname.trim(), | ||
| + | title: title.trim(), | ||
| + | fullName: fullName | ||
| + | }; | ||
| + | | ||
| + | populateTechniciansConfigTable(); | ||
| + | alert(' | ||
| + | } | ||
| + | |||
| function removeEnteralFormula(key) { | function removeEnteralFormula(key) { | ||
| Linea 3065: | Linea 5047: | ||
| function removeDoctor(key) { | function removeDoctor(key) { | ||
| - | if (confirm(' | + | if (confirm(' |
| - | alert(' | + | delete doctorsData[key]; |
| + | populateDoctorsConfigTable(); | ||
| + | updateDoctorsDropdown(); | ||
| + | alert(' | ||
| } | } | ||
| + | } | ||
| + | |||
| + | function removeNurse(key) { | ||
| + | if (confirm(' | ||
| + | delete nursesData[key]; | ||
| + | populateNursesConfigTable(); | ||
| + | alert(' | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function removePharmacist(key) { | ||
| + | if (confirm(' | ||
| + | delete pharmacistsData[key]; | ||
| + | populatePharmacistsConfigTable(); | ||
| + | alert(' | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function removeTechnician(key) { | ||
| + | if (confirm(' | ||
| + | delete technicianData[key]; | ||
| + | populateTechniciansConfigTable(); | ||
| + | alert(' | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // FUNZIONI VALIDAZIONE E ARCHIVIAZIONE PREPARAZIONE | ||
| + | function updatePreparationStaffDropdowns() { | ||
| + | console.log(' | ||
| + | | ||
| + | // Farmacisti | ||
| + | const pharmacistSelect = document.getElementById(' | ||
| + | if (pharmacistSelect) { | ||
| + | pharmacistSelect.innerHTML = '< | ||
| + | Object.keys(pharmacistsData).forEach(key => { | ||
| + | const option = document.createElement(' | ||
| + | option.value = key; | ||
| + | option.textContent = pharmacistsData[key].fullName; | ||
| + | pharmacistSelect.appendChild(option); | ||
| + | }); | ||
| + | console.log(' | ||
| + | } | ||
| + | | ||
| + | // Tecnici (per entrambe le dropdown) | ||
| + | [' | ||
| + | const select = document.getElementById(selectId); | ||
| + | if (select) { | ||
| + | select.innerHTML = '< | ||
| + | Object.keys(technicianData).forEach(key => { | ||
| + | const option = document.createElement(' | ||
| + | option.value = key; | ||
| + | option.textContent = technicianData[key].fullName; | ||
| + | select.appendChild(option); | ||
| + | }); | ||
| + | } | ||
| + | }); | ||
| + | console.log(' | ||
| + | } | ||
| + | |||
| + | // ===================================================== | ||
| + | // SISTEMA VALIDAZIONE E PREPARAZIONE IN DUE FASI | ||
| + | // ===================================================== | ||
| + | |||
| + | // FASE 1: Validazione Farmacista | ||
| + | function validatePrescription() { | ||
| + | const pharmacist = document.getElementById(' | ||
| + | | ||
| + | if (!pharmacist) { | ||
| + | alert(' | ||
| + | return; | ||
| + | } | ||
| + | | ||
| + | if (!window.residualNeeds || !window.nptCalculation || !patientData.currentWeight) { | ||
| + | alert(' | ||
| + | return; | ||
| + | } | ||
| + | | ||
| + | // Validazione completata | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Mostra status validazione | ||
| + | const pharmacistName = pharmacistsData[pharmacist].fullName; | ||
| + | const validationHtml = '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '</ | ||
| + | | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Abilita fase 2 - Allestimento | ||
| + | enablePreparationPhase(); | ||
| + | | ||
| + | alert(' | ||
| + | } | ||
| + | |||
| + | // Abilita la fase di allestimento tecnici | ||
| + | function enablePreparationPhase() { | ||
| + | const tech1Select = document.getElementById(' | ||
| + | const tech2Select = document.getElementById(' | ||
| + | | ||
| + | // Abilita le dropdown tecnici | ||
| + | tech1Select.disabled = false; | ||
| + | tech2Select.disabled = false; | ||
| + | | ||
| + | // Popola le dropdown tecnici | ||
| + | [tech1Select, | ||
| + | select.innerHTML = '< | ||
| + | Object.keys(technicianData).forEach(key => { | ||
| + | const option = document.createElement(' | ||
| + | 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(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Event listeners per controllare quando entrambi i tecnici sono selezionati | ||
| + | [tech1Select, | ||
| + | select.addEventListener(' | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | // Controlla se entrambi i tecnici sono selezionati | ||
| + | function checkTechniciansSelection() { | ||
| + | const tech1 = document.getElementById(' | ||
| + | const tech2 = document.getElementById(' | ||
| + | const confirmBtn = document.getElementById(' | ||
| + | | ||
| + | if (tech1 && tech2 && tech1 !== tech2) { | ||
| + | confirmBtn.className = ' | ||
| + | confirmBtn.innerHTML = '🧪 CONFERMA ALLESTIMENTO'; | ||
| + | } else if (tech1 === tech2 && tech1 !== '' | ||
| + | confirmBtn.className = ' | ||
| + | confirmBtn.innerHTML = ' | ||
| + | } else { | ||
| + | confirmBtn.className = ' | ||
| + | confirmBtn.innerHTML = '🧪 CONFERMA ALLESTIMENTO (seleziona tecnici)'; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // FASE 2: Conferma Allestimento | ||
| + | function confirmPreparation() { | ||
| + | const tech1 = document.getElementById(' | ||
| + | const tech2 = document.getElementById(' | ||
| + | | ||
| + | if (!tech1 || !tech2) { | ||
| + | alert(' | ||
| + | return; | ||
| + | } | ||
| + | | ||
| + | if (tech1 === tech2) { | ||
| + | alert(' | ||
| + | return; | ||
| + | } | ||
| + | | ||
| + | // Allestimento confermato | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Mostra status preparazione | ||
| + | const tech1Name = technicianData[tech1].fullName; | ||
| + | const tech2Name = technicianData[tech2].fullName; | ||
| + | const preparationHtml = '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '</ | ||
| + | | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Abilita download JSON | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | |||
| + | // Abilita pulsante blocco prescrizione | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | |||
| + | // Genera e salva l'ID preparazione per il sistema di blocco | ||
| + | if (!window.currentPrescriptionID) { | ||
| + | window.currentPrescriptionID = generatePreparationID(); | ||
| + | } | ||
| + | window.lastPreparationID = window.currentPrescriptionID; | ||
| + | |||
| + | console.log(' | ||
| + | |||
| + | |||
| + | |||
| + | alert(' | ||
| + | } | ||
| + | |||
| + | // ===================================================== | ||
| + | // 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' | ||
| + | ' | ||
| + | '• 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(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | |||
| + | // 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(' | ||
| + | '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(' | ||
| + | const preparationID = window.lastPreparationID || window.currentPrescriptionID || ' | ||
| + | const bannerHtml = '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '< | ||
| + | '</ | ||
| + | | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | } | ||
| + | |||
| + | // Disabilita tutti gli input quando prescrizione è bloccata | ||
| + | function disableAllInputs() { | ||
| + | // Disabilita TAB 2-4, mantieni TAB 1 accessibile per consultazione | ||
| + | const tabButtons = document.querySelectorAll(' | ||
| + | tabButtons.forEach((tab, | ||
| + | if (index > 0 && index < 4) { // Solo TAB 2-4, NON TAB 1 (index 0) | ||
| + | tab.style.opacity = ' | ||
| + | tab.style.pointerEvents = ' | ||
| + | tab.style.cursor = ' | ||
| + | } | ||
| + | }); | ||
| + | | ||
| + | // Disabilita input solo nei TAB 2-4, mantieni TAB 1 consultabile | ||
| + | const inputElements = document.querySelectorAll('# | ||
| + | '# | ||
| + | '# | ||
| + | |||
| + | inputElements.forEach(element => { | ||
| + | element.disabled = true; | ||
| + | element.style.opacity = ' | ||
| + | }); | ||
| + | |||
| + | // TAB 1: disabilita solo i pulsanti di modifica, mantieni visibili i dati | ||
| + | const tab1Buttons = document.querySelectorAll('# | ||
| + | tab1Buttons.forEach(button => { | ||
| + | button.disabled = true; | ||
| + | button.style.opacity = ' | ||
| + | }); | ||
| + | | ||
| + | // Mostra overlay sui TAB bloccati | ||
| + | addLockedOverlay(); | ||
| + | } | ||
| + | |||
| + | // Aggiunge overlay visivo sui TAB bloccati | ||
| + | function addLockedOverlay() { | ||
| + | const lockedTabs = [' | ||
| + | lockedTabs.forEach(tabId => { | ||
| + | const tabElement = document.getElementById(tabId); | ||
| + | if (tabElement && !tabElement.querySelector(' | ||
| + | const overlay = document.createElement(' | ||
| + | overlay.className = ' | ||
| + | overlay.style.cssText = ` | ||
| + | position: absolute; | ||
| + | top: 0; | ||
| + | left: 0; | ||
| + | width: 100%; | ||
| + | height: 100%; | ||
| + | background-color: | ||
| + | z-index: 1000; | ||
| + | display: flex; | ||
| + | align-items: | ||
| + | justify-content: | ||
| + | font-size: 24px; | ||
| + | font-weight: | ||
| + | color: #e74c3c; | ||
| + | pointer-events: | ||
| + | `; | ||
| + | overlay.innerHTML = '🔒 PRESCRIZIONE BLOCCATA'; | ||
| + | | ||
| + | tabElement.style.position = ' | ||
| + | tabElement.appendChild(overlay); | ||
| + | } | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | // Funzione per iniziare nuova prescrizione | ||
| + | function startNewPrescription() { | ||
| + | const confirmed = confirm( | ||
| + | '📋 NUOVA PRESCRIZIONE NPT\n\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' | ||
| + | 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(' | ||
| + | | ||
| + | // Vai al TAB 1 | ||
| + | showTab(' | ||
| + | | ||
| + | // Imposta nuova data | ||
| + | const today = new Date().toISOString().split(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | alert(' | ||
| + | } | ||
| + | |||
| + | // Funzioni di supporto per reset completo | ||
| + | function enableAllInputs() { | ||
| + | // Riabilita tutti i TAB | ||
| + | const tabButtons = document.querySelectorAll(' | ||
| + | tabButtons.forEach(tab => { | ||
| + | tab.style.opacity = ' | ||
| + | tab.style.pointerEvents = ' | ||
| + | tab.style.cursor = ' | ||
| + | }); | ||
| + | | ||
| + | // Riabilita tutti gli input | ||
| + | const inputElements = document.querySelectorAll('# | ||
| + | '# | ||
| + | '# | ||
| + | '# | ||
| + | | ||
| + | inputElements.forEach(element => { | ||
| + | element.disabled = false; | ||
| + | element.style.opacity = ' | ||
| + | }); | ||
| + | | ||
| + | // Rimuovi overlay bloccati | ||
| + | removeLockedOverlays(); | ||
| + | } | ||
| + | |||
| + | function removeLockedOverlays() { | ||
| + | const overlays = document.querySelectorAll(' | ||
| + | overlays.forEach(overlay => { | ||
| + | overlay.remove(); | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | function resetAllForms() { | ||
| + | // Reset TAB 1 - Dati Paziente | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Reset pulsanti TAB 1 | ||
| + | const phaseBtn = document.getElementById(' | ||
| + | if (phaseBtn) { | ||
| + | phaseBtn.className = ' | ||
| + | phaseBtn.innerHTML = ' | ||
| + | phaseBtn.disabled = false; | ||
| + | } | ||
| + | | ||
| + | // Nascondi risultati fase | ||
| + | const phaseResults = document.getElementById(' | ||
| + | if (phaseResults) { | ||
| + | phaseResults.classList.add(' | ||
| + | } | ||
| + | | ||
| + | // Reset TAB 2 - Nutrizione Enterale | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Reset pulsanti TAB 2 | ||
| + | const enteralBtn = document.getElementById(' | ||
| + | if (enteralBtn) { | ||
| + | enteralBtn.className = ' | ||
| + | enteralBtn.innerHTML = ' | ||
| + | } | ||
| + | | ||
| + | // Nascondi risultati enterali | ||
| + | const enteralResults = document.getElementById(' | ||
| + | if (enteralResults) { | ||
| + | enteralResults.classList.add(' | ||
| + | } | ||
| + | | ||
| + | // Reset TAB 3 - Fabbisogni | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | resetNutritionFields(); | ||
| + | | ||
| + | // Reset pulsanti TAB 3 | ||
| + | const loadBtn = document.getElementById(' | ||
| + | const nutritionBtn = document.getElementById(' | ||
| + | if (loadBtn) { | ||
| + | loadBtn.className = ' | ||
| + | loadBtn.innerHTML = ' | ||
| + | } | ||
| + | if (nutritionBtn) { | ||
| + | nutritionBtn.className = ' | ||
| + | nutritionBtn.innerHTML = ' | ||
| + | } | ||
| + | | ||
| + | // Nascondi risultati nutrizione | ||
| + | const nutritionResults = document.getElementById(' | ||
| + | if (nutritionResults) { | ||
| + | nutritionResults.classList.add(' | ||
| + | } | ||
| + | | ||
| + | // Reset TAB 4 - Parenterale | ||
| + | resetParenteralFields(); | ||
| + | | ||
| + | // Reset TAB 5 - Report | ||
| + | resetReportFields(); | ||
| + | | ||
| + | updateFortifierOptions(); | ||
| + | } | ||
| + | |||
| + | function resetNutritionFields() { | ||
| + | const nutritionFields = [ | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ]; | ||
| + | | ||
| + | nutritionFields.forEach(fieldId => { | ||
| + | const field = document.getElementById(fieldId); | ||
| + | if (field) { | ||
| + | field.value = ' | ||
| + | } | ||
| + | }); | ||
| + | | ||
| + | // Reset unità carboidrati | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Reset tipo sodio | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Nascondi raccomandazione sodio | ||
| + | const sodiumRec = document.getElementById(' | ||
| + | if (sodiumRec) { | ||
| + | sodiumRec.classList.add(' | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function resetParenteralFields() { | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | const parenteralBtn = document.getElementById(' | ||
| + | if (parenteralBtn) { | ||
| + | parenteralBtn.className = ' | ||
| + | parenteralBtn.innerHTML = ' | ||
| + | } | ||
| + | | ||
| + | const parenteralResults = document.getElementById(' | ||
| + | if (parenteralResults) { | ||
| + | parenteralResults.classList.add(' | ||
| + | } | ||
| + | } | ||
| + | |||
| + | function resetReportFields() { | ||
| + | // Reset dropdown personale | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | // Reset pulsanti validazione/ | ||
| + | const validateBtn = document.getElementById(' | ||
| + | const confirmBtn = document.getElementById(' | ||
| + | const downloadBtn = document.getElementById(' | ||
| + | const lockBtn = document.getElementById(' | ||
| + | | ||
| + | if (validateBtn) { | ||
| + | validateBtn.className = ' | ||
| + | validateBtn.innerHTML = '✅ VALIDA PRESCRIZIONE'; | ||
| + | validateBtn.disabled = false; | ||
| + | } | ||
| + | | ||
| + | if (confirmBtn) { | ||
| + | confirmBtn.className = ' | ||
| + | confirmBtn.innerHTML = '🧪 CONFERMA ALLESTIMENTO'; | ||
| + | confirmBtn.disabled = true; | ||
| + | } | ||
| + | | ||
| + | if (downloadBtn) { | ||
| + | downloadBtn.className = ' | ||
| + | downloadBtn.innerHTML = '💾 ARCHIVIA PREPARAZIONE (JSON)'; | ||
| + | downloadBtn.disabled = true; | ||
| + | } | ||
| + | | ||
| + | if (lockBtn) { | ||
| + | lockBtn.className = ' | ||
| + | lockBtn.innerHTML = '🔒 BLOCCA PRESCRIZIONE'; | ||
| + | lockBtn.disabled = true; | ||
| + | lockBtn.style.backgroundColor = '# | ||
| + | } | ||
| + | | ||
| + | // Nascondi status | ||
| + | const validationStatus = document.getElementById(' | ||
| + | const preparationStatus = document.getElementById(' | ||
| + | if (validationStatus) validationStatus.style.display = ' | ||
| + | if (preparationStatus) preparationStatus.style.display = ' | ||
| + | | ||
| + | // Reset area report | ||
| + | document.getElementById(' | ||
| + | } | ||
| + | |||
| + | |||
| + | // SISTEMA DI ARCHIVIAZIONE JSON | ||
| + | function generatePreparationID() { | ||
| + | const medicalRecord = patientData.medicalRecord; | ||
| + | let prescriptionDate = patientData.prescriptionDate; | ||
| + | | ||
| + | if (!medicalRecord || medicalRecord.trim() === '' | ||
| + | return null; | ||
| + | } | ||
| + | | ||
| + | if (!prescriptionDate || prescriptionDate.trim() === '' | ||
| + | // Usa data odierna se non specificata | ||
| + | const today = new Date().toISOString().split(' | ||
| + | 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, | ||
| + | const month = (dateObj.getMonth() + 1).toString().padStart(2, | ||
| + | const year = dateObj.getFullYear().toString(); | ||
| + | const formattedDate = day + month + year; | ||
| + | | ||
| + | // Crea chiave univoca per cartella + data | ||
| + | const counterKey = medicalRecord + ' | ||
| + | | ||
| + | // 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, | ||
| + | const preparationID = medicalRecord + ' | ||
| + | | ||
| + | return preparationID; | ||
| + | } | ||
| + | function createPreparationJSON() { | ||
| + | if (!window.residualNeeds || !window.nptCalculation || !patientData.currentWeight) { | ||
| + | alert(' | ||
| + | return null; | ||
| + | } | ||
| + | | ||
| + | // Genera ID preparazione | ||
| + | const preparationID = generatePreparationID(); | ||
| + | if (!preparationID) { | ||
| + | alert(' | ||
| + | return null; | ||
| + | } | ||
| + | | ||
| + | // Recupera dati personale | ||
| + | const pharmacistKey = document.getElementById(' | ||
| + | const tech1Key = document.getElementById(' | ||
| + | const tech2Key = document.getElementById(' | ||
| + | | ||
| + | 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: | ||
| + | cartellaClinica: | ||
| + | dataPrescrizione: | ||
| + | dataCreazione: | ||
| + | | ||
| + | // DATI PAZIENTE | ||
| + | paziente: { | ||
| + | pesoAttuale: | ||
| + | pesoNascita: | ||
| + | giorniVita: patientData.daysOfLife || 0, | ||
| + | etaGestazionale: | ||
| + | settimane: patientData.gestationalWeeks || null, | ||
| + | giorni: patientData.gestationalDays || null, | ||
| + | formato: patientData.gestationalWeeks && patientData.gestationalWeeks > 0 ? | ||
| + | patientData.gestationalWeeks + ' | ||
| + | } | ||
| + | }, | ||
| + | | ||
| + | // 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: | ||
| + | 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: | ||
| + | }, | ||
| + | | ||
| + | // COMPONENTI DETTAGLIATI | ||
| + | componenti: { | ||
| + | glucosio50: window.nptCalculation.glucose50Volume.toFixed(1), | ||
| + | trophamine: window.nptCalculation.proteinVolume.toFixed(1), | ||
| + | intralipid: window.nptCalculation.lipidVolume.toFixed(1), | ||
| + | acquaBidistillata: | ||
| + | elettroliti: | ||
| + | }, | ||
| + | | ||
| + | // PERSONALE | ||
| + | personale: { | ||
| + | medicoPrescrittore: | ||
| + | farmacistValidatore: | ||
| + | tecnico1: tech1Name, | ||
| + | tecnico2: tech2Name | ||
| + | }, | ||
| + | | ||
| + | // METADATA | ||
| + | sistema: { | ||
| + | versione: "NPT Calculator v3.0 UNIFIED", | ||
| + | dataCalcolo: | ||
| + | } | ||
| + | }; | ||
| + | | ||
| + | return preparationData; | ||
| + | } | ||
| + | |||
| + | function downloadPreparationJSON() { | ||
| + | console.log(' | ||
| + | | ||
| + | const preparationData = createPreparationJSON(); | ||
| + | if (!preparationData) { | ||
| + | return; // Errore già mostrato in createPreparationJSON | ||
| + | } | ||
| + | | ||
| + | try { | ||
| + | // Crea il file JSON | ||
| + | const jsonString = JSON.stringify(preparationData, | ||
| + | const blob = new Blob([jsonString], | ||
| + | | ||
| + | // Nome file: NPT_[ID].json | ||
| + | const filename = `NPT_${preparationData.preparationID}.json`; | ||
| + | | ||
| + | // Download automatico | ||
| + | const url = URL.createObjectURL(blob); | ||
| + | const a = document.createElement(' | ||
| + | a.href = url; | ||
| + | a.download = filename; | ||
| + | document.body.appendChild(a); | ||
| + | a.click(); | ||
| + | document.body.removeChild(a); | ||
| + | URL.revokeObjectURL(url); | ||
| + | | ||
| + | // Feedback successo | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | 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(' | ||
| + | | ||
| + | } catch (error) { | ||
| + | console.error(' | ||
| + | alert(' | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | // ===================================================== | ||
| + | // 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() + ' | ||
| + | document.getElementById(' | ||
| + | } | ||
| + | |||
| + | // Funzione anteprima dati mensili | ||
| + | function previewMonthlyData() { | ||
| + | const fileInput = document.getElementById(' | ||
| + | const files = fileInput.files; | ||
| + | | ||
| + | if (!files || files.length === 0) { | ||
| + | alert(' | ||
| + | return; | ||
| + | } | ||
| + | | ||
| + | // Reset dati precedenti | ||
| + | window.monthlyPreparations = []; | ||
| + | | ||
| + | let processedFiles = 0; | ||
| + | const totalFiles = files.length; | ||
| + | | ||
| + | // Processa tutti i file JSON | ||
| + | Array.from(files).forEach((file, | ||
| + | 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(' | ||
| + | } | ||
| + | | ||
| + | processedFiles++; | ||
| + | | ||
| + | // Quando tutti i file sono processati, mostra l' | ||
| + | if (processedFiles === totalFiles) { | ||
| + | showMonthlyPreview(); | ||
| + | } | ||
| + | | ||
| + | } catch (error) { | ||
| + | console.error(' | ||
| + | processedFiles++; | ||
| + | | ||
| + | if (processedFiles === totalFiles) { | ||
| + | showMonthlyPreview(); | ||
| + | } | ||
| + | } | ||
| + | }; | ||
| + | | ||
| + | reader.readAsText(file); | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | // Funzione di validazione JSON NPT | ||
| + | function validateNPTJson(data) { | ||
| + | return data && | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | // Funzione per mostrare l' | ||
| + | function showMonthlyPreview() { | ||
| + | const statsDiv = document.getElementById(' | ||
| + | const selectedMonth = document.getElementById(' | ||
| + | const monthName = new Date(selectedMonth + ' | ||
| + | year: ' | ||
| + | month: ' | ||
| + | }); | ||
| + | | ||
| + | if (window.monthlyPreparations.length === 0) { | ||
| + | statsDiv.innerHTML = '< | ||
| + | statsDiv.style.display = ' | ||
| + | return; | ||
| + | } | ||
| + | | ||
| + | // Calcola statistiche | ||
| + | const stats = calculateMonthlyStats(window.monthlyPreparations); | ||
| + | | ||
| + | let html = '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '< | ||
| + | html += '</ | ||
| + | | ||
| + | html += '< | ||
| + | html += '< | ||
| + | window.monthlyPreparations.forEach(prep => { | ||
| + | html += '• ' + prep.preparationID + ' (Cartella: ' + prep.cartellaClinica + ' | ||
| + | }); | ||
| + | html += '</ | ||
| + | | ||
| + | statsDiv.innerHTML = html; | ||
| + | statsDiv.style.display = ' | ||
| + | | ||
| + | // Abilita il pulsante Excel | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | } | ||
| + | |||
| + | // Funzione per calcolare statistiche mensili | ||
| + | function calculateMonthlyStats(preparations) { | ||
| + | const uniquePatients = new Set(preparations.map(p => p.cartellaClinica)).size; | ||
| + | const totalWeight = preparations.reduce((sum, | ||
| + | const totalGIR = preparations.reduce((sum, | ||
| + | const totalVolume = preparations.reduce((sum, | ||
| + | | ||
| + | return { | ||
| + | uniquePatients: | ||
| + | averageWeight: | ||
| + | averageGIR: totalGIR / preparations.length, | ||
| + | averageVolume: | ||
| + | }; | ||
| + | } | ||
| + | |||
| + | // Funzione principale per generare Excel mensile | ||
| + | function generateMonthlyExcel() { | ||
| + | if (!window.monthlyPreparations || window.monthlyPreparations.length === 0) { | ||
| + | alert(' | ||
| + | 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, | ||
| + | | ||
| + | // FOGLIO 2: Dettaglio Preparazioni | ||
| + | const detailData = createDetailSheet(window.monthlyPreparations); | ||
| + | const ws_detail = XLSX.utils.aoa_to_sheet(detailData); | ||
| + | XLSX.utils.book_append_sheet(wb, | ||
| + | | ||
| + | // FOGLIO 3: Statistiche Cliniche | ||
| + | const statsData = createStatsSheet(window.monthlyPreparations); | ||
| + | const ws_stats = XLSX.utils.aoa_to_sheet(statsData); | ||
| + | XLSX.utils.book_append_sheet(wb, | ||
| + | | ||
| + | // FOGLIO 4: Componenti NPT | ||
| + | const componentsData = createComponentsSheet(window.monthlyPreparations); | ||
| + | const ws_components = XLSX.utils.aoa_to_sheet(componentsData); | ||
| + | XLSX.utils.book_append_sheet(wb, | ||
| + | | ||
| + | // Genera nome file | ||
| + | const selectedMonth = document.getElementById(' | ||
| + | const monthYear = selectedMonth.replace(' | ||
| + | const fileName = `NPT_Consolidato_${monthYear}.xlsx`; | ||
| + | | ||
| + | // Salva il file | ||
| + | XLSX.writeFile(wb, | ||
| + | | ||
| + | // Feedback successo | ||
| + | document.getElementById(' | ||
| + | document.getElementById(' | ||
| + | | ||
| + | alert(`✅ Excel generato con successo!\n\n` + | ||
| + | `📁 File: ${fileName}\n` + | ||
| + | `📊 Preparazioni: | ||
| + | `📋 Fogli: 4 (Riepilogo, Dettaglio, Statistiche, | ||
| + | | ||
| + | } catch (error) { | ||
| + | console.error(' | ||
| + | alert(' | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Crea foglio riepilogo mensile | ||
| + | function createSummarySheet(preparations) { | ||
| + | const selectedMonth = document.getElementById(' | ||
| + | const monthName = new Date(selectedMonth + ' | ||
| + | year: ' | ||
| + | month: ' | ||
| + | }); | ||
| + | | ||
| + | const stats = calculateMonthlyStats(preparations); | ||
| + | | ||
| + | const data = [ | ||
| + | [`REPORT MENSILE NPT - ${monthName.toUpperCase()}`, | ||
| + | [`Generato il: ${new Date().toLocaleDateString(' | ||
| + | [`Sistema: NPT Calculator v3.0 UNIFIED`, '', | ||
| + | ['', | ||
| + | [' | ||
| + | [' | ||
| + | [' | ||
| + | ['Peso medio pazienti:', | ||
| + | ['GIR medio:', | ||
| + | [' | ||
| + | ['', | ||
| + | [' | ||
| + | ['ELBW (≤1000g):', | ||
| + | ['VLBW (1001-1500g):', | ||
| + | ['LBW (1501-2500g):', | ||
| + | ['NBW (> | ||
| + | ['', | ||
| + | [' | ||
| + | ['0-7 giorni:', | ||
| + | ['8-14 giorni:', | ||
| + | [' | ||
| + | ['> | ||
| + | ]; | ||
| + | | ||
| + | return data; | ||
| + | } | ||
| + | |||
| + | // Crea foglio dettaglio preparazioni | ||
| + | function createDetailSheet(preparations) { | ||
| + | const header = [ | ||
| + | 'ID Preparazione', | ||
| + | 'Peso (g)', ' | ||
| + | ' | ||
| + | ' | ||
| + | ]; | ||
| + | | ||
| + | const data = [header]; | ||
| + | | ||
| + | preparations.forEach(prep => { | ||
| + | const row = [ | ||
| + | prep.preparationID || '', | ||
| + | prep.cartellaClinica || '', | ||
| + | prep.dataPrescrizione || '', | ||
| + | prep.personale? | ||
| + | prep.paziente? | ||
| + | prep.paziente? | ||
| + | prep.npt? | ||
| + | prep.npt? | ||
| + | prep.npt? | ||
| + | prep.npt? | ||
| + | prep.npt? | ||
| + | prep.npt? | ||
| + | prep.personale? | ||
| + | prep.personale? | ||
| + | prep.personale? | ||
| + | ]; | ||
| + | data.push(row); | ||
| + | }); | ||
| + | | ||
| + | return data; | ||
| + | } | ||
| + | |||
| + | // Crea foglio statistiche cliniche | ||
| + | function createStatsSheet(preparations) { | ||
| + | const header = [ | ||
| + | ' | ||
| + | ]; | ||
| + | | ||
| + | const data = [ | ||
| + | [' | ||
| + | ['', | ||
| + | header | ||
| + | ]; | ||
| + | | ||
| + | // Calcola statistiche per ogni parametro clinico | ||
| + | const parameters = [ | ||
| + | { name: 'Peso (g)', values: preparations.map(p => p.paziente.pesoAttuale).filter(v => v > 0) }, | ||
| + | { name: ' | ||
| + | { name: ' | ||
| + | { name: 'GIR (mg/ | ||
| + | { name: ' | ||
| + | { name: ' | ||
| + | { name: ' | ||
| + | { name: ' | ||
| + | ]; | ||
| + | | ||
| + | parameters.forEach(param => { | ||
| + | if (param.values.length > 0) { | ||
| + | const avg = param.values.reduce((a, | ||
| + | const min = Math.min(...param.values); | ||
| + | const max = Math.max(...param.values); | ||
| + | const variance = param.values.reduce((acc, | ||
| + | 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([' | ||
| + | data.push(['', | ||
| + | | ||
| + | const bloodParams = [ | ||
| + | { name: 'BUN (mg/ | ||
| + | { name: ' | ||
| + | { name: ' | ||
| + | { name: ' | ||
| + | ]; | ||
| + | | ||
| + | bloodParams.forEach(param => { | ||
| + | if (param.values.length > 0) { | ||
| + | const avg = param.values.reduce((a, | ||
| + | const min = Math.min(...param.values); | ||
| + | const max = Math.max(...param.values); | ||
| + | const variance = param.values.reduce((acc, | ||
| + | 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', | ||
| + | ' | ||
| + | 'Mg Solfato (ml)', 'NaCl (ml)', 'Na Acetato (ml)', 'KCl (ml)', | ||
| + | ' | ||
| + | ]; | ||
| + | | ||
| + | const data = [ | ||
| + | [' | ||
| + | ['', | ||
| + | header | ||
| + | ]; | ||
| + | | ||
| + | preparations.forEach(prep => { | ||
| + | const comp = prep.componenti || {}; | ||
| + | const row = [ | ||
| + | prep.preparationID || '', | ||
| + | prep.cartellaClinica || '', | ||
| + | comp.glucosio50 || ' | ||
| + | comp.trophamine || ' | ||
| + | comp.intralipid || ' | ||
| + | comp.acquaBidistillata || ' | ||
| + | comp.elettroliti? | ||
| + | comp.elettroliti? | ||
| + | comp.elettroliti? | ||
| + | comp.elettroliti? | ||
| + | comp.elettroliti? | ||
| + | comp.elettroliti? | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ]; | ||
| + | data.push(row); | ||
| + | }); | ||
| + | | ||
| + | // Aggiungi statistiche componenti | ||
| + | data.push(['', | ||
| + | data.push([' | ||
| + | data.push(['', | ||
| + | | ||
| + | // Calcola medie componenti | ||
| + | const avgGlucose = preparations.reduce((sum, | ||
| + | const avgProtein = preparations.reduce((sum, | ||
| + | const avgLipid = preparations.reduce((sum, | ||
| + | const avgWater = preparations.reduce((sum, | ||
| + | | ||
| + | data.push([' | ||
| + | data.push([' | ||
| + | data.push([' | ||
| + | data.push([' | ||
| + | data.push([' | ||
| + | | ||
| + | return data; | ||
| + | } | ||
| + | |||
| + | // ===================================================== | ||
| + | // SISTEMA KNOWLEDGE BASE | ||
| + | // ===================================================== | ||
| + | |||
| + | // Funzione per mostrare sezioni Knowledge Base | ||
| + | function showKnowledgeSection(sectionId) { | ||
| + | // Nascondi tutte le sezioni knowledge | ||
| + | document.querySelectorAll(' | ||
| + | section.classList.remove(' | ||
| + | section.classList.add(' | ||
| + | }); | ||
| + | | ||
| + | // Rimuovi classe active da tutti i tab knowledge | ||
| + | const knowledgeTabs = document.querySelectorAll('# | ||
| + | knowledgeTabs.forEach(tab => { | ||
| + | tab.classList.remove(' | ||
| + | }); | ||
| + | | ||
| + | // Mostra la sezione selezionata | ||
| + | const targetSection = document.getElementById(sectionId); | ||
| + | if (targetSection) { | ||
| + | targetSection.classList.remove(' | ||
| + | targetSection.classList.add(' | ||
| + | } | ||
| + | | ||
| + | // Attiva il tab cliccato | ||
| + | const clickedTab = event.target.closest(' | ||
| + | if (clickedTab) { | ||
| + | clickedTab.classList.add(' | ||
| + | } | ||
| + | | ||
| + | console.log(' | ||
| + | } | ||
| + | |||
| + | // Database delle regole di calcolo (expandibile) | ||
| + | const knowledgeBase = { | ||
| + | calculationRules: | ||
| + | gir: { | ||
| + | name: "GIR (Glucose Infusion Rate)", | ||
| + | formula: " | ||
| + | unit: " | ||
| + | normalRange: | ||
| + | alerts: [ | ||
| + | { condition: "> 12", action: " | ||
| + | { condition: "> 15", action: " | ||
| + | ], | ||
| + | rationale: "Il GIR elevato può causare iperglicemia e richiede monitoraggio glicemico frequente" | ||
| + | }, | ||
| + | osmolarity: { | ||
| + | name: " | ||
| + | formula: " | ||
| + | unit: " | ||
| + | thresholds: [ | ||
| + | { range: "< 600", access: " | ||
| + | { range: " | ||
| + | { range: "> 900", access: "Solo CVC (ipertonica)", | ||
| + | ], | ||
| + | rationale: " | ||
| + | }, | ||
| + | proteinAdjustment: | ||
| + | name: " | ||
| + | rules: [ | ||
| + | { bun: "< 9 mg/ | ||
| + | { bun: "9-14 mg/ | ||
| + | { bun: "> 14 mg/ | ||
| + | ], | ||
| + | monitoring: " | ||
| + | } | ||
| + | }, | ||
| + | | ||
| + | clinicalGuidelines: | ||
| + | ageProtocols: | ||
| + | elbw: { name: "ELBW ≤1000g", | ||
| + | vlbw: { name: "VLBW 1001-1500g", | ||
| + | lbw: { name: "LBW 1501-2500g", | ||
| + | term: { name: "Term > | ||
| + | } | ||
| + | }, | ||
| + | | ||
| + | alerts: { | ||
| + | critical: [], | ||
| + | warning: [], | ||
| + | info: [] | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | // Funzione per ottenere spiegazione di una regola | ||
| + | function getCalculationExplanation(parameter, | ||
| + | const rules = knowledgeBase.calculationRules; | ||
| + | let explanation = ""; | ||
| + | | ||
| + | switch(parameter) { | ||
| + | case ' | ||
| + | if (value > 12) { | ||
| + | explanation = " | ||
| + | } else if (value < 4) { | ||
| + | explanation = " | ||
| + | } else { | ||
| + | explanation = "✅ GIR ottimale: Range di sicurezza per neonati."; | ||
| + | } | ||
| + | break; | ||
| + | | ||
| + | case ' | ||
| + | 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 = " | ||
| + | } | ||
| + | | ||
| + | return explanation; | ||
| + | } | ||
| + | |||
| + | // Funzione per mostrare tooltip informativi | ||
| + | function showKnowledgeTooltip(element, | ||
| + | // Crea tooltip dinamico | ||
| + | const tooltip = document.createElement(' | ||
| + | tooltip.className = ' | ||
| + | tooltip.innerHTML = content; | ||
| + | tooltip.style.cssText = ` | ||
| + | position: absolute; | ||
| + | background-color: | ||
| + | color: white; | ||
| + | padding: 10px; | ||
| + | border-radius: | ||
| + | font-size: 12px; | ||
| + | max-width: 300px; | ||
| + | z-index: 1000; | ||
| + | box-shadow: 0 2px 10px rgba(0, | ||
| + | `; | ||
| + | | ||
| + | document.body.appendChild(tooltip); | ||
| + | | ||
| + | // Posiziona tooltip | ||
| + | const rect = element.getBoundingClientRect(); | ||
| + | tooltip.style.left = rect.left + ' | ||
| + | tooltip.style.top = (rect.bottom + 5) + ' | ||
| + | | ||
| + | // 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(' | document.getElementById(' | ||
| document.getElementById(' | document.getElementById(' | ||
| - | | + | |
| updateFortifierOptions(); | updateFortifierOptions(); | ||
| + | // Inizializza tutte le dropdown e tabelle | ||
| updateDoctorsDropdown(); | updateDoctorsDropdown(); | ||
| + | console.log(' | ||
| + | // Test per verificare che la dropdown sia stata popolata | ||
| + | setTimeout(() => { | ||
| + | const prescribingDoctorSelect = document.getElementById(' | ||
| + | if (prescribingDoctorSelect) { | ||
| + | console.log(' | ||
| + | } | ||
| + | }, 500); | ||
| + | |||
| + | // Inizializza sezione mensile | ||
| + | initializeMonthlySection(); | ||
| console.log(' | console.log(' | ||
| }); | }); | ||