Добавлен график веса с целевой линией (58 кг за 8 недель)

This commit is contained in:
Madina 2026-08-10 09:18:05 +00:00
parent 14fb2b7e81
commit c15d07a9ad

View File

@ -490,6 +490,19 @@
<button class="btn" onclick="addProgress()">Записать</button> <button class="btn" onclick="addProgress()">Записать</button>
</div> </div>
<div class="progress-stats" id="progress-stats"></div> <div class="progress-stats" id="progress-stats"></div>
<!-- График веса -->
<div style="margin-top: 30px; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); border-radius: 15px; padding: 25px;">
<h3>📈 График веса</h3>
<p style="margin-bottom: 15px; color: #666;">Цель: <strong>58 кг</strong> через 8 недель</p>
<canvas id="weight-chart" height="80" style="width: 100%; background: white; border-radius: 10px;"></canvas>
<div style="display: flex; justify-content: space-between; margin-top: 10px; font-size: 12px; color: #666;">
<span>Неделя 1</span>
<span>Неделя 4</span>
<span>Неделя 8</span>
</div>
</div>
<div id="progress-history" style="margin-top: 30px;"></div> <div id="progress-history" style="margin-top: 30px;"></div>
</div> </div>
@ -1018,6 +1031,126 @@
).join('') : '<p>Пока нет записей. Заполни данные выше!</p>'; ).join('') : '<p>Пока нет записей. Заполни данные выше!</p>';
renderNutrition(); renderNutrition();
renderWeightChart();
}
function renderWeightChart() {
const canvas = document.getElementById('weight-chart');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
const entries = progressData.entries.sort((a, b) => new Date(a.date) - new Date(b.date));
const startDate = new Date('2026-08-10');
const totalWeeks = 8;
const startWeight = 65;
const targetWeight = 58;
// Данные для графика
const weights = [];
const weeks = [];
for (let w = 0; w <= totalWeeks; w++) {
weeks.push(w);
// Целевая линия: 65 - (w * 7/8)
weights.push({
week: w,
target: startWeight - (w * (startWeight - targetWeight) / totalWeeks),
actual: null
});
}
// Добавляем фактические замеры
entries.forEach(e => {
const date = new Date(e.date);
const daysFromStart = (date - startDate) / (1000 * 60 * 60 * 24);
const week = Math.min(8, Math.max(0, daysFromStart / 7));
if (e.weight) {
const weekIndex = Math.round(week);
if (weekIndex >= 0 && weekIndex <= 8) {
weights[weekIndex].actual = parseFloat(e.weight);
}
}
});
// Очистка
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Настройки
const padding = 40;
const chartWidth = canvas.width - padding * 2;
const chartHeight = canvas.height - padding * 2;
const weightRange = 10; // 55-75 кг
const minWeight = 55;
function x(w) { return padding + (w / totalWeeks) * chartWidth; }
function y(weight) { return padding + chartHeight - ((weight - minWeight) / weightRange) * chartHeight; }
// Сетка
ctx.strokeStyle = '#e0e0e5';
ctx.lineWidth = 1;
for (let w = 0; w <= totalWeeks; w += 2) {
ctx.beginPath();
ctx.moveTo(x(w), padding);
ctx.lineTo(x(w), canvas.height - padding);
ctx.stroke();
}
for (let wt = 56; wt <= 74; wt += 2) {
ctx.beginPath();
ctx.moveTo(padding, y(wt));
ctx.lineTo(canvas.width - padding, y(wt));
ctx.stroke();
}
// Целевая линия (красная пунктирная)
ctx.strokeStyle = '#f5576c';
ctx.lineWidth = 3;
ctx.setLineDash([10, 5]);
ctx.beginPath();
ctx.moveTo(x(0), y(startWeight));
ctx.lineTo(x(8), y(targetWeight));
ctx.stroke();
ctx.setLineDash([]);
// Фактические замеры (синяя линия)
ctx.strokeStyle = '#667eea';
ctx.lineWidth = 3;
ctx.beginPath();
let started = false;
for (let w = 0; w <= 8; w++) {
if (weights[w].actual !== null) {
if (!started) {
ctx.moveTo(x(w), y(weights[w].actual));
started = true;
} else {
ctx.lineTo(x(w), y(weights[w].actual));
}
}
}
ctx.stroke();
// Точки замеров
for (let w = 0; w <= 8; w++) {
if (weights[w].actual !== null) {
ctx.fillStyle = '#667eea';
ctx.beginPath();
ctx.arc(x(w), y(weights[w].actual), 6, 0, Math.PI * 2);
ctx.fill();
}
}
// Подписи
ctx.fillStyle = '#667eea';
ctx.font = 'bold 14px sans-serif';
ctx.fillText('Цель: 58 кг', canvas.width - padding - 100, y(targetWeight) - 10);
ctx.fillStyle = '#667eea';
ctx.font = 'bold 14px sans-serif';
ctx.fillText('Старт: 65 кг', padding, y(startWeight) - 10);
} }
// === ПИТАНИЕ === // === ПИТАНИЕ ===