Files
gym-bro/frontend/js/modals/set-modal.js
T

128 lines
6.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { showModal, closeModal, stepperHtml } from './modal-base.js';
import { formatShortDate, formatSet } from '../utils.js';
let _data = {};
let _cb = null;
export function showSetDialog(existingSet, history, callback) {
_cb = callback;
const isEdit = !!existingSet;
const isDropset = existingSet?.isDropset || false;
let historyHtml = '';
if (history?.length) {
const rows = history.map(h => `<div class="history-hint-row">
<span class="history-hint-date">${formatShortDate(h.date)}</span>
<span class="history-hint-sets">${h.sets.map(formatSet).join(', ')}</span>
</div>`).join('');
historyHtml = `<div class="history-hint"><div class="history-hint-title">📊 Прошлые тренировки</div>${rows}</div>`;
}
showModal(`<div class="modal-content">
<h3 class="modal-title">${isEdit ? 'Редактировать' : 'Новый'} подход</h3>
${historyHtml}
<div class="field-group"><label style="display:flex;align-items:center;gap:8px;">
<input type="checkbox" id="m-set-dropset" ${isDropset ? 'checked' : ''} onchange="SetModal.toggleDropset()" style="width:auto;">
Это дроп-сет</label></div>
<div id="m-set-normal" class="${isDropset ? 'hidden' : ''}">
<div class="field-row">
<div class="field-group"><label>Вес (кг)</label>${stepperHtml('m-set-weight', existingSet?.weight ?? '', 0.5, 'Вес')}</div>
<div class="field-group"><label>Повторения</label>${stepperHtml('m-set-reps', existingSet?.reps ?? '', 1, 'Повт.', 'numeric')}</div>
</div></div>
<div id="m-set-dropset-block" class="${isDropset ? '' : 'hidden'}">
<div id="m-subsets-list"></div>
<button class="btn btn-ghost mt-10" style="width:100%;" onclick="SetModal.addSubset()">+ Сбрасывание</button></div>
<div class="field-group"><label>Оценка (1-5)</label>
<div class="rating-grid" id="m-rating-grid">
${[1,2,3,4,5].map(r => `<button class="rating-btn ${existingSet?.rating===r?'active':''}" data-rating="${r}" onclick="SetModal.rating(${r})">${r}</button>`).join('')}
</div></div>
<div class="btn-row">
<button class="btn btn-secondary" onclick="ModalBase.closeOnBg({target:document.querySelector('.modal-overlay')})">Отмена</button>
<button class="btn btn-success" onclick="SetModal.submit()">Сохранить</button></div>
</div>`);
_data = {
isDropset, rating: existingSet?.rating || 3,
subSets: existingSet?.subSets ? JSON.parse(JSON.stringify(existingSet.subSets)) : [],
};
if (isDropset) { if (!_data.subSets.length) addSubset(); else renderSubsets(); }
rating(_data.rating);
}
export function toggleDropset() {
_data.isDropset = document.getElementById('m-set-dropset').checked;
document.getElementById('m-set-normal').classList.toggle('hidden', _data.isDropset);
document.getElementById('m-set-dropset-block').classList.toggle('hidden', !_data.isDropset);
if (_data.isDropset && !_data.subSets.length) addSubset();
else if (_data.isDropset) renderSubsets();
}
export function addSubset() {
const last = _data.subSets[_data.subSets.length - 1];
_data.subSets.push({ weight: last?.weight || '', reps: last?.reps || '' });
renderSubsets();
}
export function renderSubsets() {
document.getElementById('m-subsets-list').innerHTML = _data.subSets.map((s, i) => `
<div class="stepper-row">
<div class="stepper-field">
<button type="button" class="stepper-btn" onclick="SetModal.stepSubset(${i}, 'weight', -0.5)">−</button>
<input type="number" id="m-sw-${i}" step="0.5" value="${s.weight || ''}" placeholder="Вес" inputmode="decimal" oninput="SetModal.updateSubset(${i}, 'weight', this.value)">
<button type="button" class="stepper-btn" onclick="SetModal.stepSubset(${i}, 'weight', 0.5)">+</button>
</div>
<div class="stepper-field">
<button type="button" class="stepper-btn" onclick="SetModal.stepSubset(${i}, 'reps', -1)">−</button>
<input type="number" id="m-sr-${i}" step="1" value="${s.reps || ''}" placeholder="Повт." inputmode="numeric" oninput="SetModal.updateSubset(${i}, 'reps', this.value)">
<button type="button" class="stepper-btn" onclick="SetModal.stepSubset(${i}, 'reps', 1)">+</button>
</div>
<button class="icon-btn danger" onclick="SetModal.removeSubset(${i})">✕</button>
</div>
`).join('');
}
export function updateSubset(i, field, value) {
_data.subSets[i][field] = value;
}
export function stepSubset(i, field, delta) {
const current = parseFloat(_data.subSets[i][field]) || 0;
const step = field === 'weight' ? 0.5 : 1;
const newVal = Math.max(0, current + delta);
_data.subSets[i][field] = parseFloat((Math.round(newVal / step) * step).toFixed(4));
renderSubsets(); // Перерисовываем, чтобы обновить значение в input
}
export function removeSubset(i) {
_data.subSets.splice(i, 1);
renderSubsets();
}
export function rating(r) {
_data.rating = r;
document.querySelectorAll('#m-rating-grid .rating-btn').forEach(b => b.classList.toggle('active', +b.dataset.rating === r));
}
export function submit() {
if (_data.isDropset) {
_data.subSets.forEach((s, i) => {
const w = document.getElementById(`m-sw-${i}`);
const r = document.getElementById(`m-sr-${i}`);
if (w) s.weight = w.value; if (r) s.reps = r.value;
});
if (!_data.subSets.length) { alert('Добавьте сбрасывание'); return; }
closeModal(); _cb?.({ isDropset: true, subSets: _data.subSets.map(s => ({ weight: parseFloat(s.weight)||0, reps: parseInt(s.reps)||0 })), rating: _data.rating });
} else {
const w = parseFloat(document.getElementById('m-set-weight').value);
const r = parseInt(document.getElementById('m-set-reps').value);
if (!w && !r) { alert('Укажите вес и повторения'); return; }
closeModal(); _cb?.({ isDropset: false, weight: w||0, reps: r||0, rating: _data.rating });
}
}
// Обновляем экспорт в window
window.SetModal = {
toggleDropset, addSubset, removeSubset, rating, submit,
updateSubset, stepSubset
};