172 lines
7.4 KiB
HTML
172 lines
7.4 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="de">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="utf-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|||
|
|
<title>AZA – Empfang</title>
|
|||
|
|
<style>
|
|||
|
|
*{box-sizing:border-box;margin:0;padding:0}
|
|||
|
|
body{font-family:'Segoe UI',system-ui,sans-serif;background:#f0f4f8;color:#1a2a3a;min-height:100vh}
|
|||
|
|
header{background:linear-gradient(135deg,#5B8DB3,#3a6d93);color:#fff;padding:18px 24px;display:flex;align-items:center;justify-content:space-between;box-shadow:0 2px 8px rgba(0,0,0,.12)}
|
|||
|
|
header h1{font-size:1.35rem;font-weight:600;letter-spacing:.3px}
|
|||
|
|
header .badge{background:rgba(255,255,255,.2);border-radius:20px;padding:4px 14px;font-size:.85rem}
|
|||
|
|
.container{max-width:900px;margin:24px auto;padding:0 16px}
|
|||
|
|
.empty{text-align:center;padding:60px 20px;color:#6a8a9a;font-size:1.05rem}
|
|||
|
|
.card{background:#fff;border-radius:10px;box-shadow:0 1px 6px rgba(0,0,0,.08);margin-bottom:16px;overflow:hidden;border-left:4px solid #5B8DB3;transition:border-color .2s}
|
|||
|
|
.card.done{border-left-color:#8bc49a;opacity:.7}
|
|||
|
|
.card-header{display:flex;justify-content:space-between;align-items:center;padding:14px 18px;background:#fafcfe;border-bottom:1px solid #eef2f6}
|
|||
|
|
.card-header .meta{font-size:.82rem;color:#6a8a9a}
|
|||
|
|
.card-header .patient{font-weight:600;font-size:1rem;color:#1a3a5a}
|
|||
|
|
.card-header .status{font-size:.75rem;padding:3px 10px;border-radius:12px;font-weight:600}
|
|||
|
|
.status-offen{background:#fff3cd;color:#856404}
|
|||
|
|
.status-erledigt{background:#d4edda;color:#155724}
|
|||
|
|
.card-body{padding:16px 18px}
|
|||
|
|
.field{margin-bottom:10px}
|
|||
|
|
.field-label{font-size:.78rem;font-weight:600;color:#5B8DB3;text-transform:uppercase;letter-spacing:.5px;margin-bottom:3px}
|
|||
|
|
.field-value{font-size:.95rem;white-space:pre-wrap;line-height:1.5}
|
|||
|
|
.card-actions{display:flex;gap:8px;padding:10px 18px;background:#fafcfe;border-top:1px solid #eef2f6;flex-wrap:wrap}
|
|||
|
|
.btn{border:none;border-radius:6px;padding:7px 16px;font-size:.82rem;cursor:pointer;font-weight:500;transition:background .15s}
|
|||
|
|
.btn-copy{background:#e8f0f8;color:#2a5a8a}.btn-copy:hover{background:#d4e4f0}
|
|||
|
|
.btn-print{background:#e8f0e8;color:#2a5a2a}.btn-print:hover{background:#d4e8d4}
|
|||
|
|
.btn-done{background:#d4edda;color:#155724}.btn-done:hover{background:#c3e6cb}
|
|||
|
|
.btn-delete{background:#f8e8e8;color:#8a2a2a}.btn-delete:hover{background:#f0d4d4}
|
|||
|
|
.refresh-info{text-align:center;padding:8px;font-size:.78rem;color:#8a9aaa}
|
|||
|
|
@media print{header,.card-actions,.refresh-info{display:none}.card{break-inside:avoid;border-left-width:2px;box-shadow:none}}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
|
|||
|
|
<header>
|
|||
|
|
<h1>AZA – Empfang</h1>
|
|||
|
|
<span class="badge" id="count-badge">–</span>
|
|||
|
|
</header>
|
|||
|
|
|
|||
|
|
<div class="container" id="messages-container">
|
|||
|
|
<div class="empty" id="empty-state">Nachrichten werden geladen…</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="refresh-info">Aktualisiert automatisch alle 10 Sekunden</div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
const API_BASE = window.location.origin + '/empfang';
|
|||
|
|
let lastData = '';
|
|||
|
|
|
|||
|
|
async function loadMessages() {
|
|||
|
|
try {
|
|||
|
|
const r = await fetch(API_BASE + '/messages');
|
|||
|
|
const d = await r.json();
|
|||
|
|
const raw = JSON.stringify(d.messages || []);
|
|||
|
|
if (raw === lastData) return;
|
|||
|
|
lastData = raw;
|
|||
|
|
render(d.messages || []);
|
|||
|
|
} catch (e) {
|
|||
|
|
document.getElementById('messages-container').innerHTML =
|
|||
|
|
'<div class="empty">Backend nicht erreichbar.<br>Bitte Verbindung prüfen.</div>';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function render(msgs) {
|
|||
|
|
const c = document.getElementById('messages-container');
|
|||
|
|
const open = msgs.filter(m => m.status === 'offen');
|
|||
|
|
document.getElementById('count-badge').textContent = open.length + ' offen';
|
|||
|
|
if (!msgs.length) {
|
|||
|
|
c.innerHTML = '<div class="empty">Keine Nachrichten vorhanden.</div>';
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
c.innerHTML = msgs.map(m => {
|
|||
|
|
const isDone = m.status === 'erledigt';
|
|||
|
|
const fields = [];
|
|||
|
|
if (m.medikamente) fields.push({l:'Medikamente', v:m.medikamente});
|
|||
|
|
if (m.therapieplan) fields.push({l:'Therapieplan', v:m.therapieplan});
|
|||
|
|
if (m.kommentar) fields.push({l:'Kommentar', v:m.kommentar});
|
|||
|
|
return `
|
|||
|
|
<div class="card ${isDone?'done':''}">
|
|||
|
|
<div class="card-header">
|
|||
|
|
<div>
|
|||
|
|
<div class="patient">${esc(m.patient || 'Ohne Patientenangabe')}</div>
|
|||
|
|
<div class="meta">${esc(m.absender || '–')} · ${esc(m.zeitstempel || m.empfangen || '')}</div>
|
|||
|
|
</div>
|
|||
|
|
<span class="status ${isDone?'status-erledigt':'status-offen'}">${isDone?'Erledigt':'Offen'}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="card-body">
|
|||
|
|
${fields.map(f => `
|
|||
|
|
<div class="field">
|
|||
|
|
<div class="field-label">${esc(f.l)}</div>
|
|||
|
|
<div class="field-value">${esc(f.v)}</div>
|
|||
|
|
</div>
|
|||
|
|
`).join('')}
|
|||
|
|
${!fields.length?'<div class="field"><div class="field-value" style="color:#999">Keine Inhalte</div></div>':''}
|
|||
|
|
</div>
|
|||
|
|
<div class="card-actions">
|
|||
|
|
<button class="btn btn-copy" onclick="copyCard('${m.id}')">Kopieren</button>
|
|||
|
|
<button class="btn btn-print" onclick="printCard('${m.id}')">Drucken</button>
|
|||
|
|
${!isDone?`<button class="btn btn-done" onclick="markDone('${m.id}')">Erledigt</button>`:''}
|
|||
|
|
<button class="btn btn-delete" onclick="deleteMsg('${m.id}')">Löschen</button>
|
|||
|
|
</div>
|
|||
|
|
</div>`;
|
|||
|
|
}).join('');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function esc(s) {
|
|||
|
|
const d = document.createElement('div');
|
|||
|
|
d.textContent = s || '';
|
|||
|
|
return d.innerHTML;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function copyCard(id) {
|
|||
|
|
const msgs = JSON.parse(lastData);
|
|||
|
|
const m = msgs.find(x => x.id === id);
|
|||
|
|
if (!m) return;
|
|||
|
|
const parts = [];
|
|||
|
|
if (m.patient) parts.push('Patient: ' + m.patient);
|
|||
|
|
if (m.medikamente) parts.push('Medikamente:\n' + m.medikamente);
|
|||
|
|
if (m.therapieplan) parts.push('Therapieplan:\n' + m.therapieplan);
|
|||
|
|
if (m.kommentar) parts.push('Kommentar:\n' + m.kommentar);
|
|||
|
|
parts.push('Absender: ' + (m.absender||'–') + ' · ' + (m.zeitstempel||''));
|
|||
|
|
navigator.clipboard.writeText(parts.join('\n\n')).then(() => {
|
|||
|
|
const btn = event.target;
|
|||
|
|
btn.textContent = '✓ Kopiert';
|
|||
|
|
setTimeout(() => btn.textContent = 'Kopieren', 1500);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function printCard(id) {
|
|||
|
|
const msgs = JSON.parse(lastData);
|
|||
|
|
const m = msgs.find(x => x.id === id);
|
|||
|
|
if (!m) return;
|
|||
|
|
const w = window.open('', '_blank', 'width=600,height=500');
|
|||
|
|
w.document.write(`<html><head><title>Empfang</title>
|
|||
|
|
<style>body{font-family:'Segoe UI',sans-serif;padding:30px;color:#1a2a3a}
|
|||
|
|
h2{color:#5B8DB3;margin-bottom:16px}
|
|||
|
|
.f{margin-bottom:12px}.fl{font-size:.8rem;font-weight:bold;color:#5B8DB3;text-transform:uppercase}.fv{margin-top:2px;white-space:pre-wrap}
|
|||
|
|
.meta{font-size:.8rem;color:#888;margin-top:20px;border-top:1px solid #ddd;padding-top:10px}
|
|||
|
|
</style></head><body>
|
|||
|
|
<h2>${esc(m.patient||'Empfangsnachricht')}</h2>
|
|||
|
|
${m.medikamente?`<div class="f"><div class="fl">Medikamente</div><div class="fv">${esc(m.medikamente)}</div></div>`:''}
|
|||
|
|
${m.therapieplan?`<div class="f"><div class="fl">Therapieplan</div><div class="fv">${esc(m.therapieplan)}</div></div>`:''}
|
|||
|
|
${m.kommentar?`<div class="f"><div class="fl">Kommentar</div><div class="fv">${esc(m.kommentar)}</div></div>`:''}
|
|||
|
|
<div class="meta">Absender: ${esc(m.absender||'–')} · ${esc(m.zeitstempel||m.empfangen||'')}</div>
|
|||
|
|
</body></html>`);
|
|||
|
|
w.document.close();
|
|||
|
|
w.print();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function markDone(id) {
|
|||
|
|
await fetch(API_BASE + '/messages/' + id + '/done', {method:'POST'});
|
|||
|
|
lastData = '';
|
|||
|
|
loadMessages();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function deleteMsg(id) {
|
|||
|
|
if (!confirm('Nachricht wirklich löschen?')) return;
|
|||
|
|
await fetch(API_BASE + '/messages/' + id, {method:'DELETE'});
|
|||
|
|
lastData = '';
|
|||
|
|
loadMessages();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
loadMessages();
|
|||
|
|
setInterval(loadMessages, 10000);
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|