Feature: Trauer-Feature, Futter-Verträglichkeit, Multi-Hund-Fixes, Wetter-Ort (Sprint 47)
- dog-profile.js: Verstorben-Button, Gedenkseite, KI-Abschiedstext - database.py: futter_eintraege/reaktionen, route_dogs, exercise_progress.dog_id - routes/ernaehrung.py: Futter-Verträglichkeit mit 20 Reaktionstypen + Analyse - routes/routen.py: route_dogs Many-to-Many, Routen editierbar - routes/training.py: exercise_progress per dog_id - routes/ki.py: /ki/abschied Trauer-KI - weather.py: Nominatim Ortsname parallel geladen - ui.js: dogChip/bindDogChip, visualViewport-Modal - api.js: gedenken, gedenkseite, futter-Methoden, route_dogs - worlds.js: Ortsname im Wetter-Chip - uebungen.js: _progressLoaded-Flag, dog-spezifischer Fortschritt - trainingsplaene.js: dog_id Unterstützung - diary.js/health.js: P-Badge Cleanup - map.js: Wetter-Ort-Anzeige entfernt - wetter.js: Ort in Wetter-Detail
This commit is contained in:
parent
1ce802c8dc
commit
bda61a0e40
16 changed files with 713 additions and 181 deletions
|
|
@ -2156,6 +2156,7 @@ window.Page_routes = (() => {
|
|||
${_actionBtn('rd-send-friend', 'paper-plane-tilt', 'Senden')}
|
||||
${track.length >= 4 ? _actionBtn('rd-trim', 'pencil-simple', 'Kürzen') : ''}
|
||||
${_actionBtn('rd-reverse', 'path', 'Umkehren')}
|
||||
${(_appState?.dogs?.length > 0) ? _actionBtn('rd-dogs', 'dog', 'Hunde') : ''}
|
||||
${_actionBtn('rd-del', 'trash', 'Löschen', true)}
|
||||
</div>` : '';
|
||||
|
||||
|
|
@ -2244,6 +2245,9 @@ window.Page_routes = (() => {
|
|||
} catch (err) { UI.toast.error(err.message); }
|
||||
});
|
||||
|
||||
// Hunde bearbeiten
|
||||
document.getElementById('rd-dogs')?.addEventListener('click', () => _openEditDogsModal(route));
|
||||
|
||||
// Löschen
|
||||
document.getElementById('rd-del')?.addEventListener('click', async () => {
|
||||
const ok = await UI.modal.confirm({
|
||||
|
|
@ -2304,6 +2308,70 @@ window.Page_routes = (() => {
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Hunde einer Route bearbeiten
|
||||
// ----------------------------------------------------------
|
||||
function _openEditDogsModal(route) {
|
||||
const dogs = _appState?.dogs || [];
|
||||
if (!dogs.length) { UI.toast.info('Keine Hunde im Profil vorhanden.'); return; }
|
||||
|
||||
const currentIds = new Set(route.dog_ids || []);
|
||||
|
||||
const dogRows = dogs.map(d => {
|
||||
const checked = currentIds.has(d.id);
|
||||
const av = d.foto_url
|
||||
? `<img src="${UI.escape(d.foto_url)}" style="width:20px;height:20px;border-radius:50%;object-fit:cover;flex-shrink:0">`
|
||||
: `<svg class="ph-icon" style="width:14px;height:14px;flex-shrink:0" aria-hidden="true"><use href="/icons/phosphor.svg#dog"></use></svg>`;
|
||||
return `<label style="display:inline-flex;align-items:center;gap:6px;padding:5px 10px;
|
||||
border:1.5px solid ${checked ? 'var(--c-primary)' : 'var(--c-border)'};
|
||||
border-radius:100px;cursor:pointer;
|
||||
background:${checked ? 'var(--c-primary-subtle)' : ''};
|
||||
color:${checked ? 'var(--c-primary)' : ''};
|
||||
font-size:var(--text-xs);font-weight:600;user-select:none">
|
||||
<input type="checkbox" name="dog_ids" value="${d.id}" ${checked ? 'checked' : ''}
|
||||
style="display:none" class="rd-dog-cb">
|
||||
${av}<span>${UI.escape(d.name)}</span>
|
||||
</label>`;
|
||||
}).join('');
|
||||
|
||||
const body = `
|
||||
<p style="color:var(--c-text-secondary);margin-bottom:var(--space-4)">
|
||||
Welche Hunde waren bei dieser Route dabei?
|
||||
</p>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:var(--space-2)" id="rd-dogs-picker">
|
||||
${dogRows}
|
||||
</div>
|
||||
`;
|
||||
const footer = `
|
||||
<button type="button" class="btn btn-secondary flex-1" id="rd-dogs-cancel">Abbrechen</button>
|
||||
<button type="button" class="btn btn-primary flex-1" id="rd-dogs-save">${UI.icon('floppy-disk')} Speichern</button>
|
||||
`;
|
||||
UI.modal.open({ title: `${UI.icon('dog')} Hunde bearbeiten`, body, footer });
|
||||
|
||||
// Checkbox-Pill Styling
|
||||
document.querySelectorAll('.rd-dog-cb').forEach(cb => {
|
||||
const label = cb.closest('label');
|
||||
cb.addEventListener('change', () => {
|
||||
label.style.borderColor = cb.checked ? 'var(--c-primary)' : 'var(--c-border)';
|
||||
label.style.background = cb.checked ? 'var(--c-primary-subtle)' : '';
|
||||
label.style.color = cb.checked ? 'var(--c-primary)' : '';
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('rd-dogs-cancel')?.addEventListener('click', UI.modal.close);
|
||||
|
||||
document.getElementById('rd-dogs-save')?.addEventListener('click', async () => {
|
||||
const btn = document.getElementById('rd-dogs-save');
|
||||
await UI.asyncButton(btn, async () => {
|
||||
const dogIds = [...document.querySelectorAll('.rd-dog-cb:checked')].map(c => parseInt(c.value));
|
||||
await API.routes.updateDogs(route.id, dogIds);
|
||||
route.dog_ids = dogIds;
|
||||
UI.modal.close();
|
||||
UI.toast.success('Hunde aktualisiert.');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Richtungspfeile gleichmäßig entlang des Tracks platzieren
|
||||
function _addRouteArrows(map, track, color = '#fff') {
|
||||
if (track.length < 2) return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue