Feature: Übungen Desktop 2-zeilige Tabs + globale Suche über alle Kategorien — SW by-v496, APP_VER 473

This commit is contained in:
rene 2026-04-29 13:07:41 +02:00
parent 81ee1a063e
commit a3679354c8
4 changed files with 52 additions and 15 deletions

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
const APP_VER = '472'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VER = '473'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const App = (() => {

View file

@ -578,8 +578,11 @@ window.Page_uebungen = (() => {
</div>
`;
_container.querySelector('#ueb-quicksetup-btn').addEventListener('click', _openQuickSetupModal);
_container.querySelector('#ueb-tabs')?.style.setProperty('--ueb-tab-cols', Math.ceil(TABS.length / 2));
_container.querySelector('#ueb-search')?.addEventListener('input', e => {
_searchQuery = e.target.value.trim().toLowerCase();
const tabs = _container.querySelector('#ueb-tabs');
if (tabs) tabs.style.display = _searchQuery ? 'none' : '';
_renderContent();
});
_bindTabs();
@ -961,12 +964,15 @@ window.Page_uebungen = (() => {
case 'hundesport':
case 'koerperpflege':
case 'welpe-basics': {
const list = _exercisesByTab[_activeTab] || [];
el.innerHTML = list.length
? _renderUebungsList(list)
: `<div style="padding:var(--space-6);text-align:center;color:var(--c-text-muted)">
${UI.icon('spinner')} Übungen werden geladen
</div>`;
if (_searchQuery) {
el.innerHTML = _renderAllResults();
} else {
const list = _exercisesByTab[_activeTab] || [];
const html = list.length ? _renderUebungsList(list) : '';
el.innerHTML = html
? `<div style="padding:var(--space-4);display:flex;flex-direction:column;gap:var(--space-4)">${html}</div>`
: `<div style="padding:var(--space-6);text-align:center;color:var(--c-text-muted)">${UI.icon('spinner')} Übungen werden geladen…</div>`;
}
break;
}
case 'grundlagen': el.innerHTML = _renderGrundlagen(); break;
@ -1004,16 +1010,33 @@ window.Page_uebungen = (() => {
(u.beschreibung || '').toLowerCase().includes(_searchQuery)
)
: list;
if (!filtered.length) {
if (!filtered.length) return '';
return filtered.map((u, i) => _renderCard(u, i)).join('');
}
function _renderAllResults() {
const q = _searchQuery;
const allExercises = Object.entries(_exercisesByTab)
.filter(([tab]) => !['grundlagen','ki-trainer'].includes(tab))
.flatMap(([, list]) => list)
.filter(u =>
u.name.toLowerCase().includes(q) ||
(u.beschreibung || '').toLowerCase().includes(q)
);
if (!allExercises.length) {
return `<div style="padding:var(--space-8);text-align:center;color:var(--c-text-muted)">
${UI.icon('magnifying-glass')} Keine Übungen gefunden für ${_esc(_searchQuery)}"
${UI.icon('magnifying-glass')} Keine Übungen gefunden für ${_esc(q)}"
</div>`;
}
return `
<div style="padding:var(--space-4);display:flex;flex-direction:column;gap:var(--space-4)">
${filtered.map((u, i) => _renderCard(u, i)).join('')}
</div>
`;
return `<div style="padding:var(--space-4);display:flex;flex-direction:column;gap:var(--space-4)">
${allExercises.map((u, i) => `
<div>
<div style="font-size:var(--text-xs);font-weight:var(--weight-semibold);
color:var(--c-text-muted);text-transform:uppercase;letter-spacing:.05em;
margin-bottom:var(--space-1);padding:0 var(--space-2)">${_esc(u.kategorie)}</div>
${_renderCard(u, i)}
</div>`).join('')}
</div>`;
}
function _sessionStatsChip(tab, name) {