Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 54 additions & 18 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,7 @@ <h2 class="modal-title" id="modal-title"></h2>

function renderChips(containerId, values, filterKey, initialLimit = null) {
const container = document.getElementById(containerId);
container.innerHTML = '';
container.replaceChildren();

const toShow = initialLimit ? values.slice(0, initialLimit) : values;
const rest = initialLimit ? values.slice(initialLimit) : [];
Expand Down Expand Up @@ -1309,13 +1309,18 @@ <h2 class="modal-title" id="modal-title"></h2>

// ── Rendering ──────────────────────────────────────
function renderGrid() {
gridEl.innerHTML = '';
gridEl.replaceChildren();
const slice = state.filtered.slice(0, state.pageSize);

if (slice.length === 0) {
const empty = document.createElement('div');
empty.className = 'empty-state';
empty.innerHTML = '<p>🔍</p><p>No exercises found</p>';
const icon = document.createElement('p');
icon.textContent = '🔍';
const message = document.createElement('p');
message.textContent = 'No exercises found';
empty.appendChild(icon);
empty.appendChild(message);
gridEl.appendChild(empty);
spinnerEl.classList.remove('visible');
return;
Expand Down Expand Up @@ -1397,17 +1402,24 @@ <h2 class="modal-title" id="modal-title"></h2>
}

function renderSkeletons(count) {
gridEl.innerHTML = '';
gridEl.replaceChildren();
const frag = document.createDocumentFragment();
for (let i = 0; i < count; i++) {
const card = document.createElement('div');
card.className = 'skeleton-card';
card.innerHTML = `
<div class="skeleton-media"></div>
<div class="skeleton-body">
<div class="skeleton-line"></div>
<div class="skeleton-line short"></div>
</div>`;
const media = document.createElement('div');
media.className = 'skeleton-media';
const body = document.createElement('div');
body.className = 'skeleton-body';
const line = document.createElement('div');
line.className = 'skeleton-line';
const shortLine = document.createElement('div');
shortLine.className = 'skeleton-line short';

body.appendChild(line);
body.appendChild(shortLine);
card.appendChild(media);
card.appendChild(body);
frag.appendChild(card);
}
gridEl.appendChild(frag);
Expand All @@ -1423,7 +1435,7 @@ <h2 class="modal-title" id="modal-title"></h2>
}

function updateActiveBadges() {
activeFilEl.innerHTML = '';
activeFilEl.replaceChildren();
const { category, equipment, target } = state.filters;
let hasAny = false;

Expand All @@ -1432,7 +1444,15 @@ <h2 class="modal-title" id="modal-title"></h2>
hasAny = true;
const badge = document.createElement('span');
badge.className = 'active-badge';
badge.innerHTML = `${val}<button class="active-badge-remove" data-filter="${key}" data-value="${val}" aria-label="Remove ${val}">×</button>`;
const removeBtn = document.createElement('button');
removeBtn.className = 'active-badge-remove';
removeBtn.dataset.filter = key;
removeBtn.dataset.value = val;
removeBtn.setAttribute('aria-label', `Remove ${val}`);
removeBtn.textContent = '×';

badge.appendChild(document.createTextNode(val));
badge.appendChild(removeBtn);
activeFilEl.appendChild(badge);
});
};
Expand Down Expand Up @@ -1473,7 +1493,7 @@ <h2 class="modal-title" id="modal-title"></h2>
modalGif.alt = ex.name;

// Meta chips
modalMeta.innerHTML = '';
modalMeta.replaceChildren();
const metaItems = [
{ label: 'Body Part', value: ex.body_part || ex.category },
{ label: 'Equipment', value: ex.equipment },
Expand All @@ -1482,12 +1502,20 @@ <h2 class="modal-title" id="modal-title"></h2>
metaItems.forEach(({ label, value }) => {
const chip = document.createElement('div');
chip.className = 'meta-chip';
chip.innerHTML = `<span class="meta-chip-label">${label}</span><span class="meta-chip-value">${value}</span>`;
const labelEl = document.createElement('span');
labelEl.className = 'meta-chip-label';
labelEl.textContent = label;
const valueEl = document.createElement('span');
valueEl.className = 'meta-chip-value';
valueEl.textContent = value;

chip.appendChild(labelEl);
chip.appendChild(valueEl);
modalMeta.appendChild(chip);
});

// Muscles
modalMuscles.innerHTML = '';
modalMuscles.replaceChildren();
const primaryMuscles = ex.target ? [ex.target] : [];
const secondaryRaw = ex.secondary_muscles || (ex.muscle_group ? [ex.muscle_group] : []);
const secondaryMuscles = secondaryRaw.filter(m => m !== ex.target);
Expand Down Expand Up @@ -1524,7 +1552,7 @@ <h2 class="modal-title" id="modal-title"></h2>
if (primaryMuscles.length > 0 || secondaryMuscles.length > 0) modalMuscles.appendChild(musclesGrid);

// Instructions — format is always { en: [...], es: [...], it: [...], tr: [...], ru: [...] }
modalInstr.innerHTML = '';
modalInstr.replaceChildren();
const LANG_LABELS = { en: 'English', es: 'Español', it: 'Italiano', tr: 'Türkçe', ru: 'Русский', zh: '简体中文' };
const langs = ['en', 'es', 'it', 'tr', 'ru', 'zh']
.map(code => ({ code, steps: ex.instruction_steps?.[code] ?? [] }))
Expand All @@ -1540,11 +1568,19 @@ <h2 class="modal-title" id="modal-title"></h2>
list.className = 'instructions-list';

function renderSteps(steps) {
list.innerHTML = '';
list.replaceChildren();
steps.forEach((step, i) => {
const li = document.createElement('li');
li.className = 'instruction-step';
li.innerHTML = `<span class="step-num">${i + 1}</span><span class="step-text">${step}</span>`;
const stepNum = document.createElement('span');
stepNum.className = 'step-num';
stepNum.textContent = String(i + 1);
const stepText = document.createElement('span');
stepText.className = 'step-text';
stepText.textContent = step;

li.appendChild(stepNum);
li.appendChild(stepText);
list.appendChild(li);
});
}
Expand Down
28 changes: 27 additions & 1 deletion setup.html
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,32 @@ <h2 class="section-title">Ask Your LLM</h2>
const llmPromptBox = document.getElementById('llm-prompt');
const copyPromptBtn = document.getElementById('copy-prompt-btn');

function setCopyPromptButtonDefault() {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', '14');
svg.setAttribute('height', '14');
svg.setAttribute('viewBox', '0 0 16 16');
svg.setAttribute('fill', 'none');
svg.setAttribute('stroke', 'currentColor');
svg.setAttribute('stroke-width', '1.8');
svg.setAttribute('stroke-linecap', 'round');
svg.setAttribute('stroke-linejoin', 'round');

const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('x', '4');
rect.setAttribute('y', '4');
rect.setAttribute('width', '9');
rect.setAttribute('height', '11');
rect.setAttribute('rx', '1.5');

const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', 'M11 4V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h1');

svg.appendChild(rect);
svg.appendChild(path);
copyPromptBtn.replaceChildren(svg, document.createTextNode(' Copy Prompt'));
}

function renderLlmPrompt() {
llmPromptBox.value = buildLlmPrompt(currentFw, currentLlmDb);
}
Expand Down Expand Up @@ -1665,7 +1691,7 @@ <h2 class="section-title">Ask Your LLM</h2>
copyPromptBtn.textContent = '✓ Copied!';
copyPromptBtn.classList.add('copied');
setTimeout(() => {
copyPromptBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="9" height="11" rx="1.5"/><path d="M11 4V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h1"/></svg> Copy Prompt`;
setCopyPromptButtonDefault();
copyPromptBtn.classList.remove('copied');
}, 2500);
});
Expand Down