v27 — мотивационный отчёт с рекомендациями для каждого спортсмена

This commit is contained in:
Dauren777 2026-06-02 06:13:51 +00:00
parent 14ae4f0ce7
commit 7ac87e7497

View File

@ -752,6 +752,7 @@ function renderProfile(){
</div>
</div>
<button class="btn small" onclick="openPdfReport()" style="margin-top:8px">&#x1F4C4; Отчёт для тренера</button>
<button class="btn accent-outline small" onclick="openMotivationReport()" style="margin-top:4px">&#x1F4CA; Мотивационный отчёт</button>
<button class="btn danger" onclick="doLogout()" style="margin-top:8px">&#x1F6AA; Выйти</button>
`;return h;
}
@ -772,6 +773,68 @@ function saveAchievement(){
renderPage();toast('Достижение добавлено!');
}
// === MOTIVATION REPORT ===
function openMotivationReport(){
const u = currentUser;
const diary = getMyArr('diary');
const badges = computeBadges(u.id).filter(b => b.cond);
const totalKm = diary.reduce((s,e) => s + (+e.km || 0), 0);
const totalWorkouts = diary.length;
const avgFeel = diary.length ? (diary.reduce((s,e)=>s+(+e.feel||0),0)/diary.length).toFixed(1) : '—';
// Generate personalized recommendations
let recs = [];
if (totalWorkouts < 5) recs.push('&#x1F525; Ты только начинаешь! Самое сложное позади первый шаг сделан. Теперь главное регулярность. 3 тренировки в неделю = привычка.');
else if (totalWorkouts < 20) recs.push('&#x1F4C8; Отличный старт! Ты уже в ритме. Добавь одну дополнительную тренировку в неделю прогресс ускорится.');
else recs.push('&#x1F525; Ты настоящий боец! ' + totalWorkouts + ' тренировок — это серьёзная работа. Гордись собой.');
if (totalKm > 50) recs.push('&#x1F30A; ' + totalKm.toFixed(0) + ' км в воде! Ты пересёк Ла-Манш ' + (totalKm/34).toFixed(1) + ' раз. Впечатляет!');
if (avgFeel !== '—' && +avgFeel >= 4) recs.push('&#x1F4AA; Твоё самочувствие на высоте — ' + avgFeel + '/5. Организм справляется с нагрузкой отлично.');
else if (avgFeel !== '—' && +avgFeel < 3.5) recs.push('&#x1F4A4; Самочувствие ' + avgFeel + '/5. Попробуй спать на час больше восстановление улучшится.');
if (badges.length >= 5) recs.push('&#x1F3C5; ' + badges.length + ' значков! Ты собираешь их как чемпион. Продолжай!');
else recs.push('&#x1F3AF; У тебя ' + badges.length + ' значков. Следующая цель — получить ещё один. Попробуй викторину!');
recs.push('&#x1F3AF; Каждая тренировка приближает тебя к цели. Помни: чемпионами не рождаются — ими становятся каждый день.');
recs.push('&#x1F4DA; Смотри обучающие видео в разделе Инструменты. Техника — это скорость.');
if (u.sport === 'Плавание' || !u.sport) {
recs.push('&#x1F3CA; Работай над стартом и поворотом — на 50 м они дают до 30% времени. 10 стартов каждую тренировку.');
recs.push('&#x23F1; Засекай время каждую неделю. Прогресс в 0.1 секунды — это шаг к мечте.');
}
const w = window.open('', '_blank', 'width=800,height=700');
w.document.write('<!DOCTYPE html><html lang="ru"><head><meta charset="utf-8"><title>Мотивационный отчёт — ' + u.name + '</title><style>body{font:15px/1.7 Arial,sans-serif;max-width:750px;margin:30px auto;padding:20px;color:#1a1a1a;background:linear-gradient(180deg,#fff 0%,#f9fafb 100%)}h1{font-size:28px;border-bottom:3px solid #FF4D00;padding-bottom:10px;margin-bottom:0}h1 span{color:#FF4D00}h2{font-size:18px;margin-top:24px;color:#FF4D00;border-left:4px solid #FF4D00;padding-left:12px}.stats{display:flex;gap:16px;flex-wrap:wrap;margin:16px 0}.stat{background:linear-gradient(135deg,#fff5f0,#fff);border:1px solid #fdd;border-radius:12px;padding:16px 20px;min-width:100px;text-align:center}.stat .num{font-size:28px;font-weight:800;color:#FF4D00}.stat .lbl{font-size:11px;color:#888;text-transform:uppercase;letter-spacing:.5px;margin-top:4px}.rec{background:#fff;border:1px solid #eee;border-radius:10px;padding:14px 18px;margin:8px 0;border-left:3px solid #FF4D00;font-size:14px}.moto{background:linear-gradient(135deg,#FF4D00,#ff6b33);color:#fff;padding:20px 24px;border-radius:14px;margin:20px 0;font-size:18px;font-weight:700;text-align:center}.badge-tag{display:inline-block;padding:3px 10px;background:#fff5f0;border:1px solid #fdd;border-radius:6px;margin:2px;font-size:12px}@media print{body{background:#fff!important;margin:0;padding:10px}}</style></head><body>');
w.document.write('<h1>&#x1F3CA; Мотивационный отчёт<br><span>' + u.name + '</span></h1>');
w.document.write('<p style="color:#666;font-size:14px">' + u.sport + (u.club ? ' · ' + u.club : '') + (u.rank ? ' · ' + u.rank : '') + '</p>');
w.document.write('<div class="stats">');
w.document.write('<div class="stat"><div class="num">' + totalWorkouts + '</div><div class="lbl">Тренировок</div></div>');
w.document.write('<div class="stat"><div class="num">' + totalKm.toFixed(1) + '</div><div class="lbl">Км в воде</div></div>');
w.document.write('<div class="stat"><div class="num">' + avgFeel + '</div><div class="lbl">Самочувствие /5</div></div>');
w.document.write('<div class="stat"><div class="num">' + badges.length + '</div><div class="lbl">Значков</div></div>');
w.document.write('</div>');
if (badges.length) {
w.document.write('<p>Значки: ' + badges.map(b => '<span class="badge-tag">' + b.icon + ' ' + b.name + '</span>').join(' ') + '</p>');
}
if (u.goal) {
w.document.write('<div class="moto">&#x1F3AF; Твоя цель: ' + u.goal + '</div>');
}
w.document.write('<h2>&#x1F4DD; Персональные рекомендации</h2>');
recs.forEach(r => w.document.write('<div class="rec">' + r + '</div>'));
w.document.write('<div class="moto">Помни: ты уже на ' + (totalWorkouts || 1) + ' тренировок впереди тех, кто остался на диване. Не останавливайся. Твой главный соперник — ты вчерашний.</div>');
w.document.write('<p style="text-align:center;color:#999;font-size:12px;margin-top:20px">Отчёт сгенерирован в Галиконе · ' + new Date().toLocaleDateString('ru-RU') + '</p>');
w.document.write('</body></html>');
w.document.close();
}
// === PDF REPORT ===
function openPdfReport(){
const u=currentUser;