Dissoziations Tagebuch

Dissoziations-Logbuch

Druckansicht erstellt am

Hinweis: Das Dissoziations-Tagebuch dient der persönlichen Selbstbeobachtung und ersetzt keine therapeutische Behandlung. Alle Einträge werden ausschließlich lokal in diesem Browser gespeichert – nicht auf einem Server. Das bedeutet: Bei gelöschtem Browserverlauf, einem anderen Gerät oder Browser sind die Daten nicht mehr abrufbar. Nutze daher regelmäßig die Export-Funktion, um deine Daten als Datei herunterzuladen und zu sichern – über die Import-Funktion lassen sie sich jederzeit wieder einspielen.
0 · leichte Losgelöstheit 10 · vollständige Dissoziation

Noch keine Einträge vorhanden.

Noch keine Daten für eine Auswertung. Erfasse mindestens 2 Episoden.
' + (e.ausloeser ? '
Auslöser: ' + escapeHtml(e.ausloeser) + '
' : '') + (e.notiz ? '
' + escapeHtml(e.notiz) + '
' : '') + (symptomeHtml ? '' : '') + '
' + '
' ); }).join(''); listEl.querySelectorAll('.dissLog__entryDelete').forEach(function (btn) { btn.addEventListener('click', function () { if (!confirm('Diesen Eintrag wirklich löschen?')) return; entries = entries.filter(function (e) { return e.id !== btn.dataset.id; }); saveEntries(entries); renderList(); renderStats(); refreshAusloeserListe(); }); }); } filterInput.addEventListener('input', renderList); ROOT.querySelector('#dl-clear').addEventListener('click', function () { if (!confirm('Wirklich ALLE Einträge unwiderruflich löschen?')) return; entries = []; saveEntries(entries); renderList(); renderStats(); refreshAusloeserListe(); }); ROOT.querySelector('#dl-print').addEventListener('click', function () { var dateEl = ROOT.querySelector('#dl-print-date'); if (dateEl) { dateEl.textContent = new Date().toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' }) + ' · ' + new Date().toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }); } // sicherstellen, dass Liste & Auswertung aktuell sind, egal welcher Tab aktiv ist renderList(); renderStats(); window.print(); }); ROOT.querySelector('#dl-export').addEventListener('click', function () { var blob = new Blob([JSON.stringify(entries, null, 2)], { type: 'application/json' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'dissoziations-logbuch-export.json'; a.click(); URL.revokeObjectURL(url); }); ROOT.querySelector('#dl-import').addEventListener('change', function (ev) { var file = ev.target.files[0]; if (!file) return; var reader = new FileReader(); reader.onload = function () { try { var imported = JSON.parse(reader.result); if (!Array.isArray(imported)) throw new Error('Ungültiges Format'); var existingIds = {}; entries.forEach(function (e) { existingIds[e.id] = true; }); imported.forEach(function (e) { if (e && e.id && !existingIds[e.id]) entries.push(e); }); entries.sort(function (a, b) { return new Date(b.datetime) - new Date(a.datetime); }); saveEntries(entries); renderList(); renderStats(); refreshAusloeserListe(); alert('Import erfolgreich: ' + imported.length + ' Einträge geprüft.'); } catch (err) { alert('Import fehlgeschlagen: Datei ist kein gültiges Export-Format.'); } ev.target.value = ''; }; reader.readAsText(file); }); // ---------- Mustererkennung / Stats ---------- var WOCHENTAGE = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']; var TAGESZEITEN = [ { label: 'Nacht (0-6)', from: 0, to: 6 }, { label: 'Morgen (6-12)', from: 6, to: 12 }, { label: 'Mittag (12-18)', from: 12, to: 18 }, { label: 'Abend (18-24)', from: 18, to: 24 } ]; function barChartSVG(data, opts) { // data: [{label, value}] opts = opts || {}; var w = 640, barH = 22, gap = 10, labelW = opts.labelW || 130, padTop = 6, padRight = 40; var max = Math.max.apply(null, data.map(function (d) { return d.value; })) || 1; var h = data.length * (barH + gap) + padTop; var rows = data.map(function (d, i) { var y = padTop + i * (barH + gap); var maxBarW = w - labelW - padRight; var barW = Math.max(2, (d.value / max) * maxBarW); return ( '' + escapeHtml(d.label) + '' + '' + '' + '' + d.value + '' ); }).join(''); return '' + rows + ''; } function lineChartSVG(points) { // points: [{x label, value 0-10}] var w = 640, h = 200, padL = 30, padR = 15, padT = 15, padB = 30; var innerW = w - padL - padR, innerH = h - padT - padB; var n = points.length; var stepX = n > 1 ? innerW / (n - 1) : 0; var coords = points.map(function (p, i) { var x = padL + i * stepX; var y = padT + innerH - (p.value / 10) * innerH; return { x: x, y: y, label: p.label, value: p.value }; }); var path = coords.map(function (c, i) { return (i === 0 ? 'M' : 'L') + c.x.toFixed(1) + ',' + c.y.toFixed(1); }).join(' '); var gridLines = [0, 2, 4, 6, 8, 10].map(function (v) { var y = padT + innerH - (v / 10) * innerH; return '' + '' + v + ''; }).join(''); var dots = coords.map(function (c) { return '' + escapeHtml(c.label) + ': ' + c.value + ''; }).join(''); var xLabels = coords.filter(function (_, i) { return n <= 8 || i % Math.ceil(n / 8) === 0 || i === n - 1; }).map(function (c) { return '' + escapeHtml(c.label) + ''; }).join(''); return '' + gridLines + '' + dots + xLabels + ''; } function renderStats() { var statsEmpty = ROOT.querySelector('#dl-stats-empty'); var statsEl = ROOT.querySelector('#dl-stats'); if (entries.length < 2) { statsEmpty.style.display = 'block'; statsEl.style.display = 'none'; return; } statsEmpty.style.display = 'none'; statsEl.style.display = 'block'; var now = new Date(); var d7 = entries.filter(function (e) { return (now - new Date(e.datetime)) <= 7 * 86400000; }).length; var d30 = entries.filter(function (e) { return (now - new Date(e.datetime)) <= 30 * 86400000; }).length; var avgDauer = Math.round(entries.reduce(function (s, e) { return s + (e.dauer || 0); }, 0) / entries.length); var avgGrad = (entries.reduce(function (s, e) { return s + (e.grad || 0); }, 0) / entries.length).toFixed(1); ROOT.querySelector('#stat-7d').textContent = d7; ROOT.querySelector('#stat-30d').textContent = d30; ROOT.querySelector('#stat-dauer').textContent = avgDauer + ' min'; ROOT.querySelector('#stat-grad').textContent = avgGrad + ' / 10'; // Verlauf (chronologisch, letzte 25) var chron = entries.slice().sort(function (a, b) { return new Date(a.datetime) - new Date(b.datetime); }); var last = chron.slice(-25); var points = last.map(function (e) { var d = new Date(e.datetime); return { label: d.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' }), value: e.grad }; }); ROOT.querySelector('#chart-verlauf').innerHTML = lineChartSVG(points); // Auslöser var ausloeserCount = {}; entries.forEach(function (e) { var key = (e.ausloeser || '').trim(); if (!key) return; ausloeserCount[key] = (ausloeserCount[key] || 0) + 1; }); var ausloeserData = Object.keys(ausloeserCount).map(function (k) { return { label: k, value: ausloeserCount[k] }; }).sort(function (a, b) { return b.value - a.value; }).slice(0, 8); ROOT.querySelector('#chart-ausloeser').innerHTML = ausloeserData.length ? barChartSVG(ausloeserData, { labelW: 150 }) : '

Noch keine Auslöser erfasst.

'; // Wochentag var wtCount = [0, 0, 0, 0, 0, 0, 0]; entries.forEach(function (e) { var d = new Date(e.datetime); if (!isNaN(d)) wtCount[d.getDay()]++; }); var wtData = WOCHENTAGE.map(function (label, i) { return { label: label, value: wtCount[i] }; }); ROOT.querySelector('#chart-wochentag').innerHTML = barChartSVG(wtData, { labelW: 60 }); // Tageszeit var tzCount = TAGESZEITEN.map(function () { return 0; }); entries.forEach(function (e) { var d = new Date(e.datetime); if (isNaN(d)) return; var h = d.getHours(); TAGESZEITEN.forEach(function (tz, i) { if (h >= tz.from && h < tz.to) tzCount[i]++; }); }); var tzData = TAGESZEITEN.map(function (tz, i) { return { label: tz.label, value: tzCount[i] }; }); ROOT.querySelector('#chart-tageszeit').innerHTML = barChartSVG(tzData, { labelW: 110 }); // Symptome var sympCount = {}; entries.forEach(function (e) { (e.symptome || []).forEach(function (s) { sympCount[s] = (sympCount[s] || 0) + 1; }); }); var sympData = Object.keys(sympCount).map(function (k) { return { label: k, value: sympCount[k] }; }).sort(function (a, b) { return b.value - a.value; }); ROOT.querySelector('#chart-symptome').innerHTML = sympData.length ? barChartSVG(sympData, { labelW: 170 }) : '

Noch keine Symptome erfasst.

'; } // ---------- Init ---------- refreshAusloeserListe(); renderList(); renderStats(); })();