Pflege: Fell schneiden vs. trimmen + Tagebuch Medien-Button nach oben
- dogs.py: Pflegeart-Filter (trimmen/schneiden) anhand Rassen-Beschreibung - dog-profile.js: Badge '✂️ Schneiden' / '✋ Trimmen' bei Fell-Kategorie - diary.js: Fotos/Videos-Button direkt nach Textfeld (vor Ort und Meilenstein) - ki.py: Standardmodell auf claude-sonnet-4-6 umgestellt
This commit is contained in:
parent
69f78219ae
commit
22225d5717
3 changed files with 49 additions and 27 deletions
|
|
@ -361,8 +361,9 @@ async def get_pflege_tipps(dog_id: int, user=Depends(get_current_user)):
|
||||||
(f"%{dog['rasse']}%",)
|
(f"%{dog['rasse']}%",)
|
||||||
).fetchone()
|
).fetchone()
|
||||||
|
|
||||||
# Fell-Typ ableiten
|
# Fell-Typ und Pflegeart ableiten
|
||||||
fell_filter = None
|
fell_filter = None
|
||||||
|
fell_pflege_art_filter = None
|
||||||
if rasse_info:
|
if rasse_info:
|
||||||
beschr = (rasse_info["beschreibung"] or "").lower()
|
beschr = (rasse_info["beschreibung"] or "").lower()
|
||||||
if any(w in beschr for w in ["lockig", "wellig", "kraus", "pudel", "doodle"]):
|
if any(w in beschr for w in ["lockig", "wellig", "kraus", "pudel", "doodle"]):
|
||||||
|
|
@ -374,6 +375,12 @@ async def get_pflege_tipps(dog_id: int, user=Depends(get_current_user)):
|
||||||
elif rasse_info["groesse"] in ("gross", "sehr_gross"):
|
elif rasse_info["groesse"] in ("gross", "sehr_gross"):
|
||||||
fell_filter = "doppel"
|
fell_filter = "doppel"
|
||||||
|
|
||||||
|
# Pflegeart: Trimmen vs. Schneiden
|
||||||
|
if any(w in beschr for w in ["trimm", "hand-stripping", "stripping", "rauhhaar", "drahthaar", "rauhaar"]):
|
||||||
|
fell_pflege_art_filter = "trimmen"
|
||||||
|
elif any(w in beschr for w in ["schneid", "geschoren", "schere", "clipper"]):
|
||||||
|
fell_pflege_art_filter = "schneiden"
|
||||||
|
|
||||||
with db() as conn:
|
with db() as conn:
|
||||||
alle_tipps = conn.execute(
|
alle_tipps = conn.execute(
|
||||||
"SELECT * FROM pflege_tipps ORDER BY kategorie, titel"
|
"SELECT * FROM pflege_tipps ORDER BY kategorie, titel"
|
||||||
|
|
@ -388,10 +395,15 @@ async def get_pflege_tipps(dog_id: int, user=Depends(get_current_user)):
|
||||||
result = []
|
result = []
|
||||||
for t in alle_tipps:
|
for t in alle_tipps:
|
||||||
t = dict(t)
|
t = dict(t)
|
||||||
# Fell-Filter
|
# Fell-Typ-Filter
|
||||||
if fell_filter and t["fell_typ"] and t["fell_typ"] != "alle":
|
if fell_filter and t["fell_typ"] and t["fell_typ"] != "alle":
|
||||||
if fell_filter not in t["fell_typ"].split(","):
|
if fell_filter not in t["fell_typ"].split(","):
|
||||||
continue
|
continue
|
||||||
|
# Pflegeart-Filter: Trimm-Tipps nicht bei Schneidehunden und umgekehrt
|
||||||
|
tipp_art = t.get("fell_pflege_art")
|
||||||
|
if tipp_art and tipp_art != "alle" and fell_pflege_art_filter:
|
||||||
|
if tipp_art != fell_pflege_art_filter:
|
||||||
|
continue
|
||||||
t["schritte"] = _json.loads(t["schritte"] or "[]")
|
t["schritte"] = _json.loads(t["schritte"] or "[]")
|
||||||
t["saisonal_aktuell"] = bool(t["saison"] and heute_saison in t["saison"])
|
t["saisonal_aktuell"] = bool(t["saison"] and heute_saison in t["saison"])
|
||||||
result.append(t)
|
result.append(t)
|
||||||
|
|
@ -408,4 +420,5 @@ async def get_pflege_tipps(dog_id: int, user=Depends(get_current_user)):
|
||||||
"tipp_des_tages": tipp_des_tages,
|
"tipp_des_tages": tipp_des_tages,
|
||||||
"tipps": result,
|
"tipps": result,
|
||||||
"kategorien": list(dict.fromkeys(t["kategorie"] for t in result)),
|
"kategorien": list(dict.fromkeys(t["kategorie"] for t in result)),
|
||||||
|
"fell_pflege_art": fell_pflege_art_filter, # 'schneiden' | 'trimmen' | None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -700,6 +700,22 @@ window.Page_diary = (() => {
|
||||||
<textarea class="form-control" name="text" rows="5"
|
<textarea class="form-control" name="text" rows="5"
|
||||||
placeholder="Was ist passiert? Besonderheiten, Gedanken…">${UI.escape(entry?.text || '')}</textarea>
|
placeholder="Was ist passiert? Besonderheiten, Gedanken…">${UI.escape(entry?.text || '')}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<!-- Bestehende Medien (Edit-Modus) -->
|
||||||
|
<div id="diary-existing-media"></div>
|
||||||
|
|
||||||
|
<!-- Neue Medien: Vorschau-Grid -->
|
||||||
|
<div id="diary-new-media-grid" class="diary-media-grid" style="display:none"></div>
|
||||||
|
|
||||||
|
<!-- versteckter Input — multiple für Mehrfachauswahl -->
|
||||||
|
<input type="file" id="diary-media-input" accept="image/*,video/*,application/pdf" multiple style="display:none">
|
||||||
|
|
||||||
|
<!-- Einzelner Button — iOS zeigt nativen Picker (Mediathek / Kamera / Datei) -->
|
||||||
|
<label for="diary-media-input" class="btn btn-secondary" style="cursor:pointer;display:flex;align-items:center;gap:var(--space-2);justify-content:center">
|
||||||
|
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#image"></use></svg>
|
||||||
|
Fotos / Videos hinzufügen
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div class="form-group" id="diary-location-group">
|
<div class="form-group" id="diary-location-group">
|
||||||
<label class="form-label">Ort <span style="color:var(--c-text-secondary)">(optional)</span></label>
|
<label class="form-label">Ort <span style="color:var(--c-text-secondary)">(optional)</span></label>
|
||||||
|
|
||||||
|
|
@ -744,24 +760,6 @@ window.Page_diary = (() => {
|
||||||
<span>${entry?.is_milestone ? 'Meilenstein ✓' : 'Als Meilenstein markieren'}</span>
|
<span>${entry?.is_milestone ? 'Meilenstein ✓' : 'Als Meilenstein markieren'}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label class="form-label">Fotos / Videos <span style="color:var(--c-text-secondary)">(optional)</span></label>
|
|
||||||
|
|
||||||
<!-- Bestehende Medien (Edit-Modus) -->
|
|
||||||
<div id="diary-existing-media"></div>
|
|
||||||
|
|
||||||
<!-- Neue Medien: Vorschau-Grid -->
|
|
||||||
<div id="diary-new-media-grid" class="diary-media-grid" style="display:none"></div>
|
|
||||||
|
|
||||||
<!-- versteckter Input — multiple für Mehrfachauswahl -->
|
|
||||||
<input type="file" id="diary-media-input" accept="image/*,video/*,application/pdf" multiple style="display:none">
|
|
||||||
|
|
||||||
<!-- Einzelner Button — iOS zeigt nativen Picker (Mediathek / Kamera / Datei) -->
|
|
||||||
<label for="diary-media-input" class="btn btn-secondary" style="margin-top:var(--space-2);cursor:pointer;display:flex;align-items:center;gap:var(--space-2);justify-content:center">
|
|
||||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#image"></use></svg>
|
|
||||||
Fotos / Videos hinzufügen
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -349,6 +349,16 @@ window.Page_dog_profile = (() => {
|
||||||
'Saisonal':'🌸','Gesundheitsvorsorge':'❤️','Welpen-Pflege':'🐶',
|
'Saisonal':'🌸','Gesundheitsvorsorge':'❤️','Welpen-Pflege':'🐶',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const pflegeArtBadge = data.fell_pflege_art === 'schneiden'
|
||||||
|
? `<span title="Dieses Fell wächst kontinuierlich und wird mit der Schere geschnitten"
|
||||||
|
style="font-size:10px;font-weight:700;padding:2px 7px;border-radius:20px;
|
||||||
|
background:#dbeafe;color:#1d4ed8;margin-left:6px">✂️ Schneiden</span>`
|
||||||
|
: data.fell_pflege_art === 'trimmen'
|
||||||
|
? `<span title="Dieses Fell hat natürliche Wachstumsbegrenzung und wird durch Hand-Stripping gepflegt"
|
||||||
|
style="font-size:10px;font-weight:700;padding:2px 7px;border-radius:20px;
|
||||||
|
background:#fef9c3;color:#92400e;margin-left:6px">✋ Trimmen</span>`
|
||||||
|
: '';
|
||||||
|
|
||||||
el.innerHTML = `
|
el.innerHTML = `
|
||||||
<div class="card" style="padding:var(--space-4)">
|
<div class="card" style="padding:var(--space-4)">
|
||||||
<div style="display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-3)">
|
<div style="display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-3)">
|
||||||
|
|
@ -396,11 +406,12 @@ window.Page_dog_profile = (() => {
|
||||||
<div id="dp-pflege-liste" style="display:none;margin-top:var(--space-3)">
|
<div id="dp-pflege-liste" style="display:none;margin-top:var(--space-3)">
|
||||||
${data.kategorien.map(kat => {
|
${data.kategorien.map(kat => {
|
||||||
const katTipps = data.tipps.filter(t=>t.kategorie===kat);
|
const katTipps = data.tipps.filter(t=>t.kategorie===kat);
|
||||||
|
const katBadge = kat === 'Fell' ? pflegeArtBadge : '';
|
||||||
return `
|
return `
|
||||||
<div style="margin-bottom:var(--space-3)">
|
<div style="margin-bottom:var(--space-3)">
|
||||||
<div style="font-size:11px;font-weight:700;color:var(--c-text-muted);
|
<div style="font-size:11px;font-weight:700;color:var(--c-text-muted);
|
||||||
text-transform:uppercase;margin-bottom:8px">
|
text-transform:uppercase;margin-bottom:8px;display:flex;align-items:center">
|
||||||
${kat_icons[kat]||'🐾'} ${_esc(kat)}</div>
|
${kat_icons[kat]||'🐾'} ${_esc(kat)}${katBadge}</div>
|
||||||
${katTipps.map(tip => `
|
${katTipps.map(tip => `
|
||||||
<details style="background:var(--c-surface-2);border-radius:8px;
|
<details style="background:var(--c-surface-2);border-radius:8px;
|
||||||
padding:10px;margin-bottom:6px">
|
padding:10px;margin-bottom:6px">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue