Files
gym-bro/frontend/js/logic/settings.js
T

186 lines
8.3 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 { state, saveState } from '../state.js';
import { showEditExerciseDialog } from '../modals/edit-exercise-modal.js';
export function showSettings() {
const app = document.getElementById('app');
app.innerHTML = '';
const screen = document.createElement('div');
screen.className = 'settings-screen';
screen.innerHTML = `
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;">
<h2>⚙️ Настройки</h2>
<button class="btn btn-small btn-secondary" onclick="App.backToMain()">← Назад</button>
</div>
<div class="settings-section">
<h3>📋 Справочник упражнений</h3>
<p class="text-muted text-small mb-10">Управляйте списком упражнений и привязывайте их к типам тренировок.</p>
<div class="field-group">
<div style="display:flex; gap:6px;">
<input type="text" id="new-ref-exercise" placeholder="Новое упражнение...">
<select id="new-ref-type" style="width: auto; min-width: 120px;">
<option value="">тип...</option>
<option value="грудь-руки">грудь-руки</option>
<option value="ноги">ноги</option>
<option value="спина-плечи">спина-плечи</option>
<option value="круговая">круговая</option>
<option value="силовая">силовая</option>
<option value="многоповторная">многоповторная</option>
</select>
<button class="btn btn-small" style="width:auto; padding: 0 20px;" onclick="SettingsLogic.addRefExercise()">+</button>
</div>
</div>
<div id="ref-exercises-list"></div>
</div>
<div class="settings-section">
<h3>📏 Замеры тела</h3>
<div id="body-metrics-list"></div>
</div>
<div class="settings-section">
<h3>🗑 Данные</h3>
<button class="btn btn-danger" onclick="SettingsLogic.clearAllData()">Очистить все данные</button>
</div>
`;
app.appendChild(screen);
_renderRefExercises();
_renderBodyMetricsList();
}
export function addRefExercise() {
const input = document.getElementById('new-ref-exercise');
const typeSelect = document.getElementById('new-ref-type');
const name = input.value.trim();
if (!name) return;
const normalizedName = name.trim().toLowerCase();
const exists = state.exerciseRef.find(
e => e.name.trim().toLowerCase() === normalizedName
);
if (!exists) {
state.exerciseRef.push({
id: (state.nextId++).toString(),
name: name.trim(),
workoutType: typeSelect.value,
});
}
saveState();
input.value = '';
typeSelect.value = '';
_renderRefExercises();
}
export function deleteRefExercise(id) {
if (!confirm('Удалить из справочника? (в тренировках останется)')) return;
state.exerciseRef = state.exerciseRef.filter(e => e.id !== id);
saveState();
_renderRefExercises();
}
export function updateRefExerciseType(id, newType) {
const ex = state.exerciseRef.find(e => e.id === id);
if (ex) {
ex.workoutType = newType;
saveState();
}
}
export function editRefExercise(id) {
const ex = state.exerciseRef.find(e => e.id === id);
if (!ex) return;
showEditExerciseDialog(ex, (updatedData) => {
if (!updatedData) return;
Object.assign(ex, updatedData);
saveState();
_renderRefExercises();
});
}
export function clearAllData() {
if (!confirm('Удалить ВСЕ данные? Это действие необратимо!')) return;
if (!confirm('Точно уверены?')) return;
localStorage.clear();
location.reload();
}
export function _renderRefExercises() {
const list = document.getElementById('ref-exercises-list');
if (!list) return;
if (state.exerciseRef.length === 0) {
list.innerHTML = '<p class="text-muted text-small">Справочник пуст</p>';
return;
}
const sorted = [...state.exerciseRef].sort((a, b) => {
if (a.workoutType !== b.workoutType) return (a.workoutType || '').localeCompare(b.workoutType || '');
return a.name.localeCompare(b.name);
});
list.innerHTML = sorted.map(ex => {
let count = 0;
state.workouts.forEach(w => {
w.exercises.forEach(e => {
if (e.name.trim().toLowerCase() === ex.name.trim().toLowerCase()) count++;
});
});
return `
<div class="exercise-ref-item">
<div style="flex:1;">
<span class="name">${ex.name}</span>
<span class="count">(${count}×)</span>
${ex.workoutType ? `<span class="type-badge">${ex.workoutType}</span>` : ''}
</div>
<div style="display:flex; gap:4px; align-items:center;">
<select onchange="SettingsLogic.updateRefExerciseType('${ex.id}', this.value)"
style="width:auto; min-width:100px; padding:6px; font-size:0.8rem;">
<option value="">тип...</option>
<option value="грудь-руки" ${ex.workoutType==='грудь-руки'?'selected':''}>грудь-руки</option>
<option value="ноги" ${ex.workoutType==='ноги'?'selected':''}>ноги</option>
<option value="спина-плечи" ${ex.workoutType==='спина-плечи'?'selected':''}>спина-плечи</option>
<option value="круговая" ${ex.workoutType==='круговая'?'selected':''}>круговая</option>
<option value="силовая" ${ex.workoutType==='силовая'?'selected':''}>силовая</option>
<option value="многоповторная" ${ex.workoutType==='многоповторная'?'selected':''}>многоповторная</option>
</select>
<button class="icon-btn" onclick="SettingsLogic.editRefExercise('${ex.id}')">✎</button>
<button class="icon-btn danger" onclick="SettingsLogic.deleteRefExercise('${ex.id}')">✕</button>
</div>
</div>
`;
}).join('');
}
export function _renderBodyMetricsList() {
const list = document.getElementById('body-metrics-list');
if (!list) return;
if (state.bodyMetrics.length === 0) {
list.innerHTML = '<p class="text-muted text-small">Нет замеров</p>';
return;
}
list.innerHTML = state.bodyMetrics.map(m => {
const date = new Date(m.date);
const dateStr = date.toLocaleDateString('ru-RU') + ' ' + date.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' });
const parts = [];
if (m.weight) parts.push(`⚖️ ${m.weight} кг`);
if (m.chest) parts.push(`📏 ${m.chest} см`);
if (m.waist) parts.push(`📏 ${m.waist} см`);
if (m.hips) parts.push(`📏 ${m.hips} см`);
if (m.arms) parts.push(`💪 ${m.arms} см`);
if (m.legs) parts.push(`🦵 ${m.legs} см`);
return `
<div class="exercise-ref-item">
<div>
<div style="font-weight:500;">${dateStr}</div>
<div class="text-small text-muted">${parts.join(' • ') || '—'}</div>
</div>
<div style="display:flex; gap:4px;">
<button class="icon-btn" onclick="ML.editBodyMetric('${m.id}')">✎</button>
<button class="icon-btn danger" onclick="ML.deleteMetric('${m.id}')">✕</button>
</div>
</div>
`;
}).join('');
}
window.SettingsLogic = {
show: showSettings,
addRefExercise, deleteRefExercise, updateRefExerciseType,
editRefExercise, clearAllData,
_renderRefExercises, _renderBodyMetricsList,
};