massive frontend refactoring (works good)
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
import { state } from '../state.js';
|
||||
import { renderExercise } from './exercise-card.js';
|
||||
import { renderCardioItem } from './cardio-card.js';
|
||||
import { formatDate } from '../utils.js';
|
||||
|
||||
export function renderWorkoutCard(w) {
|
||||
const isActive = !w.endTime;
|
||||
const isExpanded = state.expandedWorkoutId === w.id;
|
||||
const isReadOnly = w.synced && w.endTime;
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.className = 'workout-accordion';
|
||||
|
||||
const headerClass = `workout-header ${isActive ? 'active' : 'completed'}`;
|
||||
const dateStr = formatDate(w.startTime);
|
||||
const typeStr = w.type || 'тип не выбран';
|
||||
const exCount = w.exercises.length;
|
||||
const cardioCount = w.cardio.length;
|
||||
|
||||
let statusBadge;
|
||||
if (isReadOnly) statusBadge = '<span class="workout-badge synced-badge">✓ архив</span>';
|
||||
else if (w.synced) statusBadge = '<span class="workout-badge synced-badge">✓</span>';
|
||||
else statusBadge = '<span class="workout-badge dirty">● не сохранено</span>';
|
||||
|
||||
const editDateBtn = !isReadOnly
|
||||
? `<span class="editable-date" onclick="event.stopPropagation(); WL.editWorkoutDate('${w.id}')">
|
||||
<span class="edit-icon">✎</span>
|
||||
</span>`
|
||||
: '';
|
||||
|
||||
div.innerHTML = `
|
||||
<div class="${headerClass}" onclick="WL.toggleWorkout('${w.id}')">
|
||||
<div>
|
||||
<div style="font-weight:600;">${isActive ? '🔥 Тренировка' : '✅ Завершена'}</div>
|
||||
<div class="workout-meta">${dateStr} ${editDateBtn} • ${typeStr}</div>
|
||||
<div class="workout-meta">Упр: ${exCount} • Кардио: ${cardioCount}</div>
|
||||
</div>
|
||||
<div>${statusBadge} <span class="chevron ${isExpanded ? 'open' : ''}">›</span></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const body = document.createElement('div');
|
||||
body.className = `workout-body ${isExpanded ? 'expanded' : ''}`;
|
||||
if (isExpanded) {
|
||||
body.appendChild(renderWorkoutDetails(w));
|
||||
}
|
||||
div.appendChild(body);
|
||||
return div;
|
||||
}
|
||||
|
||||
export function renderWorkoutDetails(w) {
|
||||
const wrap = document.createElement('div');
|
||||
const isActive = !w.endTime;
|
||||
const isReadOnly = w.synced && w.endTime;
|
||||
|
||||
if (isReadOnly) {
|
||||
const banner = document.createElement('div');
|
||||
banner.className = 'read-only-banner';
|
||||
banner.textContent = '🔒 Тренировка в архиве — только просмотр';
|
||||
wrap.appendChild(banner);
|
||||
}
|
||||
|
||||
// Тип тренировки
|
||||
const typeCard = document.createElement('div');
|
||||
typeCard.className = 'card';
|
||||
if (isReadOnly) {
|
||||
typeCard.innerHTML = `
|
||||
<div class="field-group" style="margin:0;">
|
||||
<span class="text-muted text-small">Тип тренировки</span>
|
||||
<div style="font-weight:600; margin-top:4px;">${w.type || '—'}</div>
|
||||
</div>`;
|
||||
} else {
|
||||
typeCard.innerHTML = `
|
||||
<label class="field-group" style="margin:0;">
|
||||
<span>Тип тренировки</span>
|
||||
<select onchange="App.getWorkout('${w.id}').type = this.value; App.saveAndRender();">
|
||||
<option value="">— выберите —</option>
|
||||
<option ${w.type==='грудь-руки'?'selected':''}>грудь-руки</option>
|
||||
<option ${w.type==='ноги'?'selected':''}>ноги</option>
|
||||
<option ${w.type==='спина-плечи'?'selected':''}>спина-плечи</option>
|
||||
<option ${w.type==='круговая'?'selected':''}>круговая</option>
|
||||
<option ${w.type==='силовая'?'selected':''}>силовая</option>
|
||||
<option ${w.type==='многоповторная'?'selected':''}>многоповторная</option>
|
||||
</select>
|
||||
</label>`;
|
||||
}
|
||||
wrap.appendChild(typeCard);
|
||||
|
||||
// Кнопки добавления
|
||||
if (isActive && !isReadOnly) {
|
||||
const addSection = document.createElement('div');
|
||||
addSection.className = 'add-section';
|
||||
addSection.innerHTML = `
|
||||
<button class="btn btn-secondary" onclick="EL.addExercise('${w.id}')">+ Упражнение</button>
|
||||
<button class="btn btn-secondary" onclick="CL.addCardio('${w.id}')">+ Кардио</button>
|
||||
`;
|
||||
wrap.appendChild(addSection);
|
||||
}
|
||||
|
||||
// Кардио: разминка сверху
|
||||
const cardioWarmup = w.cardio.filter(c => c.purpose === 'warmup' || c.purpose === 'separate');
|
||||
const cardioCooldown = w.cardio.filter(c => c.purpose === 'cooldown');
|
||||
|
||||
if (cardioWarmup.length > 0) {
|
||||
const title = document.createElement('h4');
|
||||
title.style.margin = '16px 0 8px';
|
||||
title.textContent = '🔥 Разминка / Кардио';
|
||||
wrap.appendChild(title);
|
||||
cardioWarmup.forEach(c => wrap.appendChild(renderCardioItem(w.id, c, isReadOnly)));
|
||||
}
|
||||
|
||||
// Упражнения
|
||||
[...w.exercises].reverse().forEach(ex => {
|
||||
wrap.appendChild(renderExercise(w, ex, isReadOnly));
|
||||
});
|
||||
|
||||
// Заминка внизу
|
||||
if (cardioCooldown.length > 0) {
|
||||
const title = document.createElement('h4');
|
||||
title.style.margin = '16px 0 8px';
|
||||
title.textContent = '🧘 Заминка';
|
||||
wrap.appendChild(title);
|
||||
cardioCooldown.forEach(c => wrap.appendChild(renderCardioItem(w.id, c, isReadOnly)));
|
||||
}
|
||||
|
||||
// Комментарий
|
||||
const notesCard = document.createElement('div');
|
||||
notesCard.className = 'card mt-10';
|
||||
if (isReadOnly) {
|
||||
notesCard.innerHTML = `
|
||||
<div class="field-group" style="margin:0;">
|
||||
<span class="text-muted text-small">Комментарий</span>
|
||||
<div style="margin-top:4px; white-space:pre-wrap;">${w.notes || '—'}</div>
|
||||
</div>`;
|
||||
} else {
|
||||
notesCard.innerHTML = `
|
||||
<label class="field-group" style="margin:0;">
|
||||
<span>Комментарий к тренировке</span>
|
||||
<textarea placeholder="Как прошла тренировка...">${w.notes || ''}</textarea>
|
||||
</label>`;
|
||||
notesCard.querySelector('textarea').oninput = (e) => {
|
||||
w.notes = e.target.value;
|
||||
window.App.saveAndRender();
|
||||
};
|
||||
}
|
||||
wrap.appendChild(notesCard);
|
||||
|
||||
// Блок завершения
|
||||
const finishBlock = document.createElement('div');
|
||||
finishBlock.className = 'finish-block';
|
||||
if (isReadOnly) {
|
||||
finishBlock.innerHTML = `
|
||||
<h3>🔒 Архив</h3>
|
||||
<p class="text-muted text-small">Тренировка синхронизирована и завершена. Редактирование недоступно.</p>`;
|
||||
} else if (isActive) {
|
||||
finishBlock.innerHTML = `
|
||||
<h3>Завершение тренировки</h3>
|
||||
<p class="text-muted text-small">После завершения данные останутся локально до синхронизации</p>
|
||||
<button class="btn btn-danger" onclick="WL.finishWorkout('${w.id}')">⏹ Закончить тренировку</button>`;
|
||||
} else {
|
||||
finishBlock.innerHTML = `
|
||||
<h3>Тренировка завершена</h3>
|
||||
<p class="text-muted text-small">До синхронизации можно редактировать</p>
|
||||
<button class="btn btn-danger" onclick="WL.deleteWorkout('${w.id}')">🗑 Удалить</button>`;
|
||||
}
|
||||
wrap.appendChild(finishBlock);
|
||||
|
||||
return wrap;
|
||||
}
|
||||
Reference in New Issue
Block a user