Differenze
Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
Entrambe le parti precedenti la revisioneRevisione precedenteProssima revisione | Revisione precedente | ||
docuneo:programma_npt [2025/08/01 06:02] – neoadmin | docuneo:programma_npt [2025/08/11 15:34] (versione attuale) – neoadmin | ||
---|---|---|---|
Linea 3: | Linea 3: | ||
<meta charset=" | <meta charset=" | ||
<meta name=" | <meta name=" | ||
- | < | + | < |
+ | <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 22: | Linea 131: | ||
h1 { | h1 { | ||
+ | |||
+ | text-align: center; | ||
+ | color: white; | ||
+ | background: linear-gradient(135deg, | ||
+ | border: none; | ||
+ | padding: 20px; | ||
+ | border-radius: | ||
+ | margin-bottom: | ||
+ | text-shadow: | ||
+ | position: relative; | ||
+ | overflow: hidden; | ||
+ | } | ||
+ | |||
+ | h1::before { | ||
+ | content: " | ||
+ | font-size: 30px; | ||
+ | position: absolute; | ||
+ | left: 20px; | ||
+ | top: 50%; | ||
+ | transform: translateY(-50%); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | .version-info { | ||
text-align: center; | text-align: center; | ||
- | | + | |
- | | + | |
- | | + | |
} | } | ||
Linea 210: | Linea 343: | ||
.hidden { | .hidden { | ||
- | display: none !important; | + | display: none; |
} | } | ||
- | | + | /* CSS TAB ORIZZONTALI |
- | display: block !important; | + | |
- | } | + | |
- | + | ||
- | | + | |
.tabs { | .tabs { | ||
display: flex; | display: flex; | ||
Linea 226: | Linea 355: | ||
.tab { | .tab { | ||
- | padding: | + | padding: |
background-color: | background-color: | ||
border: 1px solid #ddd; | border: 1px solid #ddd; | ||
Linea 234: | Linea 363: | ||
transition: all 0.3s ease; | transition: all 0.3s ease; | ||
text-align: center; | text-align: center; | ||
- | min-width: | + | min-width: |
flex: 1; | flex: 1; | ||
- | max-width: | + | max-width: |
+ | 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 311: | Linea 462: | ||
} | } | ||
- | | + | .config-table { |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
font-size: 12px; | font-size: 12px; | ||
- | line-height: | ||
- | max-width: 800px; | ||
- | margin: 0 auto; | ||
- | border: 1px solid #ddd; | ||
} | } | ||
- | .report-header | + | .config-table th, .config-table td { |
- | display: flex; | + | border: |
- | justify-content: | + | padding: |
- | align-items: | + | |
- | border-bottom: 2px solid #333; | + | |
- | padding-bottom: 10px; | + | |
- | | + | |
} | } | ||
- | .report-header-left | + | .config-table th { |
- | | + | |
+ | color: white; | ||
} | } | ||
- | .report-header-right | + | .config-table input { |
- | width: 100px; | + | width: 60px; |
- | height: 60px; | + | |
- | | + | border: 1px solid #ddd; |
- | border: 1px solid #ccc; | + | |
- | | + | |
- | align-items: center; | + | |
- | justify-content: | + | |
- | font-size: 10px; | + | |
- | color: #666; | + | |
} | } | ||
- | .report-title { | + | .component-name { |
- | font-size: 14px; | + | |
font-weight: | font-weight: | ||
- | | + | |
+ | text-align: left !important; | ||
} | } | ||
- | .report-subtitle | + | |
- | | + | |
- | | + | |
- | | + | |
+ | | ||
+ | padding: 20px; | ||
+ | margin: 20px 0; | ||
} | } | ||
- | .report-section | + | .config-advanced h3 { |
- | margin-bottom: | + | color: #0c5460; |
+ | margin-top: 0; | ||
+ | border-bottom: | ||
+ | padding-bottom: | ||
} | } | ||
- | .report-section-title { | + | .monitoring-table { |
- | background-color: | + | |
- | color: white; | + | |
- | padding: 5px 10px; | + | |
- | font-weight: | + | |
- | font-size: 12px; | + | |
- | margin-bottom: | + | |
- | } | + | |
- | + | ||
- | .report-table { | + | |
width: 100%; | width: 100%; | ||
border-collapse: | border-collapse: | ||
- | font-size: | + | |
+ | | ||
} | } | ||
- | .report-table td { | + | .monitoring-table th, .monitoring-table td { |
- | padding: 3px 8px; | + | border: 1px solid #17a2b8; |
- | border-bottom: 1px solid #ddd; | + | padding: 8px; |
- | | + | |
} | } | ||
- | .report-table | + | .monitoring-table |
- | | + | |
- | | + | |
} | } | ||
- | .report-table .value-col | + | .alert-critical |
- | | + | |
+ | color: white; | ||
+ | padding: 15px; | ||
+ | border-radius: | ||
+ | margin: 15px 0; | ||
font-weight: | font-weight: | ||
} | } | ||
- | .composition-table { | + | |
- | | + | |
- | border-collapse: collapse; | + | |
- | | + | border-radius: 10px; |
- | margin-top: | + | |
+ | margin-top: | ||
+ | background-color: | ||
+ | font-family: | ||
+ | line-height: | ||
} | } | ||
- | .composition-table th { | + | .medical-header |
- | background-color: | + | |
- | padding: 5px 8px; | + | |
text-align: center; | text-align: center; | ||
- | | + | |
- | | + | |
+ | margin-bottom: | ||
} | } | ||
- | .composition-table td { | + | .medical-header h1 { |
- | | + | |
- | | + | |
- | | + | |
} | } | ||
- | .composition-table .component-name-col | + | .medical-header h2 { |
- | | + | |
- | | + | color: #34495e; |
+ | | ||
} | } | ||
- | .composition-total { | + | .medical-header p { |
- | | + | |
- | | + | |
+ | | ||
} | } | ||
- | .elements-table { | + | .no-print { |
- | | + | |
- | border-collapse: | + | |
- | font-size: 11px; | + | |
- | margin-top: 0; | + | |
} | } | ||
- | .elements-table td { | + | |
- | | + | |
- | | + | display: none !important; |
+ | | ||
+ | body { | ||
+ | background: white; | ||
+ | | ||
+ | .container { | ||
+ | box-shadow: none; | ||
+ | } | ||
+ | |||
+ | | ||
} | } | ||
- | | + | /* NUOVA INTESTAZIONE MEDICA ASST LECCO */ |
- | width: | + | |
- | } | + | width: |
+ | border-collapse: | ||
+ | border: 2px solid #2c3e50; | ||
+ | margin-bottom: | ||
+ | } | ||
- | | + | .medical-header-table |
- | | + | |
- | | + | |
- | width: 80px; | + | |
- | } | + | } |
- | | + | .medical-header-left { |
- | | + | width: |
- | | + | |
- | font-size: 10px; | + | } |
- | } | + | |
- | | + | .medical-header-center |
- | margin-top: 30px; | + | |
- | | + | text-align: center; |
- | border-top: 1px solid #ddd; | + | background-color: |
- | font-size: 10px; | + | } |
- | color: #666; | + | |
- | text-align: center; | + | .medical-header-right { |
- | } | + | width: 25%; |
+ | text-align: center; | ||
+ | background-color: | ||
+ | } | ||
+ | |||
+ | .medical-header-left h2 { | ||
+ | font-size: 14px; | ||
+ | font-weight: | ||
+ | color: #2c3e50; | ||
+ | | ||
+ | } | ||
+ | |||
+ | .medical-header-left h3 { | ||
+ | font-size: 12px; | ||
+ | | ||
+ | margin: 0 0 5px 0; | ||
+ | } | ||
+ | |||
+ | .medical-header-left p { | ||
+ | font-size: 11px; | ||
+ | color: #7f8c8d; | ||
+ | margin: 0; | ||
+ | } | ||
+ | |||
+ | /* NUOVA INTESTAZIONE MEDICA ASST LECCO */ | ||
+ | .medical-header-table { | ||
+ | width: 100%; | ||
+ | border-collapse: collapse; | ||
+ | border: 2px solid #2c3e50; | ||
+ | margin-bottom: | ||
+ | } | ||
+ | |||
+ | .medical-header-table td { | ||
+ | border: 1px solid #2c3e50; | ||
+ | | ||
+ | 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-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; | ||
+ | | ||
+ | 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 { | ||
+ | | ||
+ | | ||
+ | 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; | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | .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; | ||
+ | } | ||
- | @media print { | ||
- | .npt-report { | ||
- | box-shadow: none; | ||
- | border: none; | ||
- | margin: 0; | ||
- | padding: 15px; | ||
- | } | ||
- | | ||
- | .button { | ||
- | display: none; | ||
- | } | ||
- | | ||
- | .tabs, .tab-content: | ||
- | display: none !important; | ||
- | } | ||
- | } | ||
</ | </ | ||
</ | </ | ||
Linea 484: | Linea 775: | ||
<div class=" | <div class=" | ||
- | <h1>Programma NPT Neonatale v2.0</ | + | <h1>Gestione della Nutrizione del Neonato (GNN v3.0)</h1> |
+ | < | ||
+ | < | ||
+ | </div> | ||
| | ||
- | <!-- TAB ORIZZONTALI --> | + | <!-- TAB ORIZZONTALI |
<div class=" | <div class=" | ||
- | | + | |
- | <span style=" | + | <span style=" |
- | </ | + | </ |
- | <div class=" | + | |
- | <span style=" | + | <!-- SEZIONE CONFIGURAZIONE COMPONENTI (DA VERSIONE 17) --> |
- | </ | + | |
- | <div class=" | + | <span style=" |
- | <span style=" | + | </ |
- | </ | + | <div class=" |
- | <div class=" | + | <span style=" |
- | <span style=" | + | </ |
- | </ | + | <div class=" |
- | <div class=" | + | <span style=" |
- | <span style=" | + | </ |
- | </ | + | <div class=" |
+ | <span style=" | ||
+ | </ | ||
+ | <div class=" | ||
+ | | ||
+ | </ | ||
+ | <div class=" | ||
+ | <span style=" | ||
+ | | ||
</ | </ | ||
- | <!-- TAB 1: DATI PAZIENTE --> | + | <!-- TAB 1: DATI PAZIENTE |
<div id=" | <div id=" | ||
- | | + | <div class=" |
- | < | + | < |
- | < | + | < |
- | </ | + | |
+ | </ | ||
<div class=" | <div class=" | ||
< | < | ||
Linea 522: | Linea 825: | ||
<label for=" | <label for=" | ||
<select id=" | <select id=" | ||
- | <option value=""> | + | <!-- Popolato dinamicamente --> |
- | <option value=" | + | |
- | <option value=" | + | |
- | <option value=" | + | |
- | <option value=" | + | |
- | <option value=" | + | |
- | <option value=" | + | |
</ | </ | ||
</ | </ | ||
Linea 557: | Linea 854: | ||
<div class=" | <div class=" | ||
<label for=" | <label for=" | ||
- | <input type=" | + | <input type=" |
</ | </ | ||
<div class=" | <div class=" | ||
Linea 563: | 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 610: | Linea 931: | ||
</ | </ | ||
- | <!-- TAB 2: NUTRIZIONE ENTERALE --> | + | <!-- TAB 2: NUTRIZIONE ENTERALE |
<div id=" | <div id=" | ||
<div class=" | <div class=" | ||
Linea 709: | Linea 1030: | ||
</ | </ | ||
- | <!-- TAB 3: CALCOLO FABBISOGNI --> | + | <!-- TAB 3: CALCOLO FABBISOGNI |
<div id=" | <div id=" | ||
<div class=" | <div class=" | ||
Linea 839: | Linea 1160: | ||
</ | </ | ||
- | <!-- TAB 4: NUTRIZIONE PARENTERALE --> | + | <!-- TAB 4: NUTRIZIONE PARENTERALE |
<div id=" | <div id=" | ||
<div class=" | <div class=" | ||
Linea 881: | Linea 1202: | ||
<div id=" | <div id=" | ||
| | ||
- | | + | |
- | <h3 style=" | + | |
- | <p style=" | + | <button class=" |
- | <div style=" | + | <button class=" |
- | <button id="generateWorkReportBtn" class=" | + | <button class=" |
- | < | + | </ |
- | <button id="printReportBtn" class=" | + | </ |
- | <button id="savePdfBtn" class=" | + | </ |
- | <button id="saveHtmlBtn" class=" | + | |
- | </div> | + | |
+ | <!-- TAB 5: REPORT FINALE (SPOSTATO DA TAB 6) --> | ||
+ | <div id="report" class=" | ||
+ | <div class=" | ||
+ | < | ||
+ | < | ||
+ | | ||
+ | |||
+ | <!-- Banner stato prescrizione --> | ||
+ | | ||
+ | <!-- Popolato dinamicamente --> | ||
+ | </ | ||
+ | <div class="section no-print"> | ||
+ | < | ||
+ | < | ||
+ | <button class="button" | ||
+ | < | ||
+ | < | ||
+ | <!-- 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="form-row"> | ||
+ | < | ||
+ | <div class="input-group"> | ||
+ | <label for=" | ||
+ | <select id=" | ||
+ | <option value=""> | ||
+ | <!-- Popolato dinamicamente da pharmacistsData --> | ||
+ | </ | ||
+ | </ | ||
+ | <div class=" | ||
+ | < | ||
+ | </div> | ||
+ | </ | ||
+ | |||
+ | <div class="form-col"> | ||
+ | < | ||
+ | 📝 VALIDA PRESCRIZIONE | ||
+ | </ | ||
+ | <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="form-row"> | ||
+ | < | ||
+ | <div class="input-group"> | ||
+ | <label for=" | ||
+ | <select id=" | ||
+ | <option value=""> | ||
+ | <!-- Popolato dinamicamente da technicianData --> | ||
+ | </select> | ||
</ | </ | ||
| | ||
- | <div id="nptWorkReport" class=" | + | < |
- | <div id="nptFinalReport" class=" | + | <label for=" |
+ | < | ||
+ | <option value=""> | ||
+ | <!-- Popolato dinamicamente da technicianData --> | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | </div> | ||
+ | </ | ||
+ | |||
+ | <div class=" | ||
+ | <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=" | ||
+ | < | ||
+ | <tr> | ||
+ | <th style=" | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | </ | ||
+ | < | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <!-- 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. | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
</ | </ | ||
- | <!-- TAB 5: CONFIGURAZIONE --> | + | <!-- TAB 6: CONFIGURAZIONE |
<div id=" | <div id=" | ||
<div class=" | <div class=" | ||
- | < | + | < |
- | < | + | < |
</ | </ | ||
- | | ||
<div class=" | <div class=" | ||
< | < | ||
Linea 911: | Linea 1545: | ||
<div class=" | <div class=" | ||
<label for=" | <label for=" | ||
- | <input type=" | + | <input type=" |
</ | </ | ||
<div class=" | <div class=" | ||
Linea 922: | Linea 1556: | ||
<div class=" | <div class=" | ||
<button id=" | <button id=" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | | ||
+ | <div class=" | ||
+ | < | ||
+ | <div style=" | ||
+ | <table class=" | ||
+ | < | ||
+ | <tr> | ||
+ | <th style=" | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | </ | ||
+ | <tbody id=" | ||
+ | <!-- Popolato dinamicamente --> | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | <div class=" | ||
+ | <div class=" | ||
+ | <button id=" | ||
+ | </ | ||
+ | <div class=" | ||
+ | <button class=" | ||
</ | </ | ||
</ | </ | ||
Linea 927: | Linea 1595: | ||
<div class=" | <div class=" | ||
- | <h2>Informazioni Sistema</ | + | <h2>Fortificanti in Polvere (Valori per 100g)</ |
- | < | + | < |
- | <strong>📊 NPT Calculator v2.0 - Stato Sistema</strong>< | + | <table class=" |
- | <strong>• Database Formule:</strong> 9 formule enterali configurate< | + | < |
- | <strong>• Database Componenti:</strong> 8 componenti parenterali configurati< | + | < |
- | <strong>• Medici Prescrittori: | + | <th style=" |
- | <strong>• Algoritmi:</strong> Calcoli BUN, fasi nutrizionali, | + | < |
- | | + | <th>Carboidrati< |
- | <strong>• Ultimo Aggiornamento:</strong> Agosto 2025 | + | < |
+ | <th>Sodio< | ||
+ | <th>Potassio<br> | ||
+ | <th>Calcio< | ||
+ | < | ||
+ | <th>Magnesio< | ||
+ | < | ||
+ | <th style=" | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | <tbody id=" | ||
+ | < | ||
+ | <td class=" | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | <td style=" | ||
+ | <td><button class=" | ||
+ | </ | ||
+ | </ | ||
+ | | ||
</ | </ | ||
+ | <div class=" | ||
+ | <div class=" | ||
+ | <button id=" | ||
+ | </ | ||
+ | <div class=" | ||
+ | <button class=" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div class=" | ||
+ | < | ||
+ | <div style=" | ||
+ | <table class=" | ||
+ | < | ||
+ | <tr> | ||
+ | <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 medici prescrittori. Le modifiche si applicano automaticamente alla dropdown del TAB 1. | ||
+ | </ | ||
+ | <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 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=" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <!-- SEZIONE CONFIGURAZIONE CLINICA AVANZATA (NOVITÀ) --> | ||
+ | <div class=" | ||
+ | < | ||
+ | | ||
+ | <div class=" | ||
+ | < | ||
+ | <div class=" | ||
+ | <div class=" | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <span style=" | ||
+ | </ | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <span style=" | ||
+ | </ | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <span style=" | ||
+ | </ | ||
+ | </ | ||
+ | <div class=" | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <span style=" | ||
+ | </ | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <span style=" | ||
+ | </ | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <span style=" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | <button class=" | ||
+ | </ | ||
+ | |||
+ | <div class=" | ||
+ | < | ||
+ | <table class=" | ||
+ | < | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | </ | ||
+ | < | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | <tr> | ||
+ | < | ||
+ | <td>2 volte/ | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | <tr> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </tr> | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div class=" | ||
+ | < | ||
+ | <div class=" | ||
+ | < | ||
+ | • Glicemia > 250 mg/dL o < 40 mg/ | ||
+ | • Trigliceridi > 400 mg/ | ||
+ | • AST/ALT > 3x valore normale< | ||
+ | • Segni di sepsi cateter-correlata< | ||
+ | • Edema importante con bilancio positivo > 20 ml/kg/die | ||
+ | </ | ||
+ | | ||
+ | <div class=" | ||
+ | < | ||
+ | • GIR > 12 mg/kg/min → Ridurre glucosio< | ||
+ | • BUN > 20 mg/dL → Ridurre proteine< | ||
+ | • BUN < 5 mg/dL → Aumentare proteine< | ||
+ | • Trigliceridi 200-400 mg/dL → Ridurre/ | ||
+ | • Ipernatremia → Ridurre sodio, aumentare liquidi liberi | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div class=" | ||
+ | < | ||
+ | <div class=" | ||
+ | <div class=" | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | </ | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | </ | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | </ | ||
+ | </ | ||
+ | <div class=" | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <select id=" | ||
+ | <option value=" | ||
+ | <option value=" | ||
+ | </ | ||
+ | </ | ||
+ | <div class=" | ||
+ | <label for=" | ||
+ | <select id=" | ||
+ | <option value=" | ||
+ | <option value=" | ||
+ | <option value=" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | <button class=" | ||
+ | <button class=" | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div id=" | ||
+ | < | ||
+ | <div id=" | ||
</ | </ | ||
</ | </ | ||
Linea 942: | Linea 1966: | ||
< | < | ||
- | // DATI NUTRIZIONALI COMPLETI | + | // DATI NUTRIZIONALI COMPLETI |
- | var formulaData = { | + | const formulaData = { |
maternal: { name: "Latte Materno", | maternal: { name: "Latte Materno", | ||
maternal_fortified: | maternal_fortified: | ||
Linea 955: | Linea 1979: | ||
}; | }; | ||
- | // CONFIGURAZIONI PARENTERALI COMPLETE | + | // CONFIGURAZIONI PARENTERALI COMPLETE |
- | var parenteralConfig = { | + | const parenteralConfig = { |
+ | trophamine: { | ||
+ | name: " | ||
+ | protein: 6.0, carbs: 0, lipids: 0, sodium: 0, potassium: 0, | ||
+ | calcium: 0, phosphorus: 0, magnesium: 0, energy: 24, water: 94, | ||
+ | osmolarity: 360, // mOsm/L | ||
+ | description: | ||
+ | notes: " | ||
+ | }, | ||
+ | intralipid: { | ||
+ | name: " | ||
+ | protein: 0, carbs: 0, lipids: 20.0, sodium: 0, potassium: 0, | ||
+ | calcium: 0, phosphorus: 0, magnesium: 0, energy: 200, water: 80, | ||
+ | osmolarity: 280, // mOsm/L | ||
+ | description: | ||
+ | notes: " | ||
+ | }, | ||
+ | glucose50: { | ||
+ | name: " | ||
+ | protein: 0, carbs: 50.0, lipids: 0, sodium: 0, potassium: 0, | ||
+ | calcium: 0, phosphorus: 0, magnesium: 0, energy: 200, water: 50, | ||
+ | osmolarity: 2780, // mOsm/L | ||
+ | description: | ||
+ | notes: " | ||
+ | }, | ||
ca_gluconato: | ca_gluconato: | ||
- | name: " | + | name: " |
- | | + | |
- | | + | |
+ | osmolarity: 320, // mOsm/L | ||
+ | description: | ||
+ | notes: "8.4 mg Ca/ml. Non precipita con fosfati. Osmolarità: | ||
}, | }, | ||
esafosfina: { | esafosfina: { | ||
- | name: " | + | name: " |
- | | + | |
- | | + | |
+ | osmolarity: 450, // mOsm/L | ||
+ | description: | ||
+ | notes: "16 mg P/ml + 1.3 mEq Na/ml. Fosforo organico. Osmolarità: | ||
}, | }, | ||
mg_sulfate: { | mg_sulfate: { | ||
- | name: " | + | name: " |
- | | + | |
- | | + | |
+ | osmolarity: 1620, // mOsm/L | ||
+ | description: | ||
+ | notes: "8 mEq Mg/ml. Cofattore enzimatico. Osmolarità: | ||
}, | }, | ||
nacl: { | nacl: { | ||
- | name: "Sodio Cloruro", | + | name: "Sodio Cloruro |
- | | + | |
- | | + | |
+ | osmolarity: 2050, // mOsm/L | ||
+ | description: | ||
+ | notes: "10 mEq Na/ml. Prima scelta per supplementazione sodio. Osmolarità: | ||
}, | }, | ||
sodium_acetate: | sodium_acetate: | ||
- | name: "Sodio Acetato", | + | name: "Sodio Acetato |
- | | + | |
- | | + | |
+ | osmolarity: 1340, // mOsm/L | ||
+ | description: | ||
+ | notes: "6.67 mEq Na/ml. Per acidosi: pH < 7.25 o BE < -4. Osmolarità: | ||
}, | }, | ||
kcl: { | kcl: { | ||
- | name: " | + | name: " |
- | | + | |
- | protein: 0, carbs: 0, lipids: 0, energy: 0, water: 99 | + | calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99, |
+ | osmolarity: 2050, // mOsm/L | ||
+ | description: | ||
+ | notes: "10 mEq K/ml. Max velocità infusione: 0.5 mEq/kg/h. Osmolarità: | ||
+ | }, | ||
+ | carnitene: { | ||
+ | name: " | ||
+ | protein: 0, carbs: 0, lipids: 0, sodium: 0, potassium: 0, | ||
+ | calcium: 0, phosphorus: 0, magnesium: 0, energy: 0, water: 99, | ||
+ | osmolarity: 280, // mOsm/L | ||
+ | carnitine: 10000, // 100 mg/ml = 10000 mg/100ml | ||
+ | description: | ||
+ | notes: "100 mg/ml. Indicata per NPT > 1 mese. Dose: 5 mg/kg/die. Osmolarità: | ||
} | } | ||
}; | }; | ||
- | // Database medici | + | // Database fortificanti dinamico |
- | var doctorsData = { | + | let fortifierData = { |
+ | prenidina_fm85: | ||
+ | name: " | ||
+ | protein: 14, carbs: 4, lipids: 2.5, sodium: 2, potassium: 15, | ||
+ | calcium: 3500, phosphorus: 2000, magnesium: 150, energy: 400, | ||
+ | dose: " | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | // Database medici | ||
+ | let doctorsData = { | ||
dr_bellu: { name: " | dr_bellu: { name: " | ||
dr_condo: { name: " | dr_condo: { name: " | ||
Linea 996: | Linea 2081: | ||
dr_meroni: { name: " | dr_meroni: { name: " | ||
dr_calzatini: | dr_calzatini: | ||
- | dr_ferrari: { name: " | + | dr_ferrari: { name: " |
+ | dr_ferendeles: | ||
+ | dr_fumagalli_l: | ||
+ | dr_fumagalli_m: | ||
+ | dr_corno: { name: " | ||
+ | dr_evasi: { name: " | ||
+ | dr_cereda: { name: " | ||
+ | dr_ceccon: { name: " | ||
+ | dr_nava: { name: " | ||
+ | dr_terenzi: { name: " | ||
+ | dr_raffa: { 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 | ||
- | var patientData = {}; | + | let patientData = {}; |
- | var enteralData = null; | + | let enteralData = null; |
- | window.currentActiveReport | + | let currentRequirements |
- | // INIZIALIZZAZIONE | + | // CONFIGURAZIONE CLINICA AVANZATA |
- | document.addEventListener(' | + | let clinicalConfig = { |
- | | + | |
- | | + | phosphorusReq: |
- | }); | + | magnesiumReq: |
+ | maxGIR: 12.0, | ||
+ | | ||
+ | maxProtein: 4.5, | ||
+ | hospitalName: | ||
+ | departmentName: | ||
+ | directorName: | ||
+ | }; | ||
- | // FUNZIONE | + | // FUNZIONE |
- | function | + | function |
- | | + | |
- | | + | |
- | | + | nutritionBtn.className |
+ | nutritionBtn.innerHTML = ' | ||
+ | |||
+ | // Nascondi | ||
+ | const nutritionResults = document.getElementById(' | ||
+ | | ||
+ | nutritionResults.classList.add('hidden'); | ||
+ | } | ||
+ | |||
+ | // Reset anche il pulsante NPT perché i fabbisogni sono cambiati | ||
+ | resetParenteralButton(); | ||
} | } | ||
+ | } | ||
+ | |||
+ | // FUNZIONE RESET PULSANTE PARENTERALE | ||
+ | function resetParenteralButton() { | ||
+ | const parenteralBtn = document.getElementById(' | ||
+ | if (parenteralBtn) { | ||
+ | parenteralBtn.className = ' | ||
+ | parenteralBtn.innerHTML = ' | ||
+ | | ||
+ | // Reset anche i campi visualizzati | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | | ||
+ | // Nascondi i risultati precedenti | ||
+ | const parenteralResults = document.getElementById(' | ||
+ | if (parenteralResults) { | ||
+ | parenteralResults.classList.add(' | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | // SISTEMA PROTEZIONE CONFIGURAZIONE | ||
+ | function checkConfigAccess() { | ||
+ | // Password predefinita (modificabile) | ||
+ | const ADMIN_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 | ||
+ | function showTab(tabId) { | ||
+ | // Nascondi tutti i contenuti dei tab | ||
+ | document.querySelectorAll(' | ||
+ | content.classList.remove(' | ||
+ | }); | ||
+ | |||
+ | // Rimuovi classe active da tutti i tab | ||
+ | document.querySelectorAll(' | ||
+ | tab.classList.remove(' | ||
+ | }); | ||
+ | |||
+ | // Mostra il contenuto del tab selezionato | ||
+ | const targetContent = document.getElementById(tabId); | ||
if (targetContent) { | if (targetContent) { | ||
targetContent.classList.add(' | targetContent.classList.add(' | ||
} | } | ||
| | ||
- | event.target.closest(' | + | |
+ | const clickedTab = event.target.closest(' | ||
+ | if (clickedTab) { | ||
+ | clickedTab.classList.add(' | ||
+ | } | ||
+ | |||
+ | // Sistema di protezione per TAB configurazione | ||
+ | if (tabId === ' | ||
+ | if (!checkConfigAccess()) { | ||
+ | return; // Blocca l' | ||
+ | } | ||
+ | setTimeout(() => { | ||
+ | populateEnteralConfigTable(); | ||
+ | populateParenteralConfigTable(); | ||
+ | populateDoctorsConfigTable(); | ||
+ | populateNursesConfigTable(); | ||
+ | populatePharmacistsConfigTable(); | ||
+ | populateTechniciansConfigTable(); | ||
+ | }, 100); | ||
+ | } | ||
+ | |||
+ | // Popola le dropdown del personale quando si apre il TAB 5 (report) | ||
+ | if (tabId === ' | ||
+ | setTimeout(() => { | ||
+ | updatePreparationStaffDropdowns(); | ||
+ | }, 100); | ||
} | } | ||
- | // FUNZIONE CALCOLO FASE | + | } |
+ | |||
+ | // FUNZIONE GESTIONE CARTELLA CLINICA | ||
+ | function setupMedicalRecordField() { | ||
+ | const medicalRecordInput = document.getElementById(' | ||
+ | const currentYear = new Date().getFullYear().toString(); | ||
+ | |||
+ | // Imposta il valore iniziale con l'anno corrente | ||
+ | if (!medicalRecordInput.value) { | ||
+ | medicalRecordInput.value = currentYear; | ||
+ | } | ||
+ | |||
+ | // Gestisce l' | ||
+ | medicalRecordInput.addEventListener(' | ||
+ | let value = e.target.value.replace(/ | ||
+ | |||
+ | // Se l' | ||
+ | if (value.length < 4 || !value.startsWith(currentYear)) { | ||
+ | value = currentYear + value.slice(4); | ||
+ | } | ||
+ | |||
+ | // Limita a 10 cifre totali | ||
+ | if (value.length > 10) { | ||
+ | value = value.slice(0, | ||
+ | } | ||
+ | |||
+ | e.target.value = value; | ||
+ | }); | ||
+ | |||
+ | // Quando il campo ottiene il focus, posiziona il cursore dopo l' | ||
+ | medicalRecordInput.addEventListener(' | ||
+ | if (e.target.value === currentYear) { | ||
+ | // Posiziona il cursore alla fine | ||
+ | setTimeout(() => { | ||
+ | e.target.setSelectionRange(4, | ||
+ | }, 0); | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | // Suggerimento visivo | ||
+ | medicalRecordInput.addEventListener(' | ||
+ | if (e.target.value === currentYear) { | ||
+ | e.target.placeholder = currentYear + ' | ||
+ | } | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | function updateDoctorsDropdown() { | ||
+ | console.log(' | ||
+ | const prescribingDoctorSelect = document.getElementById(' | ||
+ | console.log(' | ||
+ | |||
+ | if (!prescribingDoctorSelect) { | ||
+ | console.error(' | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | console.log(' | ||
+ | console.log(' | ||
+ | |||
+ | const currentValue = prescribingDoctorSelect.value; | ||
+ | prescribingDoctorSelect.innerHTML = '< | ||
+ | |||
+ | Object.keys(doctorsData).forEach(function(key) { | ||
+ | const doctor = doctorsData[key]; | ||
+ | console.log(' | ||
+ | const option = document.createElement(' | ||
+ | option.value = key; | ||
+ | option.textContent = doctor.fullName; | ||
+ | prescribingDoctorSelect.appendChild(option); | ||
+ | }); | ||
+ | |||
+ | // Ripristina il valore precedente se esiste ancora | ||
+ | if (currentValue && doctorsData[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 }; | ||
+ | } | ||
+ | |||
+ | // FUNZIONE CALCOLO FASE NUTRIZIONALE (DA VERSIONE 17) | ||
function calculatePhase() { | function calculatePhase() { | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
| | ||
- | patientData = { | + | |
- | medicalRecord: | + | const doctorFullName = prescribingDoctorValue && doctorsData[prescribingDoctorValue] ? |
- | birthWeight: | + | doctorsData[prescribingDoctorValue].fullName : ''; |
- | currentWeight: | + | |
- | daysOfLife: daysOfLife, | + | |
- | bun: bun, | + | // Recupera età gestazionale per i report |
- | glucose: glucose, | + | const gestationalWeeks = parseInt(document.getElementById(' |
- | sodium: sodium, | + | const gestationalDays = parseInt(document.getElementById(' |
- | ph: ph, | + | |
- | baseExcess: baseExcess, | + | // Calcola età post-concezionale |
- | diuresis: diuresis, | + | const postConceptionalAge = calculatePostConceptionalAge(); |
- | prescriptionDate: | + | |
- | prescribingDoctor: | + | patientData = { |
- | }; | + | medicalRecord: |
+ | birthWeight: | ||
+ | currentWeight: | ||
+ | daysOfLife: daysOfLife, | ||
+ | | ||
+ | gestationalDays: | ||
+ | postConceptionalAge: | ||
+ | | ||
+ | glucose: glucose, | ||
+ | sodium: sodium, | ||
+ | ph: ph, | ||
+ | baseExcess: baseExcess, | ||
+ | diuresis: diuresis, | ||
+ | prescriptionDate: | ||
+ | prescribingDoctor: | ||
+ | | ||
+ | }; | ||
| | ||
document.getElementById(' | document.getElementById(' | ||
| | ||
- | | + | |
- | | + | |
- | | + | |
| | ||
+ | // Analisi BUN | ||
if (bun && bun !== '' | if (bun && bun !== '' | ||
- | | + | |
if (bunValue < 9) { | if (bunValue < 9) { | ||
bunStatus = 'Basso - Aumentare proteine'; | bunStatus = 'Basso - Aumentare proteine'; | ||
- | bunWarning = 'BUN basso: considerare aumento | + | bunWarning = 'BUN basso: considerare aumento |
} else if (bunValue > 14) { | } else if (bunValue > 14) { | ||
bunStatus = ' | bunStatus = ' | ||
- | bunWarning = 'BUN elevato: ridurre | + | bunWarning = 'BUN elevato: ridurre |
} else { | } else { | ||
bunStatus = ' | bunStatus = ' | ||
Linea 1081: | Linea 2444: | ||
} | } | ||
| | ||
- | | + | |
+ | let otherWarnings = []; | ||
+ | |||
+ | if (glucose && glucose !== '' | ||
+ | const glucoseValue = parseFloat(glucose); | ||
+ | if (glucoseValue < 70) { | ||
+ | otherWarnings.push(' | ||
+ | } else if (glucoseValue > 150) { | ||
+ | otherWarnings.push(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if (sodium && sodium !== '' | ||
+ | const sodiumValue = parseFloat(sodium); | ||
+ | if (sodiumValue < 135) { | ||
+ | otherWarnings.push(' | ||
+ | } else if (sodiumValue > 145) { | ||
+ | otherWarnings.push(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if (ph && ph !== '' | ||
+ | const phValue = parseFloat(ph); | ||
+ | if (phValue < 7.35) { | ||
+ | otherWarnings.push(' | ||
+ | } else if (phValue > 7.45) { | ||
+ | otherWarnings.push(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if (baseExcess && baseExcess !== '' | ||
+ | const beValue = parseFloat(baseExcess); | ||
+ | if (beValue < -4) { | ||
+ | otherWarnings.push(' | ||
+ | } else if (beValue > 2) { | ||
+ | otherWarnings.push(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Raccomandazione combinata pH + BE per Sodio Acetato | ||
+ | if (ph && baseExcess) { | ||
+ | const phValue = parseFloat(ph); | ||
+ | const beValue = parseFloat(baseExcess); | ||
+ | if (phValue < 7.25 || beValue < -4) { | ||
+ | otherWarnings.push(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if (diuresis && diuresis !== '' | ||
+ | const diuresisValue = parseFloat(diuresis); | ||
+ | if (diuresisValue < 1) { | ||
+ | otherWarnings.push(' | ||
+ | } else if (diuresisValue > 3) { | ||
+ | otherWarnings.push(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | let phaseInfoHtml = '< | ||
phaseInfoHtml += '< | phaseInfoHtml += '< | ||
phaseInfoHtml += '< | phaseInfoHtml += '< | ||
Linea 1088: | Linea 2508: | ||
phaseInfoHtml += '< | phaseInfoHtml += '< | ||
} | } | ||
- | phaseInfoHtml += '< | + | phaseInfoHtml += '< |
phaseInfoHtml += '< | phaseInfoHtml += '< | ||
- | phaseInfoHtml += '< | + | |
+ | if (gestationalWeeks && gestationalWeeks > 0) { | ||
+ | const gestDaysDisplay = gestationalDays || 0; | ||
+ | phaseInfoHtml += '< | ||
+ | if (postConceptionalAge && postConceptionalAge.format) { | ||
+ | phaseInfoHtml += '< | ||
+ | } | ||
+ | } | ||
+ | | ||
phaseInfoHtml += '</ | phaseInfoHtml += '</ | ||
phaseInfoHtml += '< | phaseInfoHtml += '< | ||
Linea 1096: | Linea 2524: | ||
if (patientData.bun) { | if (patientData.bun) { | ||
phaseInfoHtml += '< | phaseInfoHtml += '< | ||
+ | } | ||
+ | if (patientData.glucose) { | ||
+ | const gluStatus = parseFloat(patientData.glucose) >= 70 && parseFloat(patientData.glucose) <= 110 ? ' | ||
+ | phaseInfoHtml += '< | ||
+ | } | ||
+ | if (patientData.sodium) { | ||
+ | const naStatus = parseFloat(patientData.sodium) >= 135 && parseFloat(patientData.sodium) <= 145 ? ' | ||
+ | phaseInfoHtml += '< | ||
+ | } | ||
+ | if (patientData.ph) { | ||
+ | const phStatus = parseFloat(patientData.ph) >= 7.35 && parseFloat(patientData.ph) <= 7.45 ? ' | ||
+ | phaseInfoHtml += '< | ||
+ | } | ||
+ | if (patientData.baseExcess) { | ||
+ | const beStatus = parseFloat(patientData.baseExcess) >= -4 && parseFloat(patientData.baseExcess) <= 2 ? ' | ||
+ | phaseInfoHtml += '< | ||
+ | } | ||
+ | if (patientData.diuresis) { | ||
+ | const diuStatus = parseFloat(patientData.diuresis) >= 1 && parseFloat(patientData.diuresis) <= 3 ? ' | ||
+ | phaseInfoHtml += '< | ||
} | } | ||
phaseInfoHtml += '</ | phaseInfoHtml += '</ | ||
Linea 1102: | Linea 2550: | ||
if (bunWarning) { | if (bunWarning) { | ||
phaseInfoHtml += '< | phaseInfoHtml += '< | ||
+ | } | ||
+ | | ||
+ | if (otherWarnings.length > 0) { | ||
+ | phaseInfoHtml += '< | ||
} | } | ||
| | ||
Linea 1111: | Linea 2563: | ||
document.getElementById(' | document.getElementById(' | ||
document.getElementById(' | document.getElementById(' | ||
+ | | ||
+ | // Aggiorna il suggerimento sodio se il TAB 3 è già stato visitato | ||
+ | updateSodiumRecommendation(); | ||
+ | | ||
+ | // RESET anche il pulsante NPT | ||
+ | resetParenteralButton(); | ||
} | } | ||
+ | // FUNZIONE AGGIORNAMENTO OPZIONI FORTIFICANTE | ||
function updateFortifierOptions() { | function updateFortifierOptions() { | ||
- | | + | |
- | | + | |
+ | const fortifierSelect = document.getElementById(' | ||
| | ||
if (formulaType === ' | if (formulaType === ' | ||
fortifierSection.classList.remove(' | fortifierSection.classList.remove(' | ||
+ | | ||
+ | fortifierSelect.innerHTML = '< | ||
+ | Object.keys(fortifierData).forEach(function(key) { | ||
+ | const option = document.createElement(' | ||
+ | option.value = key; | ||
+ | option.textContent = fortifierData[key].name; | ||
+ | fortifierSelect.appendChild(option); | ||
+ | }); | ||
} else { | } else { | ||
fortifierSection.classList.add(' | fortifierSection.classList.add(' | ||
+ | fortifierSelect.value = ' | ||
} | } | ||
} | } | ||
+ | // FUNZIONE AGGIORNAMENTO DISPLAY CONCENTRAZIONE | ||
function updateConcentrationDisplay() { | function updateConcentrationDisplay() { | ||
- | | + | |
document.getElementById(' | document.getElementById(' | ||
} | } | ||
+ | // FUNZIONE CALCOLO NUTRIZIONE ENTERALE (DA VERSIONE 17) | ||
function calculateEnteral() { | function calculateEnteral() { | ||
- | | + | |
- | alert(' | + | const enteralCurrentWeight = parseInt(document.getElementById(' |
+ | const enteralBirthWeight = parseInt(document.getElementById(' | ||
+ | |||
+ | if (!enteralCurrentWeight || !enteralBirthWeight) { | ||
+ | alert(' | ||
return; | return; | ||
} | } | ||
| | ||
- | | + | |
- | | + | if (!patientData.currentWeight) { |
- | | + | patientData.currentWeight = enteralCurrentWeight; |
- | | + | patientData.birthWeight = enteralBirthWeight; |
- | | + | } |
- | | + | |
+ | const formulaType = document.getElementById(' | ||
+ | | ||
+ | | ||
+ | | ||
+ | const currentWeight = patientData.currentWeight; | ||
+ | | ||
+ | | ||
| | ||
if (formulaType === ' | if (formulaType === ' | ||
Linea 1151: | Linea 2633: | ||
}; | }; | ||
| | ||
- | | + | |
if (additionalFluids > 0) { | if (additionalFluids > 0) { | ||
tableHtml += '< | tableHtml += '< | ||
Linea 1162: | Linea 2644: | ||
document.getElementById(' | document.getElementById(' | ||
} else { | } else { | ||
- | | + | |
- | | + | |
| | ||
+ | // Calcoli finali per kg di peso | ||
enteralData = { | enteralData = { | ||
volume: dailyVolume, | volume: dailyVolume, | ||
Linea 1180: | Linea 2663: | ||
}; | }; | ||
| | ||
- | | + | |
tableHtml += '< | tableHtml += '< | ||
tableHtml += '< | tableHtml += '< | ||
if (additionalFluids > 0) { | if (additionalFluids > 0) { | ||
- | tableHtml += '< | + | tableHtml += '< |
tableHtml += '< | tableHtml += '< | ||
} else { | } else { | ||
Linea 1204: | Linea 2687: | ||
document.getElementById(' | document.getElementById(' | ||
| | ||
- | | + | |
+ | const enteralBtn = document.getElementById(' | ||
if (enteralBtn) { | if (enteralBtn) { | ||
enteralBtn.className = ' | enteralBtn.className = ' | ||
enteralBtn.innerHTML = ' | enteralBtn.innerHTML = ' | ||
} | } | ||
+ | | ||
+ | // RESET del pulsante Fabbisogni quando si modificano gli apporti enterali | ||
+ | resetNutritionButton(); | ||
} | } | ||
+ | // FUNZIONE CARICAMENTO VALORI STANDARD (DA VERSIONE 17) | ||
function loadNutritionDefaults() { | function loadNutritionDefaults() { | ||
- | | + | |
- | alert(' | + | const defaultsCurrentWeight = parseInt(document.getElementById(' |
+ | const defaultsBirthWeight = parseInt(document.getElementById(' | ||
+ | const defaultsDaysOfLife = parseInt(document.getElementById(' | ||
+ | |||
+ | if (!defaultsCurrentWeight || !defaultsBirthWeight || !defaultsDaysOfLife) { | ||
+ | alert(' | ||
return; | return; | ||
} | } | ||
| | ||
- | | + | |
- | | + | if (!patientData.currentWeight) { |
+ | patientData.currentWeight = defaultsCurrentWeight; | ||
+ | patientData.birthWeight = defaultsBirthWeight; | ||
+ | patientData.daysOfLife = defaultsDaysOfLife; | ||
+ | } | ||
+ | |||
+ | const targetDay = parseInt(document.getElementById(' | ||
+ | | ||
| | ||
- | | + | |
- | | + | |
weightCategorySelect.value = selectedCategory; | weightCategorySelect.value = selectedCategory; | ||
| | ||
- | | + | |
if (selectedCategory === ' | if (selectedCategory === ' | ||
plan = targetDay <= 3 ? {liquids: 100, protein: 3.5, carbs: 8.0, lipids: 1.0} : | plan = targetDay <= 3 ? {liquids: 100, protein: 3.5, carbs: 8.0, lipids: 1.0} : | ||
Linea 1233: | Linea 2733: | ||
} | } | ||
| | ||
+ | // Aggiustamento BUN | ||
if (patientData.bun && patientData.bun !== '' | if (patientData.bun && patientData.bun !== '' | ||
- | | + | |
if (bunValue < 9) { | if (bunValue < 9) { | ||
plan.protein = Math.min(6.0, | plan.protein = Math.min(6.0, | ||
Linea 1246: | Linea 2747: | ||
document.getElementById(' | document.getElementById(' | ||
document.getElementById(' | document.getElementById(' | ||
- | document.getElementById(' | + | |
- | document.getElementById(' | + | // Usa configurazione clinica per elettroliti |
- | document.getElementById(' | + | |
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
document.getElementById(' | document.getElementById(' | ||
document.getElementById(' | document.getElementById(' | ||
| | ||
- | | + | |
- | | + | const sodiumSelect = document.getElementById(' |
+ | if (patientData.ph || patientData.baseExcess) { | ||
+ | const ph = patientData.ph ? parseFloat(patientData.ph) : null; | ||
+ | const be = patientData.baseExcess ? parseFloat(patientData.baseExcess) : null; | ||
+ | |||
+ | // Auto-seleziona Sodio Acetato se acidosi | ||
+ | if ((ph && ph < 7.30) || (be && be < -4)) { | ||
+ | sodiumSelect.value = ' | ||
+ | } else { | ||
+ | sodiumSelect.value = ' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Aggiorna il suggerimento sodio | ||
+ | updateSodiumRecommendation(); | ||
+ | |||
+ | // Gestione vitamine/ | ||
+ | const patientCurrentWeight | ||
+ | | ||
| | ||
if (targetDay >= 3 && enteralVolumePerKg < 100) { | if (targetDay >= 3 && enteralVolumePerKg < 100) { | ||
Linea 1260: | Linea 2781: | ||
document.getElementById(' | document.getElementById(' | ||
} else { | } else { | ||
+ | // Mantieni i valori a zero se prima del 3° giorno o se enterale ≥100 ml/kg/die | ||
document.getElementById(' | document.getElementById(' | ||
document.getElementById(' | document.getElementById(' | ||
Linea 1265: | Linea 2787: | ||
} | } | ||
| | ||
- | document.getElementById(' | + | document.getElementById(' |
| | ||
- | | + | document.getElementById(' |
- | if (loadBtn) { | + | |
- | loadBtn.className = ' | + | |
- | | + | // RESET del pulsante Fabbisogni quando si modificano i valori standard |
- | | + | resetNutritionButton(); |
} | } | ||
+ | // FUNZIONE AGGIORNAMENTO UNITÀ CARBOIDRATI | ||
function updateCarbUnit() { | function updateCarbUnit() { | ||
- | | + | |
- | | + | |
- | | + | |
| | ||
if (unit === ' | if (unit === ' | ||
Linea 1288: | Linea 2811: | ||
carbInput.setAttribute(' | carbInput.setAttribute(' | ||
} | } | ||
+ | | ||
+ | // Reset fabbisogni quando si cambia unità | ||
+ | resetNutritionButton(); | ||
} | } | ||
+ | // FUNZIONE AGGIORNAMENTO CATEGORIA PESO | ||
function updateWeightCategory() { | function updateWeightCategory() { | ||
- | // Placeholder | + | // Reset fabbisogni quando si cambia categoria peso |
+ | resetNutritionButton(); | ||
} | } | ||
+ | // FUNZIONE AGGIORNAMENTO TIPO SODIO | ||
function updateSodiumChoice() { | function updateSodiumChoice() { | ||
- | // Placeholder | + | // Resetta i fabbisogni quando si cambia il tipo di sodio |
+ | resetNutritionButton(); | ||
} | } | ||
+ | // FUNZIONE AGGIORNAMENTO SUGGERIMENTO SODIO | ||
+ | function updateSodiumRecommendation() { | ||
+ | const sodiumSelect = document.getElementById(' | ||
+ | const recommendationDiv = document.getElementById(' | ||
+ | | ||
+ | if (!patientData.ph && !patientData.baseExcess) { | ||
+ | // Nessun dato clinico disponibile | ||
+ | recommendationDiv.classList.add(' | ||
+ | return; | ||
+ | } | ||
+ | | ||
+ | const ph = patientData.ph ? parseFloat(patientData.ph) : null; | ||
+ | const be = patientData.baseExcess ? parseFloat(patientData.baseExcess) : null; | ||
+ | | ||
+ | // Logica di raccomandazione | ||
+ | let needsAcetate = false; | ||
+ | let reason = ''; | ||
+ | | ||
+ | if (ph && ph < 7.30) { | ||
+ | needsAcetate = true; | ||
+ | reason = 'pH < 7.30 (acidosi)'; | ||
+ | } else if (be && be < -4) { | ||
+ | needsAcetate = true; | ||
+ | reason = 'BE < -4 mEq/L (acidosi metabolica)'; | ||
+ | } else if (ph && be && (ph < 7.30 || be < -4)) { | ||
+ | needsAcetate = true; | ||
+ | reason = 'pH < 7.30 o BE < -4 (acidosi)'; | ||
+ | } | ||
+ | | ||
+ | if (needsAcetate) { | ||
+ | // Suggerisci Sodio Acetato | ||
+ | if (sodiumSelect.value === ' | ||
+ | // L' | ||
+ | recommendationDiv.innerHTML = '< | ||
+ | '< | ||
+ | 'In base ai parametri clinici (' + reason + '), si raccomanda < | ||
+ | '</ | ||
+ | recommendationDiv.classList.remove(' | ||
+ | } else { | ||
+ | // L' | ||
+ | recommendationDiv.innerHTML = '< | ||
+ | '< | ||
+ | 'Sodio Acetato è indicato per i parametri clinici attuali (' + reason + ' | ||
+ | '</ | ||
+ | recommendationDiv.classList.remove(' | ||
+ | } | ||
+ | } else { | ||
+ | // Parametri normali | ||
+ | if (sodiumSelect.value === ' | ||
+ | // L' | ||
+ | recommendationDiv.innerHTML = '< | ||
+ | '< | ||
+ | 'I parametri clinici sono nella norma. Sodio Cloruro potrebbe essere sufficiente, | ||
+ | '</ | ||
+ | recommendationDiv.classList.remove(' | ||
+ | } else { | ||
+ | // Tutto normale | ||
+ | recommendationDiv.classList.add(' | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // FUNZIONE CALCOLO FABBISOGNI NUTRIZIONALI (DA VERSIONE 17) | ||
function calculateNutrition() { | function calculateNutrition() { | ||
- | | + | |
- | alert(' | + | const nutritionCurrentWeight = parseInt(document.getElementById(' |
+ | const nutritionBirthWeight = parseInt(document.getElementById(' | ||
+ | |||
+ | if (!nutritionCurrentWeight || !nutritionBirthWeight) { | ||
+ | alert(' | ||
return; | return; | ||
} | } | ||
| | ||
- | | + | |
+ | if (!patientData.currentWeight) { | ||
+ | patientData.currentWeight = nutritionCurrentWeight; | ||
+ | patientData.birthWeight = nutritionBirthWeight; | ||
+ | } | ||
+ | |||
+ | const requirements = { | ||
liquids: parseFloat(document.getElementById(' | liquids: parseFloat(document.getElementById(' | ||
protein: parseFloat(document.getElementById(' | protein: parseFloat(document.getElementById(' | ||
Linea 1321: | Linea 2924: | ||
}; | }; | ||
| | ||
- | | + | |
+ | const carbsGPerKgDay = requirements.carbUnit === ' | ||
(requirements.carbs * 1440 / 1000) : requirements.carbs; | (requirements.carbs * 1440 / 1000) : requirements.carbs; | ||
| | ||
- | | + | |
+ | const enteralVolumePerKg = enteralData ? (enteralData.totalFluids / patientCurrentWeight * 1000) : 0; | ||
| | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
| | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
| | ||
- | | + | |
- | | + | const enteralCalcium = enteralData ? enteralData.calcium : 0; |
- | | + | |
- | | + | |
- | | + | |
+ | | ||
| | ||
- | | + | |
- | | + | const residualCalcium = Math.max(0, requirements.calcium - enteralCalcium); |
- | | + | |
- | | + | |
- | | + | |
+ | | ||
| | ||
window.residualNeeds = { | window.residualNeeds = { | ||
Linea 1367: | Linea 2974: | ||
}; | }; | ||
| | ||
- | | + | |
- | | + | const carbsMgPerKgMin = (carbsGPerKgDay * 1000) / 1440; |
- | | + | |
+ | | ||
| | ||
- | | + | |
tableHtml += '< | tableHtml += '< | ||
tableHtml += '< | tableHtml += '< | ||
Linea 1378: | Linea 2986: | ||
tableHtml += '< | tableHtml += '< | ||
tableHtml += '< | tableHtml += '< | ||
+ | tableHtml += '< | ||
+ | tableHtml += '< | ||
+ | tableHtml += '< | ||
+ | tableHtml += '< | ||
+ | tableHtml += '< | ||
+ | tableHtml += '< | ||
+ | tableHtml += '< | ||
+ | tableHtml += '< | ||
+ | tableHtml += '< | ||
tableHtml += '< | tableHtml += '< | ||
tableHtml += '</ | tableHtml += '</ | ||
Linea 1385: | Linea 3002: | ||
document.getElementById(' | document.getElementById(' | ||
document.getElementById(' | document.getElementById(' | ||
+ | | ||
+ | // RESET del pulsante NPT quando si modificano i fabbisogni | ||
+ | resetParenteralButton(); | ||
} | } | ||
+ | // FUNZIONE CALCOLO ELETTROLITI AGGIUNTIVI (DA VERSIONE 17) | ||
function calculateElectrolyteAdditions(calciumNeeded, | function calculateElectrolyteAdditions(calciumNeeded, | ||
- | | + | |
ca_gluconato: | ca_gluconato: | ||
esafosfina: 0, | esafosfina: 0, | ||
Linea 1396: | Linea 3017: | ||
kcl: 0, | kcl: 0, | ||
totalVolume: | totalVolume: | ||
- | providedCalcium: | ||
- | providedPhosphorus: | ||
- | providedMagnesium: | ||
- | providedSodium: | ||
- | providedPotassium: | ||
sodiumSource: | sodiumSource: | ||
}; | }; | ||
| | ||
- | | + | |
- | | + | const sodiumTypeSelect = document.getElementById(' |
+ | | ||
additions.sodiumSource = selectedSodiumType; | additions.sodiumSource = selectedSodiumType; | ||
| | ||
- | | + | |
- | | + | const totalCalciumNeeded = calciumNeeded * currentWeightKg; |
- | | + | |
- | | + | |
- | | + | |
+ | | ||
| | ||
+ | // Calcio Gluconato 10% (840 mg Ca/100ml) | ||
if (totalCalciumNeeded > 0) { | if (totalCalciumNeeded > 0) { | ||
additions.ca_gluconato = totalCalciumNeeded / (parenteralConfig.ca_gluconato.calcium / 100); | additions.ca_gluconato = totalCalciumNeeded / (parenteralConfig.ca_gluconato.calcium / 100); | ||
- | additions.providedCalcium = totalCalciumNeeded; | ||
} | } | ||
| | ||
+ | // Esafosfina (1600 mg P/100ml + 130 mEq Na/100ml) | ||
+ | let sodiumFromEsafosfina = 0; | ||
if (totalPhosphorusNeeded > 0) { | if (totalPhosphorusNeeded > 0) { | ||
additions.esafosfina = totalPhosphorusNeeded / (parenteralConfig.esafosfina.phosphorus / 100); | additions.esafosfina = totalPhosphorusNeeded / (parenteralConfig.esafosfina.phosphorus / 100); | ||
- | | + | |
- | additions.providedSodium += (additions.esafosfina * parenteralConfig.esafosfina.sodium / 100); | + | |
} | } | ||
| | ||
+ | // Magnesio Solfato (800 mEq Mg/100ml) | ||
if (totalMagnesiumNeeded > 0) { | if (totalMagnesiumNeeded > 0) { | ||
additions.mg_sulfate = totalMagnesiumNeeded / (parenteralConfig.mg_sulfate.magnesium / 100); | additions.mg_sulfate = totalMagnesiumNeeded / (parenteralConfig.mg_sulfate.magnesium / 100); | ||
- | additions.providedMagnesium = totalMagnesiumNeeded; | ||
} | } | ||
| | ||
- | | + | |
+ | const remainingSodium = Math.max(0, totalSodiumNeeded - sodiumFromEsafosfina); | ||
| | ||
if (remainingSodium > 0) { | if (remainingSodium > 0) { | ||
if (selectedSodiumType === ' | if (selectedSodiumType === ' | ||
- | | + | |
additions.sodium_acetate = remainingSodium / concentrationSodiumAcetate; | additions.sodium_acetate = remainingSodium / concentrationSodiumAcetate; | ||
} else { | } else { | ||
- | | + | |
additions.nacl = remainingSodium / concentrationNaCl; | additions.nacl = remainingSodium / concentrationNaCl; | ||
} | } | ||
- | additions.providedSodium += remainingSodium; | ||
} | } | ||
| | ||
+ | // Potassio Cloruro (1000 mEq K/100ml) | ||
if (totalPotassiumNeeded > 0) { | if (totalPotassiumNeeded > 0) { | ||
additions.kcl = totalPotassiumNeeded / (parenteralConfig.kcl.potassium / 100); | additions.kcl = totalPotassiumNeeded / (parenteralConfig.kcl.potassium / 100); | ||
- | additions.providedPotassium = totalPotassiumNeeded; | ||
} | } | ||
| | ||
+ | // Volume totale degli elettroliti | ||
additions.totalVolume = additions.ca_gluconato + additions.esafosfina + additions.mg_sulfate + additions.nacl + additions.sodium_acetate + additions.kcl; | additions.totalVolume = additions.ca_gluconato + additions.esafosfina + additions.mg_sulfate + additions.nacl + additions.sodium_acetate + additions.kcl; | ||
| | ||
Linea 1453: | Linea 3073: | ||
} | } | ||
+ | |||
+ | // 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: | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | // FUNZIONE CALCOLO NPT PARENTERALE (DA VERSIONE 17 CON CONTROLLI CLINICI) | ||
function calculateParenteral() { | function calculateParenteral() { | ||
if (!window.residualNeeds) { | if (!window.residualNeeds) { | ||
Linea 1459: | Linea 3260: | ||
} | } | ||
| | ||
- | | + | |
- | | + | |
- | | + | |
| | ||
- | | + | |
+ | const gir = (residualNeeds.carbs * 1000) / 1440; // mg/kg/min | ||
+ | let alerts = []; | ||
| | ||
- | | + | |
+ | alerts.push(' | ||
+ | } | ||
+ | if (residualNeeds.lipids > clinicalConfig.maxLipids) { | ||
+ | alerts.push(' | ||
+ | } | ||
+ | if (residualNeeds.protein > clinicalConfig.maxProtein) { | ||
+ | alerts.push(' | ||
+ | } | ||
+ | |||
+ | // Volume totale residuo richiesto | ||
+ | const totalVolume = Math.round(residualNeeds.liquids * currentWeightKg); | ||
+ | |||
+ | // CALCOLA ELETTROLITI AGGIUNTIVI | ||
+ | const electrolyteAdditions = calculateElectrolyteAdditions( | ||
residualNeeds.calcium, | residualNeeds.calcium, | ||
residualNeeds.phosphorus, | residualNeeds.phosphorus, | ||
Linea 1474: | Linea 3291: | ||
); | ); | ||
| | ||
- | | + | |
- | | + | |
| | ||
- | | + | |
- | | + | |
| | ||
- | | + | |
- | | + | const vitaminsVolume |
+ | | ||
| | ||
- | | + | |
- | | + | const neededGlucose |
+ | | ||
| | ||
- | | + | |
+ | const usedVolume | ||
| | ||
- | | + | // Volume rimanente = Acqua Bidistillata |
- | glucoseMessage = '< | + | |
- | ' | + | |
- | '• Volume utilizzato: ' + usedVolume.toFixed(1) + ' ml< | + | |
- | '• Acqua rimanente: ' + waterVolume.toFixed(1) + ' ml (NEGATIVO!)< | + | |
- | '< | + | |
- | + | ||
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
- | + | ||
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
- | return; | + | |
- | | + | |
- | + | ||
- | if (neededGlucose <= 0) { | + | |
- | glucoseMessage = '< | + | |
- | '• Tutto il glucosio necessario proviene dall\' | + | |
- | '• Non necessario glucosio in NPT</ | + | |
- | + | ||
- | document.getElementById(' | + | |
- | } else { | + | |
- | glucoseMessage = '< | + | |
- | '• Glucosio necessario: ' + neededGlucose.toFixed(1) + ' | + | |
- | '• Glucosio 50%: ' + glucose50Volume.toFixed(1) + ' | + | |
- | '• Acqua bidistillata: | + | |
- | '• < | + | |
- | + | ||
- | document.getElementById(' | + | |
- | } | + | |
| | ||
document.getElementById(' | document.getElementById(' | ||
+ | document.getElementById(' | ||
document.getElementById(' | document.getElementById(' | ||
document.getElementById(' | document.getElementById(' | ||
| | ||
- | | + | |
+ | resultHtml += '< | ||
+ | resultHtml += '< | ||
+ | resultHtml += '< | ||
+ | resultHtml += '< | ||
+ | if (enteralData && enteralData.additionalFluids > 0) { | ||
+ | resultHtml += '< | ||
+ | } | ||
+ | resultHtml += '</ | ||
| | ||
- | resultHtml += '< | + | |
- | resultHtml += '< | + | if (alerts.length > 0) { |
- | resultHtml += '< | + | |
- | resultHtml += '< | + | } |
- | resultHtml | + | |
| | ||
resultHtml += '< | resultHtml += '< | ||
Linea 1541: | Linea 3339: | ||
| | ||
resultHtml += '< | resultHtml += '< | ||
- | resultHtml += '< | + | resultHtml += '< |
| | ||
+ | // ELETTROLITI AGGIUNTIVI | ||
if (electrolyteAdditions.ca_gluconato > 0) { | if (electrolyteAdditions.ca_gluconato > 0) { | ||
resultHtml += '< | resultHtml += '< | ||
Linea 1550: | Linea 3349: | ||
} | } | ||
if (electrolyteAdditions.mg_sulfate > 0) { | if (electrolyteAdditions.mg_sulfate > 0) { | ||
- | resultHtml += '< | + | resultHtml += '< |
} | } | ||
if (electrolyteAdditions.nacl > 0) { | if (electrolyteAdditions.nacl > 0) { | ||
Linea 1556: | 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 | ||
if (residualNeeds.vitalipid > 0) { | if (residualNeeds.vitalipid > 0) { | ||
- | | + | |
resultHtml += '< | resultHtml += '< | ||
} | } | ||
if (residualNeeds.soluvit > 0) { | if (residualNeeds.soluvit > 0) { | ||
- | | + | |
resultHtml += '< | resultHtml += '< | ||
} | } | ||
if (residualNeeds.peditrace > 0) { | if (residualNeeds.peditrace > 0) { | ||
- | | + | |
resultHtml += '< | resultHtml += '< | ||
} | } | ||
| | ||
+ | | ||
+ | // CARNITINA | ||
if (residualNeeds.carnitine > 0) { | if (residualNeeds.carnitine > 0) { | ||
resultHtml += '< | resultHtml += '< | ||
} | } | ||
| | ||
+ | // ACQUA BIDISTILLATA | ||
if (waterVolume > 0) { | if (waterVolume > 0) { | ||
resultHtml += '< | resultHtml += '< | ||
Linea 1588: | Linea 3391: | ||
document.getElementById(' | document.getElementById(' | ||
| | ||
- | | + | |
- | | + | 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 | ||
+ | const deflectorVolume = parseInt(document.getElementById(' | ||
+ | | ||
+ | const ratio = totalVolumeWithDeflector / totalVolume; | ||
| | ||
- | | + | |
- | preparationHtml += '< | + | preparationHtml += '< |
preparationHtml += '• < | preparationHtml += '• < | ||
+ | preparationHtml += '• < | ||
preparationHtml += '• < | preparationHtml += '• < | ||
preparationHtml += '</ | preparationHtml += '</ | ||
| | ||
preparationHtml += '< | preparationHtml += '< | ||
- | preparationHtml += '< | + | preparationHtml += '< |
- | + | ||
- | var ratio = totalVolumeWithDeflector / totalVolume; | + | |
| | ||
if (neededGlucose > 0) { | if (neededGlucose > 0) { | ||
Linea 1607: | Linea 3458: | ||
| | ||
preparationHtml += '< | preparationHtml += '< | ||
- | preparationHtml += '< | + | preparationHtml += '< |
| | ||
if (electrolyteAdditions.ca_gluconato > 0) { | if (electrolyteAdditions.ca_gluconato > 0) { | ||
Linea 1616: | Linea 3467: | ||
} | } | ||
if (electrolyteAdditions.mg_sulfate > 0) { | if (electrolyteAdditions.mg_sulfate > 0) { | ||
- | preparationHtml += '< | + | preparationHtml += '< |
} | } | ||
if (electrolyteAdditions.nacl > 0) { | if (electrolyteAdditions.nacl > 0) { | ||
Linea 1622: | Linea 3473: | ||
} | } | ||
if (electrolyteAdditions.sodium_acetate > 0) { | if (electrolyteAdditions.sodium_acetate > 0) { | ||
- | preparationHtml += '< | + | preparationHtml += '< |
} | } | ||
if (electrolyteAdditions.kcl > 0) { | if (electrolyteAdditions.kcl > 0) { | ||
Linea 1628: | Linea 3479: | ||
} | } | ||
| | ||
+ | // VITAMINE con denominazioni complete | ||
if (residualNeeds.vitalipid > 0) { | if (residualNeeds.vitalipid > 0) { | ||
- | | + | |
preparationHtml += '< | preparationHtml += '< | ||
} | } | ||
if (residualNeeds.soluvit > 0) { | if (residualNeeds.soluvit > 0) { | ||
- | | + | |
preparationHtml += '< | preparationHtml += '< | ||
} | } | ||
if (residualNeeds.peditrace > 0) { | if (residualNeeds.peditrace > 0) { | ||
- | | + | |
preparationHtml += '< | preparationHtml += '< | ||
} | } | ||
| | ||
+ | // CARNITINA con denominazione completa | ||
if (residualNeeds.carnitine > 0) { | if (residualNeeds.carnitine > 0) { | ||
preparationHtml += '< | preparationHtml += '< | ||
Linea 1650: | 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 1655: | Linea 3519: | ||
document.getElementById(' | document.getElementById(' | ||
| | ||
- | window.nptCalculationData | + | |
- | | + | document.getElementById(' |
- | | + | |
- | | + | // Salva i dati per il report |
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | proteinVolume: | ||
+ | lipidVolume: | ||
+ | gir: gir, | ||
+ | neededGlucose: | ||
electrolyteAdditions: | electrolyteAdditions: | ||
- | | + | vitaminsVolume: |
- | lipidVolume: | + | |
- | | + | |
carnitineVolume: | carnitineVolume: | ||
- | | + | |
- | | + | |
- | neededGlucose: | + | |
- | residualNeeds: | + | |
}; | }; | ||
+ | } | ||
+ | |||
+ | // FUNZIONI CONFIGURAZIONE (DA VERSIONE 17) | ||
+ | function populateEnteralConfigTable() { | ||
+ | const tbody = document.getElementById(' | ||
+ | if (!tbody) return; | ||
| | ||
- | | + | |
- | if (parenteralBtn) { | + | Object.keys(formulaData).forEach(key => { |
- | | + | const formula = formulaData[key]; |
- | | + | const row = tbody.insertRow(); |
+ | row.innerHTML = '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | function populateParenteralConfigTable() { | ||
+ | const tbody = document.getElementById(' | ||
+ | if (!tbody) return; | ||
+ | |||
+ | tbody.innerHTML = ''; | ||
+ | Object.keys(parenteralConfig).forEach(function(key) { | ||
+ | | ||
+ | const row = tbody.insertRow(); | ||
+ | row.innerHTML = '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | function populateDoctorsConfigTable() { | ||
+ | const tbody = document.getElementById(' | ||
+ | if (!tbody) return; | ||
+ | |||
+ | tbody.innerHTML = ''; | ||
+ | Object.keys(doctorsData).forEach(key => { | ||
+ | const doctor = doctorsData[key]; | ||
+ | const row = tbody.insertRow(); | ||
+ | row.innerHTML = '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '</ | ||
+ | '< | ||
+ | '< | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | 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 = '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '</ | ||
+ | '< | ||
+ | '< | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | function markConfigChanged(configType) { | ||
+ | let buttonId = ''; | ||
+ | let buttonText = ''; | ||
+ | |||
+ | switch(configType) { | ||
+ | case ' | ||
+ | buttonId = ' | ||
+ | buttonText = 'SALVA MODIFICHE ENTERALI'; | ||
+ | break; | ||
+ | case ' | ||
+ | buttonId = ' | ||
+ | buttonText = 'SALVA MODIFICHE PARENTERALI'; | ||
+ | break; | ||
+ | case ' | ||
+ | buttonId = ' | ||
+ | buttonText = 'SALVA MODIFICHE FORTIFICANTI'; | ||
+ | break; | ||
+ | case ' | ||
+ | buttonId = ' | ||
+ | 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; | ||
+ | case ' | ||
+ | buttonId = ' | ||
+ | buttonText = 'SALVA PARAMETRI SISTEMA'; | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | const button = document.getElementById(buttonId); | ||
+ | if (button) { | ||
+ | button.className = ' | ||
+ | | ||
} | } | ||
} | } | ||
- | function | + | |
- | if (!window.nptCalculationData) { | + | function |
- | | + | |
- | | + | |
+ | Object.keys(formulaData).forEach(key => { | ||
+ | const oldValues = Object.assign({}, | ||
+ | |||
+ | const proteinEl = document.getElementById(' | ||
+ | | ||
+ | formulaData[key].protein = parseFloat(proteinEl.value); | ||
+ | formulaData[key].carbs = parseFloat(document.getElementById(' | ||
+ | formulaData[key].lipids = parseFloat(document.getElementById(' | ||
+ | formulaData[key].sodium = parseFloat(document.getElementById(' | ||
+ | formulaData[key].potassium = parseFloat(document.getElementById(' | ||
+ | formulaData[key].calcium = parseFloat(document.getElementById(' | ||
+ | formulaData[key].phosphorus = parseFloat(document.getElementById(' | ||
+ | formulaData[key].magnesium = parseFloat(document.getElementById(' | ||
+ | formulaData[key].energy = parseFloat(document.getElementById(' | ||
+ | |||
+ | if (JSON.stringify(oldValues) | ||
+ | changesCount++; | ||
+ | } | ||
+ | | ||
+ | }); | ||
+ | |||
+ | const button = document.getElementById('updateEnteralBtn'); | ||
+ | if (button) { | ||
+ | | ||
+ | button.innerHTML = ' | ||
+ | setTimeout(() => { | ||
+ | button.className = ' | ||
+ | button.innerHTML = ' | ||
+ | }, 3000); | ||
} | } | ||
+ | } | ||
+ | |||
+ | function updateParenteralConfig() { | ||
+ | let changesCount = 0; | ||
| | ||
- | | + | |
- | document.getElementById(' | + | const oldValues |
- | document.getElementById(' | + | |
- | document.getElementById(' | + | const proteinEl = document.getElementById(' |
- | document.getElementById(' | + | if (proteinEl) { |
- | document.getElementById(' | + | parenteralConfig[key].protein |
- | document.getElementById(' | + | |
- | | + | parenteralConfig[key].lipids = parseFloat(document.getElementById('config_' |
+ | | ||
+ | parenteralConfig[key].potassium = parseFloat(document.getElementById('config_' | ||
+ | | ||
+ | parenteralConfig[key].phosphorus = parseFloat(document.getElementById('config_' | ||
+ | | ||
+ | parenteralConfig[key].energy = parseFloat(document.getElementById('config_' | ||
+ | | ||
+ | parenteralConfig[key].osmolarity = parseFloat(document.getElementById('config_' | ||
+ | |||
+ | if (JSON.stringify(oldValues) !== JSON.stringify(parenteralConfig[key])) { | ||
+ | changesCount++; | ||
+ | } | ||
+ | } | ||
+ | }); | ||
| | ||
- | | + | |
- | | + | |
- | | + | button.className = ' |
+ | button.innerHTML = 'PARENTERALI SALVATE | ||
+ | | ||
+ | button.className = ' | ||
+ | button.innerHTML = ' | ||
+ | }, 3000); | ||
+ | } | ||
} | } | ||
- | function | + | function |
- | | + | |
- | | + | const proteinEl |
- | var totalVolumeWithDeflector | + | |
- | var ratio = totalVolumeWithDeflector / data.totalVolume; | + | fortifierData.prenidina_fm85.protein = parseFloat(proteinEl.value); |
+ | fortifierData.prenidina_fm85.carbs | ||
+ | | ||
+ | | ||
+ | fortifierData.prenidina_fm85.potassium = parseFloat(document.getElementById(' | ||
+ | fortifierData.prenidina_fm85.calcium = parseFloat(document.getElementById(' | ||
+ | fortifierData.prenidina_fm85.phosphorus = parseFloat(document.getElementById(' | ||
+ | fortifierData.prenidina_fm85.magnesium = parseFloat(document.getElementById(' | ||
+ | fortifierData.prenidina_fm85.energy = parseFloat(document.getElementById(' | ||
+ | } | ||
| | ||
- | | + | |
- | | + | |
+ | button.className | ||
+ | button.innerHTML = ' | ||
+ | setTimeout(() => { | ||
+ | button.className = 'button'; | ||
+ | button.innerHTML = ' | ||
+ | }, 3000); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function updateDoctorsConfig() { | ||
+ | let changesCount = 0; | ||
| | ||
- | | + | |
- | (doctorsData[patientData.prescribingDoctor] ? doctorsData[patientData.prescribingDoctor].fullName | + | const oldValues = Object.assign({}, doctorsData[key]); |
+ | | ||
+ | const nameEl = document.getElementById(' | ||
+ | if (nameEl) { | ||
+ | const newName = nameEl.value.trim(); | ||
+ | const newSurname = document.getElementById(' | ||
+ | const newTitle = document.getElementById(' | ||
+ | |||
+ | | ||
+ | doctorsData[key].surname = newSurname; | ||
+ | | ||
+ | doctorsData[key].fullName | ||
+ | |||
+ | if (JSON.stringify(oldValues) !== JSON.stringify(doctorsData[key])) { | ||
+ | changesCount++; | ||
+ | } | ||
+ | } | ||
+ | }); | ||
| | ||
- | | + | |
- | | + | |
- | var estimatedOsmolarity = (finalConcentration * 55).toFixed(0); | + | |
| | ||
- | | + | |
+ | if (button) { | ||
+ | button.className | ||
+ | button.innerHTML = ' | ||
+ | setTimeout(() => { | ||
+ | button.className = 'button'; | ||
+ | button.innerHTML = ' | ||
+ | }, 3000); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function updateNursesConfig() { | ||
+ | let changesCount = 0; | ||
| | ||
- | // Header | + | |
- | | + | const oldValues = Object.assign({}, |
- | html += '< | + | |
- | html += '< | + | const nameEl = document.getElementById(' |
- | html += '<div style=" | + | 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); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function updateSystemConfig() { | ||
+ | const button = document.getElementById(' | ||
+ | if (button) { | ||
+ | button.className = ' | ||
+ | button.innerHTML = ' | ||
+ | setTimeout(() => { | ||
+ | button.className = ' | ||
+ | button.innerHTML = ' | ||
+ | }, 3000); | ||
+ | } | ||
+ | |||
+ | resetParenteralButton(); | ||
+ | } | ||
+ | |||
+ | // FUNZIONI CONFIGURAZIONE CLINICA AVANZATA (NUOVE) | ||
+ | function updateClinicalConfig() { | ||
+ | | ||
+ | clinicalConfig.phosphorusReq = parseFloat(document.getElementById(' | ||
+ | clinicalConfig.magnesiumReq = parseFloat(document.getElementById(' | ||
+ | clinicalConfig.maxGIR = parseFloat(document.getElementById(' | ||
+ | clinicalConfig.maxLipids = parseFloat(document.getElementById(' | ||
+ | clinicalConfig.maxProtein = parseFloat(document.getElementById(' | ||
+ | |||
+ | alert(' | ||
+ | '• Calcio standard: ' + clinicalConfig.calciumReq + ' mg/ | ||
+ | '• Fosforo standard: ' + clinicalConfig.phosphorusReq + ' mg/ | ||
+ | '• GIR massimo: ' + clinicalConfig.maxGIR + ' mg/ | ||
+ | '• Lipidi massimi: ' + clinicalConfig.maxLipids + ' g/ | ||
+ | } | ||
+ | |||
+ | function resetConfiguration() { | ||
+ | // Reset configurazione clinica | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | // Reset configurazione sistema | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | // Reset configurazione clinica globale | ||
+ | clinicalConfig = { | ||
+ | calciumReq: 160, | ||
+ | phosphorusReq: | ||
+ | magnesiumReq: | ||
+ | maxGIR: 12.0, | ||
+ | maxLipids: 3.0, | ||
+ | maxProtein: 4.5, | ||
+ | hospitalName: | ||
+ | departmentName: | ||
+ | directorName: | ||
+ | }; | ||
+ | |||
+ | alert(' | ||
+ | } | ||
+ | |||
+ | function saveConfiguration() { | ||
+ | const config = { | ||
+ | deflectorVolume: | ||
+ | hospitalName: | ||
+ | departmentName: | ||
+ | directorName: | ||
+ | autoSave: document.getElementById(' | ||
+ | decimalPlaces: | ||
+ | clinicalConfig: | ||
+ | doctorsData: | ||
+ | nursesData: nursesData, | ||
+ | pharmacistsData: | ||
+ | technicianData: | ||
+ | }; | ||
+ | |||
+ | // Aggiorna configurazione clinica | ||
+ | clinicalConfig.hospitalName = config.hospitalName; | ||
+ | clinicalConfig.departmentName = config.departmentName; | ||
+ | clinicalConfig.directorName = config.directorName; | ||
+ | |||
+ | // Simula salvataggio configurazione | ||
+ | window.savedConfig = config; | ||
+ | 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' | ||
+ | } | ||
+ | |||
+ | function generatePrescription() { | ||
+ | if (!window.residualNeeds || !patientData.currentWeight) { | ||
+ | alert(' | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | const currentDate = new Date().toLocaleDateString(' | ||
+ | const currentTime = new Date().toLocaleTimeString(' | ||
+ | const prescriptionPatientWeightKg = patientData.currentWeight / 1000; | ||
+ | const calc = window.nptCalculation; | ||
+ | |||
+ | if (!calc) { | ||
+ | alert(' | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | const birthDate = new Date(); | ||
+ | birthDate.setDate(birthDate.getDate() - patientData.daysOfLife); | ||
+ | |||
+ | // Genera ID prescrizione univoco (una sola volta per sessione) | ||
+ | if (!window.currentPrescriptionID) { | ||
+ | window.currentPrescriptionID = generatePreparationID(); | ||
+ | } | ||
+ | const prescriptionID = window.currentPrescriptionID; | ||
+ | |||
+ | // Recupera il medico attualmente selezionato | ||
+ | const currentPrescribingDoctor = document.getElementById(' | ||
+ | const doctorName = currentPrescribingDoctor && doctorsData[currentPrescribingDoctor] ? | ||
+ | doctorsData[currentPrescribingDoctor].fullName : | ||
+ | (patientData.prescribingDoctorName || 'Non specificato' | ||
+ | |||
+ | let html = '< | ||
+ | |||
+ | // INTESTAZIONE MEDICA (già OK secondo le tue indicazioni) | ||
+ | html += '< | ||
+ | |||
+ | // PARTE SINISTRA - INFO OSPEDALE | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '<h3 style=" | ||
+ | html += '<p style=" | ||
html += '</ | html += '</ | ||
- | html += '< | + | |
+ | // PARTE DESTRA - LOGO ASST | ||
+ | | ||
+ | html += '< | ||
html += '</ | html += '</ | ||
| | ||
- | // Info Paziente | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | html += '< |
- | html += '< | + | html += '<h2 style=" |
- | html += '< | + | html += '< |
- | html += '< | + | html += '</div>'; |
- | html += '< | + | |
- | html += '< | + | // INFO PAZIENTE (con cartella clinica e ID prescrizione) |
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | |||
+ | html += '< | ||
+ | html += '< | ||
+ | |||
+ | if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) { | ||
+ | const gestDays = patientData.gestationalDays || 0; | ||
+ | html += '< | ||
+ | if (patientData.postConceptionalAge && patientData.postConceptionalAge.format) { | ||
+ | html += '< | ||
+ | } | ||
+ | } | ||
+ | html += '< | ||
html += '</ | html += '</ | ||
html += '</ | html += '</ | ||
| | ||
- | // Composizione | + | // LISTA DEGLI APPORTI PER LA GIORNATA CORRENTE |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
| | ||
- | if (data.waterVolume | + | |
- | html += '< | + | |
+ | const formulaType = document.getElementById(' | ||
+ | const formulaName = formulaData[formulaType] ? formulaData[formulaType].name : ' | ||
+ | html += '< | ||
} | } | ||
- | if (data.glucose50Volume | + | |
- | html += '< | + | // Altri liquidi |
+ | | ||
+ | const fluidType = document.getElementById(' | ||
+ | let fluidName = 'Altri liquidi'; | ||
+ | switch(fluidType) { | ||
+ | case ' | ||
+ | case ' | ||
+ | case ' | ||
+ | case ' | ||
+ | } | ||
+ | html += '< | ||
} | } | ||
- | if (data.electrolyteAdditions.ca_gluconato > 0) { | + | |
- | html += '< | + | // Se nessun apporto enterale |
+ | | ||
+ | html += '< | ||
} | } | ||
- | | + | |
- | html += '< | + | html += '</ |
+ | html += '</ | ||
+ | |||
+ | // COMPOSIZIONE PARENTERALE | ||
+ | const deflectorVolume = parseInt(document.getElementById(' | ||
+ | const totalVolumeWithDeflector = calc.totalVolume + deflectorVolume; | ||
+ | const ratio = totalVolumeWithDeflector / calc.totalVolume; | ||
+ | |||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | | ||
+ | |||
+ | // Componenti nell' | ||
+ | html += '< | ||
+ | |||
+ | if (calc.neededGlucose > 0) { | ||
+ | html += '< | ||
} | } | ||
- | if (data.electrolyteAdditions.sodium_acetate | + | |
- | html += '< | + | |
+ | html += '< | ||
} | } | ||
- | if (data.electrolyteAdditions.kcl > 0) { | + | |
- | html += '<tr>< | + | html += '< |
+ | | ||
+ | html += '<td style=" | ||
+ | } else if (calc.electrolyteAdditions.sodium_acetate > 0) { | ||
+ | html += '< | ||
+ | } else { | ||
+ | html += '</ | ||
} | } | ||
- | if (data.electrolyteAdditions.mg_sulfate | + | |
- | html += '< | + | |
+ | html += '< | ||
} | } | ||
- | if (data.carnitineVolume | + | |
- | html += '< | + | |
+ | html += '< | ||
+ | } | ||
+ | |||
+ | html += '< | ||
+ | if (window.residualNeeds.carnitine > 0) { | ||
+ | const carnitineVolume = (window.residualNeeds.carnitine * prescriptionPatientWeightKg) / 100; | ||
+ | html += '< | ||
+ | } else { | ||
+ | html += '< | ||
} | } | ||
| | ||
- | html += '< | + | html += '< |
| | ||
- | if (data.electrolyteAdditions.esafosfina > 0) { | + | if (calc.electrolyteAdditions.esafosfina > 0) { |
- | html += '< | + | html += '< |
} | } | ||
- | if (data.residualNeeds.peditrace > 0) { | + | |
- | | + | |
- | html += '< | + | |
+ | html += '< | ||
+ | } else { | ||
+ | html += '< | ||
} | } | ||
- | if (data.residualNeeds.soluvit > 0) { | + | |
- | | + | |
- | html += '< | + | |
+ | html += '< | ||
+ | } else { | ||
+ | html += '< | ||
} | } | ||
- | if (data.residualNeeds.vitalipid > 0) { | + | |
- | | + | |
- | html += '< | + | |
+ | html += '< | ||
+ | } else { | ||
+ | html += '< | ||
} | } | ||
| | ||
- | html += '< | + | html += '< |
| | ||
- | // Totali | + | // TOTALI |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
html += '</ | html += '</ | ||
html += '</ | html += '</ | ||
| | ||
- | html += '< | + | |
- | html += 'NPT Calculator v2.0 - Foglio di Lavoro generato il ' + new Date().toLocaleString('it-IT'); | + | |
+ | html += '< | ||
+ | html += '<table style=" | ||
+ | |||
+ | // Calcola valori totali (enterali + parenterali) per kg | ||
+ | const totalLiquidsPerKg = window.residualNeeds.liquids; | ||
+ | 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 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 | ||
+ | |||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '</ | ||
html += '</ | html += '</ | ||
| | ||
html += '</ | html += '</ | ||
| | ||
- | | + | |
} | } | ||
- | function | + | function |
- | if (!window.nptCalculationData) { | + | if (!window.residualNeeds || !patientData.currentWeight) { |
- | alert(' | + | alert(' |
return; | return; | ||
} | } | ||
| | ||
- | | + | |
- | document.getElementById('nptFinalReport' | + | |
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
- | window.currentActiveReport = ' | + | |
| | ||
- | | + | |
- | generateBtn.innerHTML = ' | + | alert('Prima calcolare la NPT nel TAB 4'); |
- | generateBtn.className = ' | + | |
- | } | + | |
- | + | ||
- | function generateFinalReportHTML() { | + | |
- | var data = window.nptCalculationData; | + | |
- | var deflectorVolume = parseInt(document.getElementById('deflectorVolume').value) || 30; | + | |
- | var totalVolumeWithDeflector = data.totalVolume + deflectorVolume; | + | |
- | | + | |
| | ||
- | | + | |
- | | + | |
| | ||
- | var medicalRecord = patientData.medicalRecord || 'N/A'; | + | // Recupera il medico attualmente selezionato |
- | var birthDate | + | const currentPrescribingDoctor |
- | new Date(new Date(patientData.prescriptionDate).getTime() - (patientData.daysOfLife * 24 * 60 * 60 * 1000)).toLocaleDateString('it-IT' | + | |
- | | + | |
- | var doctorName = patientData.prescribingDoctor ? | + | (patientData.prescribingDoctorName || 'Medico non specificato' |
- | (doctorsData[patientData.prescribingDoctor] ? doctorsData[patientData.prescribingDoctor].fullName : 'N/A' | + | |
| | ||
- | | + | |
- | var finalConcentration | + | // Usa lo stesso ID prescrizione della sessione |
- | var estimatedOsmolarity | + | if (!window.currentPrescriptionID) { |
+ | window.currentPrescriptionID = generatePreparationID(); | ||
+ | } | ||
+ | const worksheetPreparationID | ||
+ | |||
+ | let html = '< | ||
| | ||
- | | + | |
+ | | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '</ | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '</ | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '</ | ||
+ | html += '</ | ||
+ | html += '</ | ||
| | ||
- | // INTESTAZIONE | + | // TITOLO E DATA |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | html += '<h2 style=" |
- | html += '<div style=" | + | |
html += '</ | html += '</ | ||
- | html += '< | ||
html += '</ | html += '</ | ||
| | ||
- | html += '<div class="report-title"> | + | html += '<h3 style="margin: 20px 0 10px 0; font-size: 14px;">FOGLIO DI LAVORO</h3>'; |
- | html += '< | + | |
| | ||
// INFO PAZIENTE | // INFO PAZIENTE | ||
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '< | + | if (worksheetPreparationID) { |
- | html += '< | + | html += '< |
- | html += '< | + | } |
- | html += '< | + | html += '< |
+ | html += '< | ||
+ | html += '< | ||
+ | |||
+ | if (patientData.gestationalWeeks && patientData.gestationalWeeks > 0) { | ||
+ | const gestDays = patientData.gestationalDays || 0; | ||
+ | html += '< | ||
+ | if (patientData.postConceptionalAge && patientData.postConceptionalAge.format) { | ||
+ | html += '< | ||
+ | } | ||
+ | } | ||
+ | html += '< | ||
html += '</ | html += '</ | ||
html += '</ | html += '</ | ||
| | ||
- | // LISTA APPORTI ENTERALI | + | // COMPOSIZIONE PARENTERALE - FORMATO FOGLIO DI LAVORO |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | | + | |
- | var formulaName | + | html += '< |
- | var formulaDisplayName | + | |
- | html += '<table class="report-table">'; | + | // Ordine esatto come nel PDF del foglio di lavoro |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '</table>'; | + | html += '< |
- | | + | |
- | | + | |
- | html += '< | + | html += '< |
- | html += '< | + | html += '< |
- | html += '</ | + | |
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '<tr>< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | |||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | | ||
+ | html += '</ | ||
+ | |||
+ | html += '</ | ||
+ | |||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | function generateLabel() { | ||
+ | if (!window.residualNeeds || !patientData.currentWeight) { | ||
+ | alert(' | ||
+ | return; | ||
} | } | ||
+ | | ||
+ | const currentDate = new Date().toLocaleDateString(' | ||
+ | const currentTime = new Date().toLocaleTimeString(' | ||
+ | const calc = window.nptCalculation; | ||
+ | | ||
+ | if (!calc) { | ||
+ | alert(' | ||
+ | return; | ||
+ | } | ||
+ | | ||
+ | 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 || ' | ||
+ | | ||
+ | // Usa lo stesso ID prescrizione della sessione | ||
+ | if (!window.currentPrescriptionID) { | ||
+ | window.currentPrescriptionID = generatePreparationID(); | ||
+ | } | ||
+ | const labelPreparationID = window.currentPrescriptionID; | ||
+ | | ||
+ | let html = '< | ||
+ | | ||
+ | // INTESTAZIONE COMPATTA PER ETICHETTA | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
html += '</ | html += '</ | ||
| | ||
- | // COMPOSIZIONE PARENTERALE (identica al foglio di lavoro) | ||
- | html += '< | ||
- | html += '< | ||
- | html += '< | ||
- | html += '< | ||
| | ||
- | // Componenti con ordine identico al foglio di lavoro | + | // SEZIONE IDENTIFICAZIONE PAZIENTE - GRANDE E VISIBILE |
- | | + | |
- | html += '<tr>< | + | html += '<h2 style="margin: 0 0 10px 0; font-size: 18px; color: #d32f2f;">👤 IDENTIFICAZIONE PAZIENTE</h2>'; |
+ | |||
+ | // CODICE A BARRE per cartella clinica | ||
+ | if (patientData.medicalRecord && patientData.medicalRecord.trim() !== '' | ||
+ | html += '<div style=" | ||
+ | html += '<canvas id=" | ||
+ | html += '<div style=" | ||
+ | html += '</div>'; | ||
} | } | ||
- | if (data.glucose50Volume | + | |
- | html += '< | + | html += '< |
+ | html += '< | ||
+ | |||
+ | if (labelPreparationID) { | ||
+ | html += '< | ||
} | } | ||
- | | + | |
- | html += '< | + | html += '< |
+ | html += '< | ||
+ | |||
+ | | ||
+ | const gestDays = patientData.gestationalDays || 0; | ||
+ | html += '< | ||
+ | if (patientData.postConceptionalAge && patientData.postConceptionalAge.format) { | ||
+ | html += '< | ||
+ | } | ||
} | } | ||
- | if (data.electrolyteAdditions.nacl | + | |
- | html += '< | + | html += '< |
+ | html += '</ | ||
+ | html += '</ | ||
+ | |||
+ | // SEZIONE PRESCRIZIONE | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | | ||
+ | html += '< | ||
+ | html += '< | ||
+ | html += '< | ||
+ | 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 (data.electrolyteAdditions.mg_sulfate | + | if (calc.electrolyteAdditions.esafosfina |
- | html += '< | + | html += '< |
} | } | ||
- | | + | |
- | html += '< | + | html += '< |
+ | html += '</ | ||
+ | html += '</ | ||
+ | |||
+ | html += '</ | ||
+ | |||
+ | 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: | ||
+ | height: 60, | ||
+ | margin: 5, | ||
+ | background: "# | ||
+ | lineColor: "# | ||
+ | }); | ||
+ | console.log('✅ Codice a barre generato per cartella:', | ||
+ | } catch (error) { | ||
+ | console.error(' | ||
+ | | ||
+ | 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('barcodeCanvas' | ||
+ | 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 COMPLETA | ||
+ | function generatePDF(type) { | ||
+ | if (!window.residualNeeds || !patientData.currentWeight) { | ||
+ | alert(' | ||
+ | return; | ||
} | } | ||
- | if (data.proteinVolume > 0) { | + | |
- | html += '< | + | const { jsPDF } = window.jspdf; |
+ | const doc = new jsPDF(); | ||
+ | |||
+ | | ||
+ | doc.setFontSize(10); | ||
+ | doc.text(clinicalConfig.departmentName, | ||
+ | doc.text('Direttore: | ||
+ | |||
+ | // Logo ASST (posizionamento approssimativo) | ||
+ | doc.text(clinicalConfig.hospitalName, | ||
+ | |||
+ | const currentDate = new Date().toLocaleDateString(' | ||
+ | doc.text(' | ||
+ | |||
+ | if (type === 'foglio_lavoro') { | ||
+ | generateWorksheetPDFContent(doc); | ||
+ | } else if (type === ' | ||
+ | generatePrescriptionPDFContent(doc); | ||
+ | } else if (type === ' | ||
+ | generateLabelPDFContent(doc); | ||
} | } | ||
- | | + | |
- | | + | // Salva il PDF |
+ | let fileName = ''; | ||
+ | switch(type) { | ||
+ | | ||
+ | fileName | ||
+ | break; | ||
+ | case ' | ||
+ | fileName = ' | ||
+ | break; | ||
+ | case ' | ||
+ | fileName = ' | ||
+ | break; | ||
+ | default: | ||
+ | fileName = ' | ||
} | } | ||
- | | + | |
- | var peditraceVolume | + | doc.save(fileName); |
- | html += '< | + | } |
+ | // CONTENUTO PDF PRESCRIZIONE MEDICA | ||
+ | function generatePrescriptionPDFContent(doc) { | ||
+ | const currentDate | ||
+ | const calc = window.nptCalculation; | ||
+ | const prescriptionPatientWeightKg = patientData.currentWeight / 1000; | ||
+ | |||
+ | // Recupera il medico attualmente selezionato | ||
+ | const currentPrescribingDoctor | ||
+ | const doctorName = currentPrescribingDoctor && doctorsData[currentPrescribingDoctor] ? | ||
+ | doctorsData[currentPrescribingDoctor].fullName : | ||
+ | | ||
+ | |||
+ | const birthDate = new Date(); | ||
+ | birthDate.setDate(birthDate.getDate() - patientData.daysOfLife); | ||
+ | |||
+ | if (!window.currentPrescriptionID) { | ||
+ | window.currentPrescriptionID = generatePreparationID(); | ||
} | } | ||
- | | + | |
- | var soluvitVolume | + | |
- | | + | let yPos = 50; |
+ | |||
+ | doc.setFontSize(12); | ||
+ | | ||
+ | yPos += 20; | ||
+ | |||
+ | doc.setFontSize(10); | ||
+ | doc.text(' | ||
+ | | ||
+ | doc.text('Peso: ' + patientData.currentWeight | ||
+ | yPos += 10; | ||
+ | doc.text(' | ||
+ | yPos += 10; | ||
+ | doc.text(' | ||
+ | yPos += 20; | ||
+ | |||
+ | if (prescriptionID) { | ||
+ | doc.text('ID Prescrizione: | ||
+ | yPos += 10; | ||
} | } | ||
- | | + | |
- | var vitalipidVolume | + | // COMPOSIZIONE NPT |
- | | + | doc.text(' |
+ | yPos += 15; | ||
+ | |||
+ | doc.text(' | ||
+ | | ||
+ | doc.text('GIR: ' + calc.gir.toFixed(1) + ' | ||
+ | yPos += 10; | ||
+ | doc.text(' | ||
+ | yPos += 10; | ||
+ | |||
+ | if (calc.osmolarityData) { | ||
+ | doc.text(' | ||
+ | yPos += 10; | ||
} | } | ||
- | // Gestione valore negativo per Intralipid | ||
- | var displayLipidVolume = data.lipidVolume < 0 ? 0 : data.lipidVolume; | ||
- | html += '< | ||
| | ||
- | // Totali | + | // Componenti principali |
- | | + | |
- | | + | doc.text('COMPONENTI PRINCIPALI:', 20, yPos); |
- | html += '< | + | |
- | html += '< | + | |
- | html += '</ | + | |
- | html += '</ | + | |
| | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
| | ||
- | | + | |
- | | + | |
- | | + | doc.text(' |
+ | | ||
+ | doc.text('Acqua Bidistillata: | ||
+ | yPos += 15; | ||
| | ||
- | | + | |
- | | + | const totalProteinPerKg |
- | | + | |
- | | + | |
- | var totalPhosphorus = (enteralData ? enteralData.phosphorus * data.currentWeightKg / 1000 : 0) + (data.residualNeeds.phosphorus * data.currentWeightKg / 1000); | + | |
- | var totalSodium = (enteralData ? enteralData.sodium * data.currentWeightKg / 1000 : 0) + (data.residualNeeds.sodium * data.currentWeightKg / 1000); | + | |
- | var totalPotassium = (enteralData ? enteralData.potassium * data.currentWeightKg / 1000 : 0) + (data.residualNeeds.potassium * data.currentWeightKg / 1000); | + | |
- | var totalMagnesium = (enteralData ? enteralData.magnesium * data.currentWeightKg / 1000 : 0) + (data.residualNeeds.magnesium * data.currentWeightKg / 1000); | + | |
- | var totalCarnitine = data.residualNeeds.carnitine * data.currentWeightKg / 1000; | + | |
| | ||
- | | + | |
- | | + | yPos += 15; |
- | | + | doc.text(' |
+ | | ||
+ | doc.text(' | ||
+ | | ||
+ | doc.text(' | ||
+ | yPos += 8; | ||
+ | doc.text(' | ||
+ | } | ||
+ | |||
+ | // CONTENUTO PDF FOGLIO DI LAVORO | ||
+ | function generateWorksheetPDFContent(doc) { | ||
+ | const calc = window.nptCalculation; | ||
| | ||
- | | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '< | + | |
- | html += '</ | + | |
- | html += '</ | + | |
| | ||
- | | + | |
- | | + | |
- | | + | |
| | ||
- | | + | |
+ | doc.text(' | ||
+ | yPos += 10; | ||
+ | doc.text(' | ||
+ | yPos += 10; | ||
+ | doc.text(' | ||
+ | yPos += 20; | ||
| | ||
- | | + | |
+ | 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(' | ||
+ | } | ||
+ | } | ||
} | } | ||
- | function | + | // CONTENUTO PDF ETICHETTA SACCA |
- | | + | function |
- | alert('Prima genera un report!'); | + | |
- | | + | 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('prescribingDoctor').value; | ||
+ | const doctorName = currentPrescribingDoctor && doctorsData[currentPrescribingDoctor] ? | ||
+ | doctorsData[currentPrescribingDoctor].fullName : | ||
+ | (patientData.prescribingDoctorName || ' | ||
+ | |||
+ | if (!window.currentPrescriptionID) { | ||
+ | | ||
} | } | ||
+ | const labelPreparationID = window.currentPrescriptionID; | ||
| | ||
- | | + | |
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
| | ||
- | | + | |
- | 'Foglio di Lavoro NPT' : ' | + | doc.setFont(undefined, |
+ | | ||
+ | yPos += 20; | ||
| | ||
- | // Crea una nuova finestra per la stampa | + | // IDENTIFICAZIONE PAZIENTE |
- | | + | |
+ | doc.setFont(undefined, | ||
+ | doc.text('IDENTIFICAZIONE PAZIENTE', | ||
+ | yPos += 15; | ||
| | ||
- | if (!printWindow) { | + | |
- | alert(' | + | 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 | ||
+ | function showAddEnteralForm() { | ||
+ | alert(' | ||
+ | } | ||
+ | |||
+ | function showAddFortifierForm() { | ||
+ | alert(' | ||
+ | } | ||
+ | |||
+ | function showAddParenteralForm() { | ||
+ | alert(' | ||
+ | } | ||
+ | |||
+ | |||
+ | function showAddDoctorForm() { | ||
+ | const name = prompt(' | ||
+ | | ||
+ | |||
+ | 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] = { | ||
+ | | ||
+ | surname: surname.trim(), | ||
+ | title: title.trim(), | ||
+ | fullName: fullName | ||
+ | }; | ||
+ | |||
+ | populateDoctorsConfigTable(); | ||
+ | updateDoctorsDropdown(); | ||
+ | | ||
+ | } | ||
+ | |||
+ | 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) { | ||
+ | if (confirm(' | ||
+ | alert(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function removeParenteralComponent(key) { | ||
+ | if (confirm(' | ||
+ | alert(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function removeFortifier(key) { | ||
+ | if (confirm(' | ||
+ | alert(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function removeDoctor(key) { | ||
+ | if (confirm(' | ||
+ | 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; | return; | ||
} | } | ||
| | ||
- | | + | |
- | var htmlContent = '<!DOCTYPE html>'; | + | |
- | | + | |
- | htmlContent += '< | + | |
- | htmlContent += '< | + | |
- | htmlContent += '< | + | |
- | htmlContent += 'body { margin: 0; padding: 15px; font-family: Arial, sans-serif; }'; | + | |
- | htmlContent += document.querySelector(' | + | |
- | | + | |
- | | + | |
- | htmlContent += reportContent; | + | |
- | htmlContent += '</ | + | |
| | ||
- | // Scrivi il contenuto nella nuova finestra | + | // Validazione completata |
- | | + | document.getElementById(' |
- | | + | document.getElementById(' |
- | | + | document.getElementById(' |
| | ||
- | // Avvia la stampa dopo un breve ritardo | + | // Mostra status validazione |
- | | + | |
- | | + | const validationHtml = '< |
- | | + | '< |
- | | + | '< |
+ | '< | ||
+ | | ||
+ | '</ | ||
+ | |||
+ | document.getElementById(' | ||
+ | | ||
+ | | ||
+ | // Abilita fase 2 - Allestimento | ||
+ | enablePreparationPhase(); | ||
+ | |||
+ | alert(' | ||
} | } | ||
- | function | + | // Abilita la fase di allestimento tecnici |
- | if (!window.currentActiveReport | + | function |
- | alert(' | + | 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 | ||
+ | alert(' | ||
return; | return; | ||
} | } | ||
| | ||
- | | + | |
- | 'Foglio di Lavoro NPT' | + | |
+ | return; | ||
+ | } | ||
| | ||
- | // Genera nome file suggerito | + | // Allestimento confermato |
- | | + | |
- | | + | |
- | | + | |
- | var suggestedFileName = ' | + | |
| | ||
- | // Feedback visivo immediato | + | // Mostra status preparazione |
- | | + | |
- | | + | |
- | | + | |
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '</ | ||
| | ||
- | | + | |
- | | + | |
- | savePdfBtn.disabled = true; | + | |
| | ||
- | // Mostra istruzioni dettagliate | + | // Abilita download JSON |
- | var instructions | + | document.getElementById(' |
- | | + | document.getElementById('downloadBtn' |
- | | + | |
- | | + | |
- | | + | document.getElementById('lockPrescriptionBtn').disabled = false; |
- | | + | |
- | instructions | + | |
- | | + | |
+ | | ||
+ | if (!window.currentPrescriptionID) { | ||
+ | window.currentPrescriptionID | ||
+ | } | ||
+ | window.lastPreparationID = window.currentPrescriptionID; | ||
+ | |||
+ | console.log('ID Preparazione assegnato:', | ||
+ | |||
+ | |||
+ | |||
+ | alert(' | ||
+ | | ||
+ | |||
+ | // ===================================================== | ||
+ | // SISTEMA BLOCCO PRESCRIZIONE | ||
+ | // ===================================================== | ||
+ | |||
+ | // Variabile globale per stato blocco | ||
+ | window.prescriptionLocked = false; | ||
+ | |||
+ | // Funzione per bloccare la prescrizione | ||
+ | function lockPrescription() { | ||
+ | const confirmed = confirm( | ||
+ | | ||
+ | | ||
+ | | ||
+ | '• La preparazione sarà considerata FINALIZZATA\n' | ||
+ | ' | ||
+ | | ||
+ | ); | ||
| | ||
- | if (confirm(instructions)) { | + | if (!confirmed) { |
- | // Prova ad aprire la finestra | + | return; |
- | | + | } |
- | var reportContent | + | |
- | document.getElementById(' | + | // Blocca la prescrizione |
- | document.getElementById(' | + | 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) { | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | |||
+ | // 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 | ||
+ | const bannerHtml | ||
+ | | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '< | ||
+ | '</ | ||
+ | |||
+ | | ||
+ | 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('.locked-overlay')) { | ||
+ | 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 | ||
| | ||
- | | + | |
- | + | tabElement.appendChild(overlay); | |
- | if (!printWindow) { | + | } |
- | // Popup bloccato | + | }); |
- | | + | } |
- | | + | |
- | + | // Funzione per iniziare nuova prescrizione | |
- | | + | function startNewPrescription() { |
- | alert('⚠️ POPUP BLOCCATO!\n\nPer salvare come PDF:\n1. Abilita i popup per questo sito\n2. Riprova a cliccare | + | const confirmed = confirm( |
- | | + | '📋 NUOVA PRESCRIZIONE NPT\n\n' |
- | | + | ' |
- | | + | '• Resetterà tutti i dati correnti\n' |
- | }, 1000); | + | '• Permetterà di iniziare una nuova prescrizione\n' |
- | return; | + | '• 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.residualNeeds = null; | ||
+ | window.nptCalculation = null; | ||
+ | window.monthlyPreparations = []; | ||
+ | window.currentPrescriptionID = null; | ||
+ | patientData = {}; | ||
+ | enteralData = null; | ||
+ | currentRequirements = null; | ||
+ | |||
+ | // Riabilita tutti gli input | ||
+ | enableAllInputs(); | ||
+ | |||
+ | // Reset tutti i form | ||
+ | resetAllForms(); | ||
+ | |||
+ | // Nascondi banner | ||
+ | document.getElementById('prescriptionStatusBanner').style.display = ' | ||
+ | |||
+ | // 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('# | ||
+ | '#enteral input, #enteral select, #enteral button, ' | ||
+ | '# | ||
+ | '# | ||
+ | |||
+ | 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(' | ||
+ | | ||
+ | | ||
+ | phaseBtn.innerHTML = ' | ||
+ | phaseBtn.disabled = false; | ||
+ | } | ||
+ | |||
+ | | ||
+ | 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 = 'Calcola Apporti Enterali'; | ||
+ | } | ||
+ | |||
+ | // Nascondi risultati enterali | ||
+ | const enteralResults = document.getElementById(' | ||
+ | if (enteralResults) { | ||
+ | enteralResults.classList.add(' | ||
+ | } | ||
+ | |||
+ | // Reset TAB 3 - Fabbisogni | ||
+ | document.getElementById(' | ||
+ | | ||
+ | | ||
+ | |||
+ | // 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 | ||
+ | const nutritionFields = [ | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ]; | ||
+ | |||
+ | nutritionFields.forEach(fieldId => { | ||
+ | const field = document.getElementById(fieldId); | ||
+ | if (field) { | ||
+ | field.value = '0'; | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | // 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(' | ||
+ | | ||
+ | |||
+ | 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(' | ||
+ | |||
+ | // 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 + ' | ||
+ | |||
+ | | ||
+ | } | ||
+ | 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 + ' | ||
} | } | ||
- | | + | }, |
- | // Costruisci il contenuto HTML completo | + | |
- | var htmlContent = '< | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | htmlContent += 'body { margin: 0; padding: 15px; font-family: | + | |
- | | + | |
- | | + | |
- | | + | }, |
- | | + | |
- | | + | // COMPOSIZIONE NPT |
- | htmlContent += reportContent; | + | npt: { |
- | htmlContent += '</body></ | + | |
- | + | | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | + | | |
- | | + | |
- | savePdfBtn.innerHTML = '✅ Finestra Aperta!'; | + | }, |
- | | + | |
- | | + | |
- | // Avvia la stampa dopo un breve ritardo | + | |
- | setTimeout(function() { | + | |
- | printWindow.focus(); | + | |
- | printWindow.print(); | + | |
- | + | | |
- | // Mostra istruzioni nella finestra di stampa | + | |
- | | + | }, |
- | | + | |
- | savePdfBtn.style.backgroundColor = '# | + | // PERSONALE |
- | }, 1000); | + | personale: { |
- | | + | |
- | | + | |
- | // Ripristina il pulsante dopo 5 secondi | + | |
- | setTimeout(function() { | + | |
- | | + | }, |
- | savePdfBtn.style.backgroundColor = originalColor; | + | |
- | | + | // METADATA |
- | }, 5000); | + | |
- | + | | |
- | | + | dataCalcolo: |
- | | + | |
- | | + | |
- | | + | |
- | + | ||
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
- | | + | |
} | } | ||
- | } else { | + | }; |
- | // Utente ha annullato | + | |
- | | + | return preparationData; |
- | | + | } |
- | | + | |
+ | function downloadPreparationJSON() { | ||
+ | console.log(' | ||
+ | |||
+ | const preparationData = createPreparationJSON(); | ||
+ | if (!preparationData) | ||
+ | | ||
+ | } | ||
+ | |||
+ | try { | ||
+ | | ||
+ | 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); | ||
+ | | ||
+ | a.href | ||
+ | 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(' | ||
} | } | ||
} | } | ||
- | function | + | |
- | if (!window.currentActiveReport | + | // ===================================================== |
- | alert(' | + | // SISTEMA ARCHIVIAZIONE MENSILE EXCEL |
+ | // ===================================================== | ||
+ | |||
+ | // Variabile globale per i dati mensili | ||
+ | window.monthlyPreparations = []; | ||
+ | |||
+ | // Funzione per inizializzare il mese corrente | ||
+ | function | ||
+ | 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; | return; | ||
} | } | ||
| | ||
- | | + | |
- | document.getElementById(' | + | |
- | document.getElementById(' | + | |
| | ||
- | | + | |
- | ' | + | const totalFiles = files.length; |
| | ||
- | | + | |
- | var dateStr | + | Array.from(files).forEach((file, |
- | var medicalRecord = patientData.medicalRecord || 'SENZA_CARTELLA'; | + | const reader |
- | var fileName = ' | + | |
+ | reader.onload | ||
+ | try { | ||
+ | const jsonData = JSON.parse(e.target.result); | ||
+ | |||
+ | // Valida che sia un file NPT valido | ||
+ | if (validateNPTJson(jsonData)) { | ||
+ | window.monthlyPreparations.push(jsonData); | ||
+ | } else { | ||
+ | console.warn('File non valido ignorato:', | ||
+ | } | ||
+ | |||
+ | processedFiles++; | ||
+ | |||
+ | | ||
+ | if (processedFiles === totalFiles) { | ||
+ | showMonthlyPreview(); | ||
+ | } | ||
+ | |||
+ | } catch (error) { | ||
+ | console.error('Errore parsing JSON:', file.name, error); | ||
+ | | ||
+ | |||
+ | if (processedFiles | ||
+ | showMonthlyPreview(); | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | reader.readAsText(file); | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | // Funzione di validazione JSON NPT | ||
+ | function validateNPTJson(data) { | ||
+ | return data && | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | // Funzione per mostrare l'anteprima | ||
+ | function showMonthlyPreview() { | ||
+ | const statsDiv = document.getElementById('monthlyStats'); | ||
+ | const selectedMonth = document.getElementById('selectedMonth').value; | ||
+ | const monthName = new Date(selectedMonth | ||
+ | year: 'numeric', | ||
+ | month: ' | ||
+ | }); | ||
| | ||
- | | + | |
- | 'body { margin: 0; padding: 20px; font-family: | + | |
- | document.querySelector(' | + | |
- | ' | + | return; |
- | | + | } |
- | '</ | + | |
- | | + | |
- | | + | |
- | '< | + | |
| | ||
- | | + | // Calcola statistiche |
- | | + | |
- | var a = document.createElement(' | + | |
- | a.href = url; | + | |
- | a.download = fileName; | + | |
- | document.body.appendChild(a); | + | |
- | a.click(); | + | |
- | document.body.removeChild(a); | + | |
- | URL.revokeObjectURL(url); | + | |
| | ||
- | | + | |
- | | + | html += '< |
- | | + | html += '< |
- | | + | |
+ | | ||
+ | html += '< | ||
+ | | ||
+ | html += '</ | ||
| | ||
- | | + | |
- | | + | html += '< |
- | | + | window.monthlyPreparations.forEach(prep => { |
- | | + | |
+ | }); | ||
+ | html += '</ | ||
+ | |||
+ | statsDiv.innerHTML = html; | ||
+ | | ||
+ | | ||
+ | // Abilita il pulsante Excel | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
} | } | ||
- | function | + | // Funzione per calcolare statistiche mensili |
- | | + | function |
- | | + | |
- | | + | |
+ | | ||
+ | const totalVolume = preparations.reduce((sum, | ||
| | ||
- | | + | |
- | | + | uniquePatients: |
- | | + | averageWeight: |
+ | averageGIR: totalGIR / preparations.length, | ||
+ | averageVolume: | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | // Funzione principale per generare Excel mensile | ||
+ | function | ||
+ | if (!window.monthlyPreparations || window.monthlyPreparations.length === 0) { | ||
+ | | ||
+ | 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(' | ||
+ | | ||
+ | |||
+ | 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); | }, 3000); | ||
} | } | ||
+ | // Aggiorna la funzione showTab esistente per gestire il knowledge base | ||
+ | function showTabOriginal(tabId) { | ||
+ | // Funzione originale già esistente - non modificare | ||
+ | // Questa è solo per referenza | ||
+ | } | ||
+ | |||
+ | // INIZIALIZZAZIONE | ||
+ | document.addEventListener(' | ||
+ | console.log(' | ||
+ | | ||
+ | // Imposta la data odierna come default | ||
+ | const today = new Date().toISOString().split(' | ||
+ | document.getElementById(' | ||
+ | | ||
+ | // Configura il campo cartella clinica | ||
+ | setupMedicalRecordField(); | ||
+ | | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | }); | ||
+ | | ||
+ | // Event listeners per resettare Fabbisogni e NPT quando si modificano i valori manualmente | ||
+ | const requirementFields = [ | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ]; | ||
+ | | ||
+ | requirementFields.forEach(fieldId => { | ||
+ | const field = document.getElementById(fieldId); | ||
+ | if (field) { | ||
+ | field.addEventListener(' | ||
+ | resetNutritionButton(); | ||
+ | }); | ||
+ | field.addEventListener(' | ||
+ | resetNutritionButton(); | ||
+ | }); | ||
+ | } | ||
+ | }); | ||
+ | | ||
+ | // Event listener per il tipo di sodio | ||
+ | const sodiumTypeSelect = document.getElementById(' | ||
+ | if (sodiumTypeSelect) { | ||
+ | sodiumTypeSelect.addEventListener(' | ||
+ | updateSodiumChoice(); | ||
+ | updateSodiumRecommendation(); | ||
+ | }); | ||
+ | } | ||
+ | | ||
+ | // Event listener per il volume del deflussore | ||
+ | const deflectorVolumeInput = document.getElementById(' | ||
+ | if (deflectorVolumeInput) { | ||
+ | deflectorVolumeInput.addEventListener(' | ||
+ | resetParenteralButton(); | ||
+ | }); | ||
+ | } | ||
+ | | ||
+ | // Inizializza configurazione clinica avanzata | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | updateFortifierOptions(); | ||
+ | // Inizializza tutte le dropdown e tabelle | ||
+ | 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(' | ||
+ | }); | ||
</ | </ | ||
+ | |||
</ | </ | ||
</ | </ |