Sprint 11: Freunde & Chat + Phosphor-Icon-Vollmigration
- Freundschaften (pending/accepted), Nutzersuche, Anfragen per Push - Direktnachrichten mit Polling, iMessage-Stil, Deep-Links aus Push - Alle Seiten (map, places, diary, health, dog-profile, sitting, knigge, forum, wiki, walks) vollständig auf Phosphor-Icons migriert - Wikidata-Rassen-Scraper (~833 neue Rassen, lokal gespiegelte Fotos) - TheDogAPI lokal gespiegelt (169 Rassen + Fotos) - Quiz-Result-Cards horizontal (korrekte Bildproportionen) - SW by-v89
This commit is contained in:
parent
96bd57f0ad
commit
097295c628
44 changed files with 9980 additions and 300 deletions
|
|
@ -13,13 +13,14 @@ window.Page_health = (() => {
|
|||
let _activeTab = 'impfung';
|
||||
|
||||
const TABS = [
|
||||
{ key: 'impfung', label: 'Impfpass', icon: '💉' },
|
||||
{ key: 'tierarzt', label: 'Besuche', icon: '🩺' },
|
||||
{ key: 'gewicht', label: 'Gewicht', icon: '⚖️' },
|
||||
{ key: 'medikament', label: 'Medikamente',icon: '💊' },
|
||||
{ key: 'allergie', label: 'Allergien', icon: '🌿' },
|
||||
{ key: 'dokument', label: 'Dokumente', icon: '📄' },
|
||||
{ key: 'praxen', label: 'Praxen', icon: '🏥' },
|
||||
{ key: 'impfung', label: 'Impfpass', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#syringe"></use></svg>' },
|
||||
{ key: 'tierarzt', label: 'Besuche', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>' },
|
||||
{ key: 'gewicht', label: 'Gewicht', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#scales"></use></svg>' },
|
||||
{ key: 'medikament', label: 'Medikamente', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>' },
|
||||
{ key: 'allergie', label: 'Allergien', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#leaf"></use></svg>' },
|
||||
{ key: 'dokument', label: 'Dokumente', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg>' },
|
||||
{ key: 'praxen', label: 'Praxen', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>' },
|
||||
{ key: 'symptomcheck', label: 'Symptom-Check', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#magnifying-glass"></use></svg>' },
|
||||
];
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
|
@ -56,7 +57,7 @@ window.Page_health = (() => {
|
|||
async function _render() {
|
||||
if (!_appState.activeDog) {
|
||||
_container.innerHTML = UI.emptyState({
|
||||
icon: '💉',
|
||||
icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#syringe"></use></svg>',
|
||||
title: 'Noch kein Hund angelegt',
|
||||
text: 'Erstelle zuerst ein Hundeprofil.',
|
||||
action: `<button class="btn btn-primary" onclick="App.navigate('dog-profile')">Profil erstellen</button>`,
|
||||
|
|
@ -81,7 +82,7 @@ window.Page_health = (() => {
|
|||
const isActive = dog.id === activeDogId;
|
||||
const av = dog.foto_url
|
||||
? `<img src="${_esc(dog.foto_url)}" alt="${_esc(dog.name)}">`
|
||||
: `<span style="font-size:2.5rem">🐕</span>`;
|
||||
: `<span>${UI.icon('dog')}</span>`;
|
||||
return `
|
||||
<div class="diary-picker-card${isActive ? ' diary-picker-card--active' : ''}"
|
||||
data-dog-id="${dog.id}">
|
||||
|
|
@ -119,7 +120,7 @@ window.Page_health = (() => {
|
|||
_container.innerHTML = `
|
||||
<div class="health-header">
|
||||
<button class="btn btn-secondary btn-sm" id="health-ki-btn">
|
||||
✨ KI-Zusammenfassung
|
||||
${UI.icon('star')} KI-Zusammenfassung
|
||||
</button>
|
||||
</div>
|
||||
<div id="health-reminders"></div>
|
||||
|
|
@ -165,13 +166,17 @@ window.Page_health = (() => {
|
|||
|
||||
if (!items.length) { el.innerHTML = ''; return; }
|
||||
|
||||
const ICONS = { impfung: '💉', entwurmung: '🪱', medikament: '💊' };
|
||||
const ICONS = {
|
||||
impfung: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#syringe"></use></svg>',
|
||||
entwurmung: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#paw-print"></use></svg>',
|
||||
medikament: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>',
|
||||
};
|
||||
|
||||
el.innerHTML = `
|
||||
<div style="padding:var(--space-3) var(--space-4) 0">
|
||||
<div style="font-size:var(--text-sm);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text-secondary);margin-bottom:var(--space-2)">
|
||||
📅 Anstehende Erinnerungen
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#calendar-dots"></use></svg> Anstehende Erinnerungen
|
||||
</div>
|
||||
${items.map(e => {
|
||||
const ampel = _impfAmpel(e.naechstes);
|
||||
|
|
@ -185,7 +190,7 @@ window.Page_health = (() => {
|
|||
padding:var(--space-2) var(--space-3);margin-bottom:var(--space-1);
|
||||
background:var(--c-surface);border-radius:var(--radius-md);
|
||||
border-left:3px solid ${ampel.color === 'red' ? '#ef4444' : ampel.color === 'yellow' ? '#f59e0b' : '#22c55e'}">
|
||||
<span style="font-size:1.2rem">${ICONS[e._typ] || '📋'}</span>
|
||||
<span style="font-size:1.2rem">${ICONS[e._typ] || '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#clipboard-text"></use></svg>'}</span>
|
||||
<div style="flex:1;min-width:0">
|
||||
<div style="font-size:var(--text-sm);font-weight:var(--weight-medium);
|
||||
white-space:nowrap;overflow:hidden;text-overflow:ellipsis">
|
||||
|
|
@ -199,7 +204,7 @@ window.Page_health = (() => {
|
|||
data-action="reminder-erledigt"
|
||||
data-entry-id="${e.id}" data-entry-typ="${e._typ}"
|
||||
style="flex-shrink:0;white-space:nowrap">
|
||||
✓ Erledigt
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#check"></use></svg> Erledigt
|
||||
</button>
|
||||
</div>`;
|
||||
}).join('')}
|
||||
|
|
@ -302,13 +307,14 @@ window.Page_health = (() => {
|
|||
const entries = _data[_activeTab] || [];
|
||||
|
||||
switch (_activeTab) {
|
||||
case 'impfung': content.innerHTML = _renderImpfungen(entries); break;
|
||||
case 'tierarzt': content.innerHTML = _renderTierarzt(entries); break;
|
||||
case 'gewicht': content.innerHTML = _renderGewicht(entries); break;
|
||||
case 'medikament': content.innerHTML = _renderMedikamente(entries); break;
|
||||
case 'allergie': content.innerHTML = _renderAllergien(entries); break;
|
||||
case 'dokument': content.innerHTML = _renderDokumente(entries); break;
|
||||
case 'praxen': content.innerHTML = _renderPraxen(); break;
|
||||
case 'impfung': content.innerHTML = _renderImpfungen(entries); break;
|
||||
case 'tierarzt': content.innerHTML = _renderTierarzt(entries); break;
|
||||
case 'gewicht': content.innerHTML = _renderGewicht(entries); break;
|
||||
case 'medikament': content.innerHTML = _renderMedikamente(entries); break;
|
||||
case 'allergie': content.innerHTML = _renderAllergien(entries); break;
|
||||
case 'dokument': content.innerHTML = _renderDokumente(entries); break;
|
||||
case 'praxen': content.innerHTML = _renderPraxen(); break;
|
||||
case 'symptomcheck': _renderSymptomCheck(content); break;
|
||||
}
|
||||
|
||||
_bindTabEvents(content);
|
||||
|
|
@ -321,7 +327,7 @@ window.Page_health = (() => {
|
|||
const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Impfung eintragen</button>`;
|
||||
|
||||
if (!entries.length) return UI.emptyState({
|
||||
icon: '💉', title: 'Noch keine Impfungen', text: 'Trage alle Impfungen ein, um nichts zu verpassen.', action: addBtn
|
||||
icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#syringe"></use></svg>', title: 'Noch keine Impfungen', text: 'Trage alle Impfungen ein, um nichts zu verpassen.', action: addBtn
|
||||
});
|
||||
|
||||
const items = entries.map(e => {
|
||||
|
|
@ -337,7 +343,7 @@ window.Page_health = (() => {
|
|||
${UI.time.format(e.datum + 'T00:00:00')}
|
||||
${e.charge_nr ? ` · Ch.-Nr: ${_esc(e.charge_nr)}` : ''}
|
||||
</div>
|
||||
${vetName ? `<div style="font-size:var(--text-sm);color:var(--c-text-secondary);margin-top:var(--space-1)">🏥 ${_esc(vetName)}</div>` : ''}
|
||||
${vetName ? `<div style="font-size:var(--text-sm);color:var(--c-text-secondary);margin-top:var(--space-1)"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> ${_esc(vetName)}</div>` : ''}
|
||||
${e.naechstes ? `<div class="health-card-next ampel-text-${ampel.color}">
|
||||
Nächste Impfung: ${UI.time.format(e.naechstes + 'T00:00:00')} ${ampel.icon}
|
||||
</div>` : ''}
|
||||
|
|
@ -365,7 +371,7 @@ window.Page_health = (() => {
|
|||
function _renderTierarzt(entries) {
|
||||
const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Besuch eintragen</button>`;
|
||||
if (!entries.length) return UI.emptyState({
|
||||
icon: '🩺', title: 'Noch keine Tierarztbesuche', text: 'Halte alle Tierarztbesuche fest.', action: addBtn
|
||||
icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>', title: 'Noch keine Tierarztbesuche', text: 'Halte alle Tierarztbesuche fest.', action: addBtn
|
||||
});
|
||||
|
||||
const items = entries.map(e => {
|
||||
|
|
@ -383,7 +389,7 @@ window.Page_health = (() => {
|
|||
${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)}` : ''}
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> ${_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>` : ''}
|
||||
|
|
@ -403,7 +409,7 @@ window.Page_health = (() => {
|
|||
const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Gewicht eintragen</button>`;
|
||||
|
||||
if (!entries.length) return UI.emptyState({
|
||||
icon: '⚖️', title: 'Noch keine Gewichtseinträge', action: addBtn
|
||||
icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#scales"></use></svg>', title: 'Noch keine Gewichtseinträge', action: addBtn
|
||||
});
|
||||
|
||||
const sorted = [...entries].sort((a, b) => a.datum.localeCompare(b.datum));
|
||||
|
|
@ -529,7 +535,7 @@ window.Page_health = (() => {
|
|||
function _renderMedikamente(entries) {
|
||||
const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Medikament eintragen</button>`;
|
||||
if (!entries.length) return UI.emptyState({
|
||||
icon: '💊', title: 'Noch keine Medikamente', action: addBtn
|
||||
icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>', title: 'Noch keine Medikamente', action: addBtn
|
||||
});
|
||||
|
||||
const aktive = entries.filter(e => e.aktiv);
|
||||
|
|
@ -554,7 +560,7 @@ window.Page_health = (() => {
|
|||
|
||||
return `
|
||||
<div class="health-list">
|
||||
${renderGroup(aktive, '💊 Aktuelle Medikamente')}
|
||||
${renderGroup(aktive, '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> Aktuelle Medikamente')}
|
||||
${renderGroup(inaktive, 'Vergangene Medikamente')}
|
||||
</div>
|
||||
<div style="text-align:center;padding:var(--space-4)">${addBtn}</div>
|
||||
|
|
@ -567,7 +573,7 @@ window.Page_health = (() => {
|
|||
function _renderAllergien(entries) {
|
||||
const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Allergie eintragen</button>`;
|
||||
if (!entries.length) return UI.emptyState({
|
||||
icon: '🌿', title: 'Noch keine Allergien eingetragen', action: addBtn
|
||||
icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#leaf"></use></svg>', title: 'Noch keine Allergien eingetragen', action: addBtn
|
||||
});
|
||||
|
||||
const SCHWEREGRAD = { leicht: '🟡', mittel: '🟠', schwer: '🔴' };
|
||||
|
|
@ -598,7 +604,7 @@ window.Page_health = (() => {
|
|||
function _renderDokumente(entries) {
|
||||
const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Dokument hinzufügen</button>`;
|
||||
if (!entries.length) return UI.emptyState({
|
||||
icon: '📄', title: 'Noch keine Dokumente', text: 'Lade Impfpässe, Befunde und mehr hoch.', action: addBtn
|
||||
icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg>', title: 'Noch keine Dokumente', text: 'Lade Impfpässe, Befunde und mehr hoch.', action: addBtn
|
||||
});
|
||||
|
||||
const items = entries.map(e => {
|
||||
|
|
@ -610,7 +616,7 @@ window.Page_health = (() => {
|
|||
? `<img src="${e.datei_url}" class="health-doc-thumb" alt="Vorschau"
|
||||
style="width:64px;height:64px;object-fit:cover;border-radius:var(--radius-md);flex-shrink:0">`
|
||||
: `<div style="width:48px;height:48px;display:flex;align-items:center;justify-content:center;
|
||||
font-size:2rem;flex-shrink:0">${isPdf ? '📄' : '📎'}</div>`}
|
||||
font-size:2rem;flex-shrink:0"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg></div>`}
|
||||
<div class="health-card-body">
|
||||
<div class="health-card-title">${_esc(e.bezeichnung)}</div>
|
||||
<div class="health-card-meta">${UI.time.format(e.datum + 'T00:00:00')}</div>
|
||||
|
|
@ -619,7 +625,7 @@ window.Page_health = (() => {
|
|||
? `<a href="${e.datei_url}" target="_blank" rel="noopener"
|
||||
class="btn btn-secondary btn-sm" style="margin-top:var(--space-2);display:inline-flex"
|
||||
onclick="event.stopPropagation()">
|
||||
${isPdf ? '📄 PDF öffnen' : '🖼️ Bild öffnen'}
|
||||
${isPdf ? '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg> PDF öffnen' : '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#image"></use></svg> Bild öffnen'}
|
||||
</a>`
|
||||
: `<span style="font-size:var(--text-xs);color:var(--c-text-muted)">Noch keine Datei hochgeladen</span>`}
|
||||
</div>
|
||||
|
|
@ -668,7 +674,7 @@ window.Page_health = (() => {
|
|||
${fields}
|
||||
${entry.datei_url
|
||||
? (entry.datei_typ === 'pdf'
|
||||
? `<a href="${entry.datei_url}" target="_blank" class="btn btn-secondary btn-sm" style="margin-top:var(--space-3)">📄 PDF öffnen</a>`
|
||||
? `<a href="${entry.datei_url}" target="_blank" class="btn btn-secondary btn-sm" style="margin-top:var(--space-3)"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg> PDF öffnen</a>`
|
||||
: `<img src="${entry.datei_url}" style="width:100%;border-radius:var(--radius-md);margin-top:var(--space-3)" alt="Dokument">`)
|
||||
: ''}
|
||||
</div>
|
||||
|
|
@ -717,7 +723,7 @@ window.Page_health = (() => {
|
|||
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}`]);
|
||||
rows.push(['Praxis', `<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> ${_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)]);
|
||||
|
|
@ -940,7 +946,7 @@ window.Page_health = (() => {
|
|||
: `<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 —
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> 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>
|
||||
|
|
@ -1062,7 +1068,7 @@ window.Page_health = (() => {
|
|||
const inaktive = _praxen.filter(p => !p.aktiv);
|
||||
|
||||
if (!_praxen.length) return UI.emptyState({
|
||||
icon: '🏥', title: 'Noch keine Praxis eingetragen',
|
||||
icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>', title: 'Noch keine Praxis eingetragen',
|
||||
text: 'Trage deine Tierarztpraxis ein für schnellen Zugriff.',
|
||||
action: addBtn
|
||||
});
|
||||
|
|
@ -1070,7 +1076,7 @@ window.Page_health = (() => {
|
|||
const renderCard = p => `
|
||||
<div class="health-card praxis-card${!p.aktiv ? ' health-card--inactive' : ''}"
|
||||
data-praxis-id="${p.id}" data-action="open-praxis">
|
||||
<div style="font-size:1.5rem">${p.ist_notfallpraxis ? '🚨' : '🏥'}</div>
|
||||
<div style="font-size:1.5rem">${p.ist_notfallpraxis ? '🚨' : '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>'}</div>
|
||||
<div class="health-card-body">
|
||||
<div class="health-card-title">
|
||||
${_esc(p.name)}
|
||||
|
|
@ -1225,6 +1231,111 @@ window.Page_health = (() => {
|
|||
});
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// SYMPTOM-CHECK
|
||||
// ----------------------------------------------------------
|
||||
function _renderSymptomCheck(content) {
|
||||
content.innerHTML = `
|
||||
<div style="padding:var(--space-4)">
|
||||
<div class="card" style="padding:var(--space-4)">
|
||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-4)">
|
||||
Beschreibe die Symptome deines Hundes. Die KI gibt eine erste Einschätzung — kein Ersatz für den Tierarzt.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="symptom-input">Symptome</label>
|
||||
<textarea id="symptom-input" class="form-control" rows="4"
|
||||
placeholder="z.B. frisst nicht, trinkt viel, schläft mehr als sonst..."></textarea>
|
||||
</div>
|
||||
<button id="symptom-submit-btn" class="btn btn-primary" style="width:100%">
|
||||
Symptome analysieren <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#magnifying-glass"></use></svg>
|
||||
</button>
|
||||
<div id="symptom-result" style="display:none;margin-top:var(--space-5)"></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
content.querySelector('#symptom-submit-btn').addEventListener('click', async function () {
|
||||
const btn = this;
|
||||
const textarea = content.querySelector('#symptom-input');
|
||||
const resultEl = content.querySelector('#symptom-result');
|
||||
const symptoms = textarea.value.trim();
|
||||
|
||||
if (!symptoms) {
|
||||
UI.toast.warning('Bitte Symptome eingeben.');
|
||||
return;
|
||||
}
|
||||
|
||||
await UI.asyncButton(btn, async () => {
|
||||
resultEl.style.display = 'none';
|
||||
resultEl.innerHTML = '';
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await API.post(
|
||||
`/dogs/${_appState.activeDog.id}/health/symptom-check`,
|
||||
{ symptoms }
|
||||
);
|
||||
} catch (err) {
|
||||
if (err.status === 402) {
|
||||
resultEl.innerHTML = `
|
||||
<div class="card" style="padding:var(--space-4);border:1px solid var(--c-warning,#f59e0b)">
|
||||
<p style="margin:0;font-size:var(--text-sm)">
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#star"></use></svg> Dieses Feature benötigt Ban Yaro Plus oder einen laufenden KI-Server.
|
||||
</p>
|
||||
</div>`;
|
||||
} else if (err.status === 503) {
|
||||
resultEl.innerHTML = `
|
||||
<div class="card" style="padding:var(--space-4);border:1px solid var(--c-danger,#ef4444)">
|
||||
<p style="margin:0;font-size:var(--text-sm)">
|
||||
KI-Server nicht erreichbar. Bitte später versuchen.
|
||||
</p>
|
||||
</div>`;
|
||||
} else {
|
||||
UI.toast.error(err.message || 'Fehler bei der Symptomanalyse.');
|
||||
return;
|
||||
}
|
||||
resultEl.style.display = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const DRINGLICHKEIT = {
|
||||
beobachten: { badgeClass: 'badge-success', label: '🟢 Beobachten' },
|
||||
tierarzt: { badgeClass: 'badge-warning', label: '🟡 Zum Tierarzt' },
|
||||
notfall: { badgeClass: 'badge-danger', label: '🔴 Notfall — sofort zum Tierarzt!' },
|
||||
};
|
||||
const d = DRINGLICHKEIT[result.dringlichkeit] || { badgeClass: 'badge-primary', label: _esc(result.dringlichkeit) };
|
||||
|
||||
const hinweiseHtml = (result.hinweise || []).length
|
||||
? `<ul style="margin:var(--space-2) 0 0;padding-left:var(--space-5);font-size:var(--text-sm)">
|
||||
${result.hinweise.map(h => `<li style="margin-bottom:var(--space-1)">${_esc(h)}</li>`).join('')}
|
||||
</ul>`
|
||||
: '';
|
||||
|
||||
const zumTierarztHtml = result.zum_tierarzt_wenn
|
||||
? `<div style="margin-top:var(--space-3);padding:var(--space-3);
|
||||
background:var(--c-surface-alt,var(--c-surface));
|
||||
border-radius:var(--radius-md);font-size:var(--text-sm)">
|
||||
<strong>Zum Tierarzt wenn:</strong> ${_esc(result.zum_tierarzt_wenn)}
|
||||
</div>`
|
||||
: '';
|
||||
|
||||
resultEl.innerHTML = `
|
||||
<div style="display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-3)">
|
||||
<span class="badge ${d.badgeClass}" style="font-size:var(--text-sm);padding:var(--space-1) var(--space-3)">
|
||||
${d.label}
|
||||
</span>
|
||||
</div>
|
||||
${result.einschaetzung
|
||||
? `<p style="font-size:var(--text-sm);line-height:1.6;margin:0">${_esc(result.einschaetzung)}</p>`
|
||||
: ''}
|
||||
${hinweiseHtml}
|
||||
${zumTierarztHtml}
|
||||
`;
|
||||
resultEl.style.display = '';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// KI-ZUSAMMENFASSUNG
|
||||
// ----------------------------------------------------------
|
||||
|
|
@ -1235,7 +1346,7 @@ window.Page_health = (() => {
|
|||
try {
|
||||
const { zusammenfassung } = await API.health.kiZusammenfassung(_appState.activeDog.id);
|
||||
UI.modal.open({
|
||||
title: '✨ KI-Gesundheitsbericht',
|
||||
title: `${UI.icon('star')} KI-Gesundheitsbericht`,
|
||||
body: `<div style="white-space:pre-wrap;line-height:1.7;font-size:var(--text-sm)">${_esc(zusammenfassung)}</div>`,
|
||||
});
|
||||
} catch (err) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue