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
|
|
@ -1688,11 +1688,34 @@ window.Page_map = (() => {
|
|||
}
|
||||
|
||||
function _showRecSaveModal(track, distKm, dauMin) {
|
||||
const dogs = _appState?.dogs || [];
|
||||
const activeDogId = _appState?.activeDog?.id;
|
||||
const dogPickerHtml = dogs.length > 1 ? `
|
||||
<div class="form-group">
|
||||
<label class="form-label">Welche Hunde waren dabei?</label>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:var(--space-2)">
|
||||
${dogs.map(d => {
|
||||
const checked = d.id === activeDogId;
|
||||
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"><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 var(--c-border);border-radius:100px;cursor:pointer;
|
||||
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="rec-dog-cb">
|
||||
${av}<span>${UI.escape(d.name)}</span>
|
||||
</label>`;
|
||||
}).join('')}
|
||||
</div>
|
||||
</div>` : '';
|
||||
|
||||
const body = `
|
||||
<p style="color:var(--c-text-secondary);margin-bottom:var(--space-4)">
|
||||
${track.length} GPS-Punkte · ${distKm.toFixed(2)} km · ca. ${dauMin} min
|
||||
</p>
|
||||
<form id="rec-save-form" autocomplete="off">
|
||||
${dogPickerHtml}
|
||||
<div class="form-group">
|
||||
<label class="form-label">Name der Route *</label>
|
||||
<input class="form-control" type="text" name="name"
|
||||
|
|
@ -1772,10 +1795,23 @@ window.Page_map = (() => {
|
|||
if (_recMarker) { _recMarker.remove(); _recMarker = null; }
|
||||
});
|
||||
|
||||
// Hund-Checkbox Toggle-Styling
|
||||
document.querySelectorAll('.rec-dog-cb').forEach(cb => {
|
||||
const label = cb.closest('label');
|
||||
const update = () => {
|
||||
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)' : '';
|
||||
};
|
||||
update();
|
||||
cb.addEventListener('change', update);
|
||||
});
|
||||
|
||||
document.getElementById('rec-save-form')?.addEventListener('submit', async e => {
|
||||
e.preventDefault();
|
||||
const btn = document.querySelector('[form="rec-save-form"][type="submit"]');
|
||||
const fd = UI.formData(e.target);
|
||||
const dogIds = [...document.querySelectorAll('.rec-dog-cb:checked')].map(c => parseInt(c.value));
|
||||
await UI.asyncButton(btn, async () => {
|
||||
const saved = await API.routes.create({
|
||||
name: fd.name?.trim(),
|
||||
|
|
@ -1789,6 +1825,7 @@ window.Page_map = (() => {
|
|||
leine_empfohlen: 'leine_empfohlen' in fd,
|
||||
is_public: 'is_public' in fd,
|
||||
hunde_tauglichkeit: fd.hunde_tauglichkeit || 'sehr_gut',
|
||||
dog_ids: dogIds.length ? dogIds : null,
|
||||
});
|
||||
UI.modal.close();
|
||||
if (_recPolyline) { _recPolyline.remove(); _recPolyline = null; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue