Differenze

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

Link a questa pagina di confronto

Prossima revisione
Revisione precedente
dashboard:monitoraggio_terapia_antibiotica_-_dot [2025/09/27 06:51] – creata neoadmindashboard:monitoraggio_terapia_antibiotica_-_dot [2025/09/27 22:51] (versione attuale) neoadmin
Linea 1: Linea 1:
-<html> + [[https://docuneo.org/app_est/control_chart_final%20(2).html]]
-<head> +
-    <meta charset="UTF-8"> +
-    <meta name="viewport" content="width=device-width, initial-scale=1.0"> +
-    <title>📊 Control Chart - DOT System</title> +
-    <script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script> +
-    <style> +
-        body {  +
-            font-family: Arial, sans-serif;  +
-            margin: 0;  +
-            padding: 20px;  +
-            background: #f5f5f5;  +
-        } +
-        .container {  +
-            max-width: 1200px;  +
-            margin: 0 auto;  +
-            background: white;  +
-            border-radius: 10px;  +
-            padding: 20px; +
-            box-shadow: 0 4px 6px rgba(0,0,0,0.1); +
-        } +
-        .header {  +
-            text-align: center;  +
-            padding: 20px;  +
-            background: #2c3e50;  +
-            color: white;  +
-            border-radius: 8px; +
-            margin-bottom: 20px; +
-        } +
-        .header.dot { background: #9b59b6; } +
-        .header.manual { background: #2c3e50; } +
-         +
-        .sample-buttons {  +
-            display: grid;  +
-            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));  +
-            gap: 10px;  +
-            margin: 20px 0; +
-        } +
-        .sample-btn {  +
-            padding: 15px;  +
-            border: none;  +
-            border-radius: 6px;  +
-            color: white;  +
-            cursor: pointer; +
-            font-weight: bold; +
-        } +
-        .btn-dot { background: #9b59b6; } +
-         +
-        /* GRAFICO IN EVIDENZA */ +
-        .chart-container {  +
-            margin: 20px 0;  +
-            padding: 20px; +
-            background: #fff; +
-            border-radius: 8px; +
-            border: 3px solid #007bff; +
-            box-shadow: 0 8px 16px rgba(0,123,255,0.2); +
-        } +
-        .chart-wrapper {  +
-            position: relative;  +
-            height: 500px;  +
-            margin: 20px 0; +
-        } +
-         +
-        .stats {  +
-            display: grid;  +
-            grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));  +
-            gap: 15px;  +
-            margin: 20px 0; +
-        } +
-        .stat {  +
-            text-align: center;  +
-            padding: 15px;  +
-            background: #f8f9fa;  +
-            border-radius: 6px; +
-        } +
-        .stat-value {  +
-            font-size: 1.5rem;  +
-            font-weight: bold;  +
-            color: #2c3e50; +
-        } +
-        .stat-label {  +
-            font-size: 0.9rem;  +
-            color: #666;  +
-            margin-top: 5px; +
-        } +
-         +
-        /* SEZIONI COLLASSABILI */ +
-        .collapsible-section { +
-            margin: 15px 0; +
-            border: 1px solid #ddd; +
-            border-radius: 8px; +
-            overflow: hidden; +
-        } +
-        .collapsible-header { +
-            background: #f8f9fa; +
-            padding: 15px 20px; +
-            cursor: pointer; +
-            display: flex; +
-            justify-content: space-between; +
-            align-items: center; +
-            font-weight: bold; +
-            color: #2c3e50; +
-            transition: background 0.3s; +
-        } +
-        .collapsible-header:hover { +
-            background: #e9ecef; +
-        } +
-        .collapsible-header .toggle-icon { +
-            font-size: 18px; +
-            transition: transform 0.3s; +
-        } +
-        .collapsible-header.collapsed .toggle-icon { +
-            transform: rotate(-90deg); +
-        } +
-        .collapsible-content { +
-            padding: 20px; +
-            background: white; +
-            max-height: 2000px; +
-            transition: max-height 0.3s ease-out, padding 0.3s; +
-            overflow: hidden; +
-        } +
-        .collapsible-content.collapsed { +
-            max-height: 0; +
-            padding: 0 20px; +
-        } +
-         +
-        .alert {  +
-            padding: 15px;  +
-            border-radius: 6px;  +
-            margin: 15px 0; +
-            border-left: 4px solid; +
-        } +
-        .alert-success { background: #d4edda; border-color: #28a745; color: #155724; } +
-        .alert-info { background: #d1ecf1; border-color: #17a2b8; color: #0c5460; } +
-        .alert-danger { background: #f8d7da; border-color: #dc3545; color: #721c24; } +
-         +
-        .data-management { +
-            background: #f8f9fa; +
-            padding: 10px 15px; +
-            border-radius: 6px; +
-            margin-bottom: 15px; +
-            display: flex; +
-            align-items: center; +
-            gap: 10px; +
-            flex-wrap: wrap; +
-        } +
-        .data-management-label { +
-            font-size: 12px; +
-            color: #666; +
-            font-weight: bold; +
-            margin-right: 10px; +
-        } +
-         +
-        .save-buttons { +
-            display: flex; +
-            gap: 8px; +
-            margin: 15px 0; +
-            flex-wrap: wrap; +
-        } +
-        .save-btn { +
-            padding: 6px 12px; +
-            border: none; +
-            border-radius: 4px; +
-            cursor: pointer; +
-            font-weight: normal; +
-            font-size: 12px; +
-        } +
-        .save-data-btn { background: #28a745; color: white; } +
-        .save-chart-btn { background: #17a2b8; color: white; } +
-        .load-data-btn { background: #ffc107; color: #333; } +
-         +
-        .manual-input { +
-            background: #f8f9fa; +
-            padding: 20px; +
-            border-radius: 8px; +
-            margin: 20px 0; +
-        } +
-        .input-row { +
-            display: grid; +
-            grid-template-columns: 150px 150px 200px 40px; +
-            gap: 10px; +
-            margin-bottom: 10px; +
-            align-items: center; +
-        } +
-        .input-row input { +
-            padding: 8px; +
-            border: 1px solid #ddd; +
-            border-radius: 4px; +
-            font-size: 14px; +
-        } +
-        .add-row-btn, .remove-row-btn { +
-            padding: 8px 12px; +
-            border: none; +
-            border-radius: 4px; +
-            cursor: pointer; +
-            font-size: 16px; +
-        } +
-        .add-row-btn { +
-            background: #28a745; +
-            color: white; +
-            margin-top: 10px; +
-        } +
-        .remove-row-btn { +
-            background: #dc3545; +
-            color: white; +
-        } +
-        .process-btn { +
-            background: #007bff; +
-            color: white; +
-            padding: 12px 24px; +
-            border: none; +
-            border-radius: 6px; +
-            cursor: pointer; +
-            font-size: 16px; +
-            margin-top: 15px; +
-        } +
-         +
-        .data-table {  +
-            width: 100%;  +
-            border-collapse: collapse;  +
-            margin: 20px 0; +
-        } +
-        .data-table th, .data-table td {  +
-            border: 1px solid #ddd;  +
-            padding: 8px;  +
-            text-align: left; +
-        } +
-        .data-table th {  +
-            background: #f2f2f2;  +
-            font-weight: bold; +
-        } +
-        .violation { background: #ffe6e6; } +
-         +
-        .hidden { display: none; } +
-    </style> +
-</head> +
-<body> +
-    <div class="container"> +
-        <div class="header" id="header"> +
-            <h1 id="title">📊 Control Chart System</h1> +
-            <p id="subtitle">Monitoraggio DOT - Days of Therapy</p> +
-        </div> +
- +
-        <div class="sample-buttons"> +
-            <button class="sample-btn btn-dot" id="sampleBtn" onclick="loadSample('dot')"> +
-                💊 DOT - Days of Therapy +
-            </button> +
-        </div> +
- +
-        <div id="status" class="hidden"></div> +
- +
-        <!-- ============ GRAFICO IN ALTO - SEMPRE VISIBILE ============ --> +
-        <div class="chart-container" id="chartContainer"> +
-            <h2 id="chartTitle" style="color: #007bff; margin-bottom: 20px;">📊 Control Chart</h2> +
-            <div class="chart-wrapper"> +
-                <canvas id="chart"></canvas> +
-            </div> +
-        </div> +
- +
-        <!-- Statistiche --> +
-        <div class="stats" id="statsContainer"> +
-            <div class="stat"> +
-                <div class="stat-value" id="meanValue">-</div> +
-                <div class="stat-label">Media</div> +
-            </div> +
-            <div class="stat"> +
-                <div class="stat-value" id="uclValue">-</div> +
-                <div class="stat-label">UCL</div> +
-            </div> +
-            <div class="stat"> +
-                <div class="stat-value" id="lclValue">-</div> +
-                <div class="stat-label">LCL</div> +
-            </div> +
-            <div class="stat"> +
-                <div class="stat-value" id="violationsCount">-</div> +
-                <div class="stat-label">Violazioni</div> +
-            </div> +
-        </div> +
-         +
-        <div class="save-buttons" id="saveChartButtons"> +
-            <span class="data-management-label">💾 Esporta Grafico:</span> +
-            <button class="save-btn save-chart-btn" onclick="saveChartImage()">Salva PNG</button> +
-            <button class="save-btn save-chart-btn" onclick="saveChartPDF()">Salva Report HTML</button> +
-        </div> +
- +
-        <!-- ============ SEZIONE COLLASSABILE: INSERIMENTO DATI ============ --> +
-        <div class="collapsible-section"> +
-            <div class="collapsible-header" onclick="toggleSection('dataInput')"> +
-                <span>✏️ Inserimento Dati</span> +
-                <span class="toggle-icon">▼</span> +
-            </div> +
-            <div class="collapsible-content" id="dataInputContent"> +
-                <div class="data-management"> +
-                    <span class="data-management-label">💾 Gestione Dati:</span> +
-                    <button class="save-btn save-data-btn" onclick="saveManualData()">Esporta JSON</button> +
-                    <button class="save-btn load-data-btn" onclick="loadManualData()">Importa JSON</button> +
-                    <button class="save-btn" style="background: #6c757d; color: white;" onclick="clearLocalStorage()">Cancella Salvati</button> +
-                </div> +
-                 +
-                <div style="margin-bottom: 15px;"> +
-                    <label style="font-weight: bold;">Titolo Indicatore:</label> +
-                    <input type="text" id="manualTitle" placeholder="es. DOT Reparto XYZ" style="width: 300px; padding: 8px; margin-left: 10px; border: 1px solid #ddd; border-radius: 4px;"> +
-                </div> +
-                 +
-                <div style="margin-bottom: 20px;"> +
-                    <div class="input-row" style="font-weight: bold; background: #e9ecef; padding: 10px; border-radius: 4px;"> +
-                        <div>Periodo</div> +
-                        <div>Valore</div> +
-                        <div>Note</div> +
-                        <div></div> +
-                    </div> +
-                </div> +
-                 +
-                <div id="manualRows"> +
-                    <div class="input-row"> +
-                        <input type="text" placeholder="Sett_1" class="period-input"> +
-                        <input type="number" step="0.01" placeholder="0.20" class="value-input"> +
-                        <input type="text" placeholder="Note..." class="note-input"> +
-                        <button class="remove-row-btn" onclick="removeRow(this)">🗑️</button> +
-                    </div> +
-                </div> +
-                 +
-                <button class="add-row-btn" onclick="addRow()">➕ Aggiungi Riga</button> +
-                <button class="process-btn" onclick="processManualData()">📊 Genera Control Chart</button> +
-                 +
-                <input type="file" id="loadDataFile" accept=".json" style="display: none;"> +
-            </div> +
-        </div> +
- +
-        <!-- ============ SEZIONE COLLASSABILE: TABELLA ============ --> +
-        <div class="collapsible-section"> +
-            <div class="collapsible-header" onclick="toggleSection('dataTable')"> +
-                <span>📋 Tabella Dati e Analisi</span> +
-                <span class="toggle-icon">▼</span> +
-            </div> +
-            <div class="collapsible-content" id="dataTableContent"> +
-                <table class="data-table" id="dataTable"> +
-                    <thead> +
-                        <tr> +
-                            <th>Punto</th> +
-                            <th>Periodo</th> +
-                            <th>Valore</th> +
-                            <th>Stato</th> +
-                            <th>Note</th> +
-                        </tr> +
-                    </thead> +
-                    <tbody id="tableBody"> +
-                    </tbody> +
-                </table> +
-            </div> +
-        </div> +
-    </div> +
- +
-    <script> +
-        let currentChart = null; +
-        let currentData = []; +
- +
-        const examples = { +
-            dot: { +
-                theme: 'dot', +
-                name: 'DOT - Days of Therapy', +
-                icon: '💊', +
-                units: '%', +
-                data: [ +
-                    {periodo'Sett_1', valore: 0.20, note: 'GG terapia: 5 GG degenza: 25'}, +
-                    {periodo: 'Sett_2', valore: 0.24, note: 'GG terapia: 6 GG degenza: 25'}, +
-                    {periodo: 'Sett_3', valore: 0.18, note: 'GG terapia: 5 GG degenza: 28'}, +
-                    {periodo: 'Sett_4', valore: 0.28, note: 'GG terapia: 7 GG degenza: 25'}, +
-                    {periodo: 'Sett_5', valore: 0.22, note: 'GG terapia: 6 / GG degenza: 27'}, +
-                    {periodo: 'Sett_6', valore: 0.26, note: 'GG terapia: 7 / GG degenza: 27'}, +
-                    {periodo: 'Sett_7', valore: 0.19, note: 'GG terapia: 5 / GG degenza: 26'}, +
-                    {periodo: 'Sett_8', valore: 0.31, note: 'GG terapia: 8 / GG degenza: 26'}, +
-                    {periodo: 'Sett_9', valore: 0.21, note: 'GG terapia: 6 / GG degenza: 29'}, +
-                    {periodo: 'Sett_10', valore: 0.25, note: 'GG terapia: 7 / GG degenza: 28'} +
-                ] +
-            } +
-        }; +
- +
-        function loadSample(type) { +
-            const example = examples[type]; +
-            processData(example.data, example); +
-        } +
- +
-        function toggleSection(sectionId) { +
-            const content = document.getElementById(sectionId + 'Content'); +
-            const header = content.previousElementSibling; +
-            content.classList.toggle('collapsed'); +
-            header.classList.toggle('collapsed'); +
-        } +
- +
-        function processData(data, config = null) { +
-            if (!config) { +
-                config = { +
-                    theme: 'manual', +
-                    name: 'Dati Manuali', +
-                    icon: '📊', +
-                    units: '%+
-                }; +
-            } +
-             +
-            currentData = data; +
-             +
-            const values = data.map(d => d.valore); +
-            const mean = values.reduce((a, b) => a + b, 0) / values.length; +
-            const std = Math.sqrt(values.reduce((sum, x) => sum + Math.pow(x - mean, 2), 0) / values.length); +
-            const ucl = mean + 3 * std; +
-            const lcl = Math.max(0, mean - 3 * std); +
-             +
-            const violations = []; +
-            values.forEach((val, i) => { +
-                if (val > ucl || val < lcl) violations.push(i); +
-            }); +
-             +
-            updateHeader(config); +
-            updateStats(mean, ucl, lcl, violations.length); +
-            createChart(data, config, mean, ucl, lcl, violations); +
-            updateTable(data, violations); +
-            showAlert(violations.length, config.name); +
-        } +
- +
-        function updateHeader(config) { +
-            document.getElementById('header').className = `header ${config.theme}`; +
-            document.getElementById('title').textContent = `${config.icon} ${config.name}`; +
-            document.getElementById('subtitle').textContent = `Control Chart - Monitoraggio ${config.name}`; +
-        } +
- +
-        function updateStats(mean, ucl, lcl, violationsCount) { +
-            const formatValue = (val) => { +
-                if (val < 1 && val > 0) return (val * 100).toFixed(1) + '%'; +
-                return val.toFixed(1); +
-            }; +
-             +
-            document.getElementById('meanValue').textContent = formatValue(mean); +
-            document.getElementById('uclValue').textContent = formatValue(ucl); +
-            document.getElementById('lclValue').textContent = formatValue(lcl); +
-            document.getElementById('violationsCount').textContent = violationsCount; +
-        } +
- +
-        function createChart(data, config, mean, ucl, lcl, violations) { +
-            if (currentChart) { +
-                currentChart.destroy(); +
-                currentChart = null; +
-            } +
-             +
-            document.getElementById('chartTitle').textContent = `📊 Control Chart - ${config.name}`; +
-             +
-            const values = data.map(d => d.valore); +
-            const labels = data.map((d, i) => i + 1); +
-            const colors = values.map((val, i) => violations.includes(i) ? 'red' : '#007bff'); +
-            const sizes = values.map((val, i) => violations.includes(i) ? 8 : 4); +
-             +
-            const formatValue = (val) => { +
-                if (val < 1 && val > 0) return (val * 100).toFixed(1) + '%'; +
-                return val.toFixed(1); +
-            }; +
-             +
-            const ctx = document.getElementById('chart').getContext('2d'); +
-            currentChart = new Chart(ctx, { +
-                type: 'line', +
-                data: { +
-                    labels: labels, +
-                    datasets: [{ +
-                        label: `${config.name} (${config.units})`, +
-                        data: values, +
-                        borderColor: '#007bff', +
-                        backgroundColor: colors, +
-                        pointRadius: sizes, +
-                        pointBackgroundColor: colors, +
-                        fill: false, +
-                        tension: 0.1 +
-                    }, { +
-                        label: `UCL (${formatValue(ucl)})`, +
-                        data: Array(values.length).fill(ucl), +
-                        borderColor: 'red', +
-                        borderDash: [5, 5], +
-                        pointRadius: 0, +
-                        fill: false +
-                    }, { +
-                        label: `Media (${formatValue(mean)})`, +
-                        data: Array(values.length).fill(mean), +
-                        borderColor: 'green', +
-                        pointRadius: 0, +
-                        fill: false +
-                    }, { +
-                        label: `LCL (${formatValue(lcl)})`, +
-                        data: Array(values.length).fill(lcl), +
-                        borderColor: 'red', +
-                        borderDash: [5, 5], +
-                        pointRadius: 0, +
-                        fill: false +
-                    }] +
-                }, +
-                options: { +
-                    responsive: true, +
-                    maintainAspectRatio: false, +
-                    plugins: { +
-                        title: { +
-                            display: true, +
-                            text: `${config.icon} Control Chart - ${config.name}`, +
-                            font: { size: 16, weight: 'bold'+
-                        } +
-                    }, +
-                    scales: { +
-                        y: { +
-                            title: { +
-                                display: true, +
-                                text: `${config.name} (${config.units})` +
-                            } +
-                        } +
-                    } +
-                } +
-            }); +
-        } +
- +
-        function updateTable(data, violations) { +
-            const tbody = document.getElementById('tableBody'); +
-            tbody.innerHTML = ''; +
-             +
-            data.forEach((row, i) => { +
-                const tr = document.createElement('tr'); +
-                if (violations.includes(i)) tr.className = 'violation'; +
-                tr.innerHTML = ` +
-                    <td>${i + 1}</td> +
-                    <td>${row.periodo}</td> +
-                    <td>${row.valore}</td> +
-                    <td>${violations.includes(i) ? '🚨 VIOLAZIONE' : '✅ OK'}</td> +
-                    <td>${row.note}</td> +
-                `; +
-                tbody.appendChild(tr); +
-            }); +
-        } +
- +
-        function showAlert(violationsCount, name) { +
-            const status = document.getElementById('status'); +
-            status.classList.remove('hidden'); +
-             +
-            if (violationsCount === 0) { +
-                status.innerHTML = `<div class="alert alert-success"><strong>✅ Processo sotto controllo</strong></div>`; +
-            } else { +
-                status.innerHTML = `<div class="alert alert-danger"><strong>🚨 ${violationsCount} violazioni rilevate!</strong></div>`; +
-            } +
-        } +
- +
-        function addRow() { +
-            const container = document.getElementById('manualRows'); +
-            const newRow = document.createElement('div'); +
-            newRow.className = 'input-row'; +
-            newRow.innerHTML = ` +
-                <input type="text" placeholder="Sett_${container.children.length + 1}" class="period-input"> +
-                <input type="number" step="0.01" placeholder="0.20" class="value-input"> +
-                <input type="text" placeholder="Note..." class="note-input"> +
-                <button class="remove-row-btn" onclick="removeRow(this)">🗑️</button> +
-            `; +
-            container.appendChild(newRow); +
-            saveToLocalStorage(); +
-        } +
- +
-        function removeRow(button) { +
-            const container = document.getElementById('manualRows'); +
-            if (container.children.length > 1) { +
-                button.parentElement.remove(); +
-                saveToLocalStorage(); +
-            } else { +
-                alert('Devi mantenere almeno una riga!'); +
-            } +
-        } +
- +
-        function processManualData() { +
-            const title = document.getElementById('manualTitle').value.trim() || 'Dati Manuali'; +
-            const rows = document.getElementById('manualRows').children; +
-            const data = []; +
-             +
-            for (let row of rows) { +
-                const periodo = row.querySelector('.period-input').value.trim(); +
-                const valore = parseFloat(row.querySelector('.value-input').value); +
-                const note = row.querySelector('.note-input').value.trim() || 'Dato manuale'; +
-                 +
-                if (periodo && !isNaN(valore)) { +
-                    data.push({ periodo, valore, note }); +
-                } +
-            } +
-             +
-            if (data.length === 0) { +
-                alert('⚠️ Inserisci almeno un dato valido!'); +
-                return; +
-            } +
-             +
-            const config = { +
-                theme: 'manual', +
-                name: title, +
-                icon: '📊', +
-                units: '%' +
-            }; +
-             +
-            processData(data, config); +
-             +
-            // Aggiorna il pulsante esempio con il titolo inserito +
-            if (title && title !== 'Dati Manuali') { +
-                document.getElementById('sampleBtn').textContent = `📊 ${title}`; +
-            } +
-        } +
- +
-        function saveToLocalStorage() { +
-            const title = document.getElementById('manualTitle').value.trim(); +
-            const rows = document.getElementById('manualRows').children; +
-            const data = []; +
-             +
-            for (let row of rows) { +
-                const periodo = row.querySelector('.period-input').value.trim(); +
-                const valore = row.querySelector('.value-input').value; +
-                const note = row.querySelector('.note-input').value.trim(); +
-                data.push({ periodo, valore, note }); +
-            } +
-             +
-            localStorage.setItem('controlChartData', JSON.stringify({ +
-                title: title, +
-                lastSaved: new Date().toISOString(), +
-                rows: data +
-            })); +
-        } +
- +
-        function loadFromLocalStorage() { +
-            const saved = localStorage.getItem('controlChartData'); +
-            if (!saved) return false; +
-             +
-            try { +
-                const savedData = JSON.parse(saved); +
-                document.getElementById('manualTitle').value = savedData.title || ''; +
-                 +
-                const container = document.getElementById('manualRows'); +
-                container.innerHTML = ''; +
-                 +
-                savedData.rows.forEach((row) => { +
-                    const newRow = document.createElement('div'); +
-                    newRow.className = 'input-row'; +
-                    newRow.innerHTML = ` +
-                        <input type="text" value="${row.periodo || ''}" class="period-input"> +
-                        <input type="number" step="0.01" value="${row.valore || ''}" class="value-input"> +
-                        <input type="text" value="${row.note || ''}" class="note-input"> +
-                        <button class="remove-row-btn" onclick="removeRow(this)">🗑️</button> +
-                    `; +
-                    container.appendChild(newRow); +
-                }); +
-                 +
-                addAutoSaveListeners(); +
-                return true; +
-            } catch (error) { +
-                return false; +
-            } +
-        } +
- +
-        function addAutoSaveListeners() { +
-            document.getElementById('manualTitle').addEventListener('input', saveToLocalStorage); +
-            document.getElementById('manualRows').addEventListener('input', saveToLocalStorage); +
-        } +
- +
-        function saveManualData() { +
-            const title = document.getElementById('manualTitle').value.trim() || 'Dati'; +
-            const rows = document.getElementById('manualRows').children; +
-            const data = []; +
-             +
-            for (let row of rows) { +
-                data.push({ +
-                    periodo: row.querySelector('.period-input').value.trim(), +
-                    valore: row.querySelector('.value-input').value, +
-                    note: row.querySelector('.note-input').value.trim() +
-                }); +
-            } +
-             +
-            const blob = new Blob([JSON.stringify({title, rows: data}, null, 2)], {type: 'application/json'}); +
-            const url = URL.createObjectURL(blob); +
-            const link = document.createElement('a'); +
-            link.href = url; +
-            link.download = `control_chart_${title.replace(/\s+/g, '_')}.json`; +
-            link.click(); +
-            URL.revokeObjectURL(url); +
-        } +
- +
-        function loadManualData() { +
-            const input = document.getElementById('loadDataFile'); +
-            input.onchange = function() { +
-                const file = input.files[0]; +
-                if (!file) return; +
-                 +
-                const reader = new FileReader(); +
-                reader.onload = function(e) { +
-                    try { +
-                        const savedData = JSON.parse(e.target.result); +
-                        document.getElementById('manualTitle').value = savedData.title || ''; +
-                         +
-                        const container = document.getElementById('manualRows'); +
-                        container.innerHTML = ''; +
-                         +
-                        savedData.rows.forEach((row) => { +
-                            const newRow = document.createElement('div'); +
-                            newRow.className = 'input-row'; +
-                            newRow.innerHTML = ` +
-                                <input type="text" value="${row.periodo || ''}" class="period-input"> +
-                                <input type="number" step="0.01" value="${row.valore || ''}" class="value-input"> +
-                                <input type="text" value="${row.note || ''}" class="note-input"> +
-                                <button class="remove-row-btn" onclick="removeRow(this)">🗑️</button> +
-                            `; +
-                            container.appendChild(newRow); +
-                        }); +
-                         +
-                        saveToLocalStorage(); +
-                        alert('✅ Dati importati!'); +
-                    } catch (error) { +
-                        alert('❌ Errore: ' + error.message); +
-                    } +
-                }; +
-                reader.readAsText(file); +
-                input.value = ''; +
-            }; +
-            input.click(); +
-        } +
- +
-        function clearLocalStorage() { +
-            if (confirm('⚠️ Cancellare i dati salvati?')) { +
-                localStorage.removeItem('controlChartData'); +
-                document.getElementById('manualTitle').value = ''; +
-                document.getElementById('manualRows').innerHTML = ` +
-                    <div class="input-row"> +
-                        <input type="text" placeholder="Sett_1" class="period-input"> +
-                        <input type="number" step="0.01" placeholder="0.20" class="value-input"> +
-                        <input type="text" placeholder="Note..." class="note-input"> +
-                        <button class="remove-row-btn" onclick="removeRow(this)">🗑️</button> +
-                    </div> +
-                `; +
-                addAutoSaveListeners(); +
-                alert('✅ Dati cancellati!'); +
-            } +
-        } +
- +
-        function saveChartImage() { +
-            if (!currentChart) return; +
-            const url = document.getElementById('chart').toDataURL('image/png'); +
-            const link = document.createElement('a'); +
-            link.href = url; +
-            link.download = `control_chart_${new Date().toISOString().split('T')[0]}.png`; +
-            link.click(); +
-        } +
- +
-        function saveChartPDF() { +
-            if (!currentChart || currentData.length === 0) return; +
-             +
-            const canvas = document.getElementById('chart'); +
-            const imageData = canvas.toDataURL('image/png'); +
-             +
-            const reportHTML = ` +
-<!DOCTYPE html+
-<html> +
-<head> +
-    <meta charset="UTF-8"> +
-    <title>Control Chart Report</title> +
-    <style> +
-        body { font-family: Arial, sans-serif; margin: 40px; } +
-        h1 { color: #2c3e50; } +
-        .stats { display: flex; gap: 20px; margin: 20px 0; } +
-        .stat { background: #f8f9fa; padding: 15px; border-radius: 6px; } +
-        img { max-width: 100%; height: auto; margin: 20px 0; } +
-        table { width: 100%; border-collapse: collapse; margin: 20px 0; } +
-        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } +
-        th { background: #f2f2f2; } +
-        .violation { background: #ffe6e6; } +
-    </style> +
-</head> +
-<body> +
-    <h1>📊 Control Chart Report</h1> +
-    <p><strong>Data:</strong> ${new Date().toLocaleDateString('it-IT')}</p> +
-    <p><strong>Indicatore:</strong> ${document.getElementById('title').textContent}</p> +
-     +
-    <div class="stats"> +
-        <div class="stat"> +
-            <strong>Media:</strong> ${document.getElementById('meanValue').textContent} +
-        </div> +
-        <div class="stat"> +
-            <strong>UCL:</strong> ${document.getElementById('uclValue').textContent} +
-        </div> +
-        <div class="stat"> +
-            <strong>LCL:</strong> ${document.getElementById('lclValue').textContent} +
-        </div> +
-        <div class="stat"> +
-            <strong>Violazioni:</strong> ${document.getElementById('violationsCount').textContent} +
-        </div> +
-    </div> +
-     +
-    <h2>Grafico</h2> +
-    <img src="${imageData}" alt="Control Chart"> +
-     +
-    <h2>Dati Dettagliati</h2> +
-    ${document.getElementById('dataTable').outerHTML} +
-     +
-    <p style="margin-top: 40px; color: #666; font-size: 12px;"> +
-        Report generato da Control Chart System - ${new Date().toLocaleString('it-IT')} +
-    </p> +
-</body> +
-</html> +
-            `; +
-             +
-            const blob = new Blob([reportHTML], { type: 'text/html' }); +
-            const url = URL.createObjectURL(blob); +
-            const link = document.createElement('a'); +
-            link.href = url; +
-            link.download = `control_chart_report_${new Date().toISOString().split('T')[0]}.html`; +
-            link.click(); +
-            URL.revokeObjectURL(url); +
-        } +
- +
-        window.addEventListener('load', function() { +
-            const loaded = loadFromLocalStorage(); +
-            if (loaded) { +
-                document.getElementById('status').innerHTML = ` +
-                    <div class="alert alert-info"> +
-                        <strong>ℹ️ Dati ripristinati automaticamente</strong> +
-                    </div> +
-                `; +
-                document.getElementById('status').classList.remove('hidden'); +
-                 +
-                setTimeout(() => { +
-                    processManualData(); +
-                }, 300); +
-            } else { +
-                addAutoSaveListeners(); +
-            } +
-        }); +
-    </script> +
-</body> +
-</html>+
dashboard/monitoraggio_terapia_antibiotica_-_dot.1758948718.txt.gz · Ultima modifica: da neoadmin