Session 2026-04-22: Training, Fixes, KI-Cloud, Dark-Mode
Training-System: - Einheit-Dialog Bugs behoben (UI.toast callable, _dogId via _appState, activeDog.id) - Virtueller Trainer (rein statistisch): üben/festigen/entdecken/levelup Empfehlungen auf Basis exercise_progress + sessions, Prognose bis 80% - Stand erfassen Modal: alle Übungen auf einmal setzen (onboarding) - Erfolgsindikatoren auf Karten: Ø-Quote + Trend-Pfeil + Anzahl Sessions - exercise_progress → synthetische Stats im Trainer (ohne Sessions nutzbar) - Levelup: Tricks empfehlen wenn ≥4 Grundkommandos sitzen - Kommandos & Fähigkeiten im Hundeprofil + öffentlichem Profil - 2 neue Problemverhalten-Übungen: Bellen/Kläffen, Enttriggern Mobile/UI-Fixes: - Übungskarten: Name + Difficulty oben, Buttons eigene Zeile (kein Umbruch) - Trainingsgrundlagen: Padding in allen Karten, Hinweis-Boxen Dark-Mode-sicher - Tab-Sichtbarkeit: Trainer/Suggestions nur auf Übungs-Tabs - Tagebuch FAB (Neu-Eintrag Button) + Quick-Add Eintrag - FAB Abstand fix (nav-bottom-height + safe-bottom) - Suggestion-Karten rgba (Dark-Mode) - routes.js + uebungen.js: alle Hellfarben → rgba (Dark-Mode-sicher) - ui.js: UI.toast als callable Function-Object (war nur plain Object) KI & Backend: - KI_MODE=cloud + ANTHROPIC_API_KEY gesetzt - ki.py: Cloud-Fallback wenn local nicht erreichbar + KI_MODE=cloud - KI-Trainer Tageslimit 10 Anfragen/User + ki_daily_calls Tabelle - Admin-Panel: KI-Nutzung (heute/Monat/User) - Status-Report Fix (lost-Tabelle) → 06:00 + 18:00 täglich - Wiki-Anreicherung läuft jetzt (50 Rassen Startup, 20/Nacht) - landing.html: Trainings-Features in JSON-LD + Feature-Karten
This commit is contained in:
parent
2b442ebd98
commit
44081a6b9d
16 changed files with 938 additions and 117 deletions
|
|
@ -148,6 +148,8 @@ window.Page_dog_profile = (() => {
|
|||
</div>
|
||||
` : ''}
|
||||
|
||||
<div id="dp-skills" style="margin-bottom:var(--space-5);text-align:left"></div>
|
||||
|
||||
${dog.is_public ? `
|
||||
<div style="background:var(--c-primary-subtle);border:1px solid var(--c-primary-light);
|
||||
border-radius:var(--radius-md);padding:var(--space-4);
|
||||
|
|
@ -215,6 +217,9 @@ window.Page_dog_profile = (() => {
|
|||
_showPhotoEditor(dog);
|
||||
});
|
||||
|
||||
// Skills laden
|
||||
_loadSkills(dog);
|
||||
|
||||
// Sitter-Zugang laden (nur für Besitzer)
|
||||
if (dog.user_id === _appState.user?.id) {
|
||||
_loadSittingAccess(dog.id);
|
||||
|
|
@ -255,6 +260,70 @@ window.Page_dog_profile = (() => {
|
|||
// Edit- und Add-Klicks laufen über Event-Delegation in init() — keine direkten Listener nötig.
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// FÄHIGKEITEN & KOMMANDOS
|
||||
// ----------------------------------------------------------
|
||||
async function _loadSkills(dog) {
|
||||
const el = document.getElementById('dp-skills');
|
||||
if (!el) return;
|
||||
|
||||
const skills = await API.dogs.getSkills(dog.id).catch(() => null);
|
||||
if (!skills || !skills.length) { el.innerHTML = ''; return; }
|
||||
|
||||
const sitzt = skills.filter(s => s.status === 'sitzt');
|
||||
const meistens = skills.filter(s => s.status === 'meistens');
|
||||
|
||||
const badge = (skill, type) => {
|
||||
const isGreen = type === 'sitzt';
|
||||
return `<span style="
|
||||
display:inline-flex;align-items:center;gap:4px;
|
||||
padding:3px 10px;border-radius:var(--radius-full,999px);
|
||||
font-size:var(--text-xs);font-weight:var(--weight-semibold);
|
||||
background:${isGreen ? '#f0fdf4' : '#fff7ed'};
|
||||
color:${isGreen ? '#15803d' : '#c2410c'};
|
||||
border:1px solid ${isGreen ? '#86efac' : '#fdba74'}">
|
||||
<svg class="ph-icon" style="width:11px;height:11px" aria-hidden="true">
|
||||
<use href="/icons/phosphor.svg#${isGreen ? 'check' : 'fire'}"></use>
|
||||
</svg>
|
||||
${_esc(skill.exercise_name)}
|
||||
</span>`;
|
||||
};
|
||||
|
||||
const sitztBlock = sitzt.length ? `
|
||||
<div style="margin-bottom:var(--space-3)">
|
||||
<div style="font-size:var(--text-xs);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text-secondary);margin-bottom:var(--space-2);
|
||||
text-transform:uppercase;letter-spacing:.04em">Sitzt</div>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:var(--space-2)">
|
||||
${sitzt.map(s => badge(s, 'sitzt')).join('')}
|
||||
</div>
|
||||
</div>` : '';
|
||||
|
||||
const meistensBlock = meistens.length ? `
|
||||
<div>
|
||||
<div style="font-size:var(--text-xs);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text-secondary);margin-bottom:var(--space-2);
|
||||
text-transform:uppercase;letter-spacing:.04em">Übt noch</div>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:var(--space-2)">
|
||||
${meistens.map(s => badge(s, 'meistens')).join('')}
|
||||
</div>
|
||||
</div>` : '';
|
||||
|
||||
el.innerHTML = `
|
||||
<div class="card" style="padding:var(--space-4)">
|
||||
<div style="display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-3)">
|
||||
<svg class="ph-icon" style="width:16px;height:16px;color:var(--c-primary)" aria-hidden="true">
|
||||
<use href="/icons/phosphor.svg#list-checks"></use>
|
||||
</svg>
|
||||
<span style="font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--c-text)">
|
||||
Kommandos & Fähigkeiten
|
||||
</span>
|
||||
</div>
|
||||
${sitztBlock}
|
||||
${meistensBlock}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// SITTER-ZUGANG
|
||||
// ----------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue