UX: Tierarztbesuch-Tab — Praxis-Verknüpfung als Kernfunktion
- Formular: Praxis-Dropdown ersetzt Freitext wenn Praxen vorhanden - Kein redundantes Freitext-Feld mehr, Ort in der Option angezeigt - "Praxis anlegen"-Link navigiert direkt zum Praxen-Tab - tierarzt_name wird zusätzlich als Sicherheitskopie gespeichert - Karte: zeigt Praxisname + Ort unter dem Besuchsgrund - Detail-Modal: Praxis mit Adresse und anklickbarer Telefonnummer - SW-Cache → by-v12
This commit is contained in:
parent
d9f2e85263
commit
e9587d4ecd
2 changed files with 69 additions and 45 deletions
|
|
@ -245,23 +245,32 @@ window.Page_health = (() => {
|
||||||
function _renderTierarzt(entries) {
|
function _renderTierarzt(entries) {
|
||||||
const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Besuch eintragen</button>`;
|
const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Besuch eintragen</button>`;
|
||||||
if (!entries.length) return UI.emptyState({
|
if (!entries.length) return UI.emptyState({
|
||||||
icon: '🏥', title: 'Noch keine Tierarztbesuche', text: 'Halte alle Tierarztbesuche fest.', action: addBtn
|
icon: '🩺', title: 'Noch keine Tierarztbesuche', text: 'Halte alle Tierarztbesuche fest.', action: addBtn
|
||||||
});
|
});
|
||||||
|
|
||||||
const items = entries.map(e => `
|
const items = entries.map(e => {
|
||||||
<div class="health-card" data-id="${e.id}" data-action="open-entry">
|
const praxis = _praxen.find(p => p.id === e.tierarzt_id);
|
||||||
<div class="health-card-body">
|
const praxisName = praxis?.name || e.tierarzt_name || '';
|
||||||
<div class="health-card-title">${_esc(e.bezeichnung)}</div>
|
const praxisOrt = praxis ? [praxis.plz, praxis.ort].filter(Boolean).join(' ') : '';
|
||||||
<div class="health-card-meta">
|
return `
|
||||||
${UI.time.format(e.datum + 'T00:00:00')}
|
<div class="health-card" data-id="${e.id}" data-action="open-entry">
|
||||||
${e.tierarzt_name ? ` · ${_esc(e.tierarzt_name)}` : ''}
|
<div class="health-card-body">
|
||||||
${e.kosten != null ? ` · ${Number(e.kosten).toFixed(2)} €` : ''}
|
<div class="health-card-title">${_esc(e.bezeichnung)}</div>
|
||||||
|
<div class="health-card-meta">
|
||||||
|
${UI.time.format(e.datum + 'T00:00:00')}
|
||||||
|
${e.kosten != null ? ` · ${Number(e.kosten).toFixed(2)} €` : ''}
|
||||||
|
</div>
|
||||||
|
${praxisName ? `
|
||||||
|
<div style="display:flex;align-items:center;gap:var(--space-1);
|
||||||
|
margin-top:var(--space-1);font-size:var(--text-sm);color:var(--c-text-secondary)">
|
||||||
|
🏥 ${_esc(praxisName)}${praxisOrt ? ` · ${_esc(praxisOrt)}` : ''}
|
||||||
|
</div>` : ''}
|
||||||
|
${e.diagnose ? `<div class="health-card-note"><b>Diagnose:</b> ${_esc(e.diagnose)}</div>` : ''}
|
||||||
|
${e.notiz ? `<div class="health-card-note">${_esc(e.notiz)}</div>` : ''}
|
||||||
</div>
|
</div>
|
||||||
${e.diagnose ? `<div class="health-card-note"><b>Diagnose:</b> ${_esc(e.diagnose)}</div>` : ''}
|
|
||||||
${e.notiz ? `<div class="health-card-note">${_esc(e.notiz)}</div>` : ''}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
`;
|
||||||
`).join('');
|
}).join('');
|
||||||
|
|
||||||
return `<div class="health-list">${items}</div>
|
return `<div class="health-list">${items}</div>
|
||||||
<div style="text-align:center;padding:var(--space-4)">${addBtn}</div>`;
|
<div style="text-align:center;padding:var(--space-4)">${addBtn}</div>`;
|
||||||
|
|
@ -574,7 +583,16 @@ window.Page_health = (() => {
|
||||||
const rows = [];
|
const rows = [];
|
||||||
if (e.datum) rows.push(['Datum', UI.time.format(e.datum + 'T00:00:00')]);
|
if (e.datum) rows.push(['Datum', UI.time.format(e.datum + 'T00:00:00')]);
|
||||||
if (e.naechstes) rows.push(['Nächstes', UI.time.format(e.naechstes + 'T00:00:00')]);
|
if (e.naechstes) rows.push(['Nächstes', UI.time.format(e.naechstes + 'T00:00:00')]);
|
||||||
if (e.tierarzt_name) rows.push(['Tierarzt', _esc(e.tierarzt_name)]);
|
if (e.tierarzt_id) {
|
||||||
|
const praxis = _praxen.find(p => p.id === e.tierarzt_id);
|
||||||
|
if (praxis) {
|
||||||
|
const adresse = [praxis.strasse, [praxis.plz, praxis.ort].filter(Boolean).join(' ')].filter(Boolean).join(', ');
|
||||||
|
const tel = praxis.telefon ? ` · <a href="tel:${_esc(praxis.telefon)}">${_esc(praxis.telefon)}</a>` : '';
|
||||||
|
rows.push(['Praxis', `🏥 ${_esc(praxis.name)}${adresse ? `<br><small style="color:var(--c-text-secondary)">${_esc(adresse)}${tel}</small>` : tel}`]);
|
||||||
|
}
|
||||||
|
} else if (e.tierarzt_name) {
|
||||||
|
rows.push(['Tierarzt', _esc(e.tierarzt_name)]);
|
||||||
|
}
|
||||||
if (e.charge_nr) rows.push(['Charge-Nr.', _esc(e.charge_nr)]);
|
if (e.charge_nr) rows.push(['Charge-Nr.', _esc(e.charge_nr)]);
|
||||||
if (e.kosten != null) rows.push(['Kosten', `${Number(e.kosten).toFixed(2)} €`]);
|
if (e.kosten != null) rows.push(['Kosten', `${Number(e.kosten).toFixed(2)} €`]);
|
||||||
if (e.diagnose) rows.push(['Diagnose', _esc(e.diagnose)]);
|
if (e.diagnose) rows.push(['Diagnose', _esc(e.diagnose)]);
|
||||||
|
|
@ -648,17 +666,12 @@ window.Page_health = (() => {
|
||||||
const form = document.getElementById('health-form');
|
const form = document.getElementById('health-form');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
form?.querySelector('[name="bezeichnung"]')?.focus();
|
form?.querySelector('[name="bezeichnung"]')?.focus();
|
||||||
// Praxis-Dropdown: Name auto-befüllen
|
// "Praxis anlegen" Button im Formular
|
||||||
const praxisSelect = document.getElementById('health-praxis-select');
|
form?.querySelector('[data-action="goto-praxen"]')?.addEventListener('click', () => {
|
||||||
const nameInput = document.getElementById('health-tierarzt-name-input');
|
UI.modal.close();
|
||||||
if (praxisSelect && nameInput) {
|
_activeTab = 'praxen';
|
||||||
praxisSelect.addEventListener('change', () => {
|
_renderTab();
|
||||||
const selected = praxisSelect.options[praxisSelect.selectedIndex];
|
});
|
||||||
if (selected.value) {
|
|
||||||
nameInput.value = selected.dataset.name || selected.textContent.trim();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 150);
|
}, 150);
|
||||||
|
|
||||||
document.getElementById('health-form-cancel')?.addEventListener('click', UI.modal.close);
|
document.getElementById('health-form-cancel')?.addEventListener('click', UI.modal.close);
|
||||||
|
|
@ -743,25 +756,31 @@ window.Page_health = (() => {
|
||||||
`;
|
`;
|
||||||
case 'tierarzt': {
|
case 'tierarzt': {
|
||||||
const aktivePraxen = _praxen.filter(p => p.aktiv);
|
const aktivePraxen = _praxen.filter(p => p.aktiv);
|
||||||
const praxisDropdown = aktivePraxen.length ? `
|
const praxisField = aktivePraxen.length
|
||||||
<div class="form-group">
|
? `<div class="form-group">
|
||||||
<label class="form-label">Praxis auswählen</label>
|
<label class="form-label">Behandelnde Praxis</label>
|
||||||
<select class="form-control" id="health-praxis-select" name="tierarzt_id">
|
<select class="form-control" id="health-praxis-select" name="tierarzt_id">
|
||||||
<option value="">– Praxis wählen –</option>
|
<option value="">– Praxis wählen –</option>
|
||||||
${aktivePraxen.map(p => `
|
${aktivePraxen.map(p => `
|
||||||
<option value="${p.id}" data-name="${_esc(p.name)}"
|
<option value="${p.id}"
|
||||||
${entry?.tierarzt_id === p.id ? 'selected' : ''}>
|
${entry?.tierarzt_id === p.id ? 'selected' : ''}>
|
||||||
${_esc(p.name)}
|
${_esc(p.name)}${p.ort ? ` · ${_esc(p.ort)}` : ''}
|
||||||
</option>`).join('')}
|
</option>`).join('')}
|
||||||
</select>
|
</select>
|
||||||
</div>` : '';
|
</div>`
|
||||||
|
: `<div class="form-group">
|
||||||
|
<div style="padding:var(--space-3);background:var(--c-bg);border-radius:var(--radius-md);
|
||||||
|
font-size:var(--text-sm);color:var(--c-text-secondary)">
|
||||||
|
🏥 Noch keine Praxis angelegt —
|
||||||
|
<button type="button" class="btn btn-ghost btn-sm" style="padding:0;font-size:inherit"
|
||||||
|
data-action="goto-praxen">Praxis im Tab Praxen anlegen</button>
|
||||||
|
</div>
|
||||||
|
<label class="form-label" style="margin-top:var(--space-2)">Tierarzt / Praxis (Freitext)</label>
|
||||||
|
<input class="form-control" name="tierarzt_name"
|
||||||
|
value="${_esc(entry?.tierarzt_name || '')}" placeholder="Dr. Muster">
|
||||||
|
</div>`;
|
||||||
return `
|
return `
|
||||||
${praxisDropdown}
|
${praxisField}
|
||||||
<div class="form-group">
|
|
||||||
<label class="form-label">Tierarzt / Praxis (Freitext)</label>
|
|
||||||
<input class="form-control" type="text" id="health-tierarzt-name-input"
|
|
||||||
name="tierarzt_name" value="${_esc(entry?.tierarzt_name || '')}">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">Diagnose</label>
|
<label class="form-label">Diagnose</label>
|
||||||
<textarea class="form-control" name="diagnose" rows="2">${_esc(entry?.diagnose || '')}</textarea>
|
<textarea class="form-control" name="diagnose" rows="2">${_esc(entry?.diagnose || '')}</textarea>
|
||||||
|
|
@ -845,7 +864,12 @@ window.Page_health = (() => {
|
||||||
if (typ === 'gewicht') p.bezeichnung = `${p.wert} kg`;
|
if (typ === 'gewicht') p.bezeichnung = `${p.wert} kg`;
|
||||||
}
|
}
|
||||||
if (fd.kosten) p.kosten = parseFloat(fd.kosten.toString().replace(',', '.'));
|
if (fd.kosten) p.kosten = parseFloat(fd.kosten.toString().replace(',', '.'));
|
||||||
if (fd.tierarzt_id) p.tierarzt_id = parseInt(fd.tierarzt_id);
|
if (fd.tierarzt_id) {
|
||||||
|
p.tierarzt_id = parseInt(fd.tierarzt_id);
|
||||||
|
// Praxisname auch als tierarzt_name sichern (bleibt lesbar wenn Praxis inaktiv/gelöscht)
|
||||||
|
const praxis = _praxen.find(x => x.id === p.tierarzt_id);
|
||||||
|
if (praxis) p.tierarzt_name = praxis.name;
|
||||||
|
}
|
||||||
if (typ === 'medikament') {
|
if (typ === 'medikament') {
|
||||||
p.aktiv = 'aktiv' in fd ? 1 : 0;
|
p.aktiv = 'aktiv' in fd ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Offline-Cache + Push Notifications
|
Offline-Cache + Push Notifications
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const CACHE_VERSION = 'by-v11';
|
const CACHE_VERSION = 'by-v12';
|
||||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||||
|
|
||||||
// Diese Dateien werden beim Install gecacht (App Shell)
|
// Diese Dateien werden beim Install gecacht (App Shell)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue