morozovka-portal/app/templates/onboarding.html

107 lines
4.2 KiB
HTML
Raw Permalink 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.

{% extends "base.html" %}
{% block title %}Тур по платформе — Morozovka{% endblock %}
{% block main_class %}container container-narrow{% endblock %}
{% block content %}
<div class="page-header">
<div>
<h1 class="page-title">👋 Тур по платформе</h1>
<p class="page-subtitle">Короткое знакомство с разделами. Займёт 2 минуты.</p>
</div>
</div>
{% if just_done %}
<div class="welcome-banner">
<div class="welcome-banner-icon">✅</div>
<div class="welcome-banner-body">
<h3 class="welcome-banner-title">Готово! Тур пройден.</h3>
<p class="welcome-banner-text">Все разделы отмечены. Можешь возвращаться сюда из футера, чтобы освежить память.</p>
</div>
<a href="/" class="btn btn-primary">На главную →</a>
</div>
{% endif %}
<div class="onboarding-progress">
<div class="onboarding-progress-label">
<span>Прогресс</span>
<strong>{{ completed }} / {{ total }}</strong>
</div>
<div class="onboarding-progress-bar">
<div class="onboarding-progress-fill" id="progress-fill"
style="width: {{ (completed / total * 100)|round(1) }}%"></div>
</div>
</div>
{% for step in steps %}
<div class="onboarding-step {% if ob[step.key] %}done{% endif %}" data-key="{{ step.key }}">
<div class="onboarding-step-num">{{ step.num if not ob[step.key] else '✓' }}</div>
<div class="onboarding-step-body">
<h3 class="onboarding-step-title">
<span>{{ step.icon }}</span>
{{ step.title }}
</h3>
<p class="onboarding-step-desc">{{ step.desc }}</p>
<div class="onboarding-step-actions">
<a href="{{ step.url }}" class="btn btn-outline btn-sm">Открыть →</a>
<label class="onboarding-step-check">
<input type="checkbox" data-key="{{ step.key }}"
{% if ob[step.key] %}checked{% endif %}>
Освоил(а)
</label>
</div>
</div>
</div>
{% endfor %}
<div style="text-align: center; margin-top: 32px;">
<form action="/onboarding/complete" method="POST" style="display: inline;">
<button type="submit" class="btn btn-primary"
onclick="return confirm('Отметить все разделы как освоенные?');">
✅ Отметить всё сразу
</button>
</form>
</div>
{% endblock %}
{% block scripts %}
<script>
(function() {
const checks = document.querySelectorAll('.onboarding-step-check input[data-key]');
const fill = document.getElementById('progress-fill');
function recalcProgress(completed, total) {
if (!fill) return;
fill.style.width = (completed / total * 100) + '%';
document.querySelector('.onboarding-progress-label strong').textContent = completed + ' / ' + total;
}
checks.forEach(function(cb) {
cb.addEventListener('change', async function() {
const key = cb.dataset.key;
const value = cb.checked;
const stepEl = cb.closest('.onboarding-step');
try {
const r = await fetch('/onboarding/mark', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({key: key, value: value})
});
if (!r.ok) throw new Error('bad response');
const data = await r.json();
if (stepEl) stepEl.classList.toggle('done', value);
const numEl = stepEl.querySelector('.onboarding-step-num');
if (numEl) {
if (value) numEl.textContent = '✓';
else numEl.textContent = Array.from(document.querySelectorAll('.onboarding-step')).indexOf(stepEl) + 1;
}
recalcProgress(data.completed, data.total);
} catch (e) {
cb.checked = !value; // откатить
console.error('onboarding mark failed', e);
}
});
});
})();
</script>
{% endblock %}