You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
4.8 KiB
103 lines
4.8 KiB
{% extends "base.html" %} |
|
{% block title %}Статистика прохождений{% endblock %} |
|
|
|
{% block content %} |
|
<div class="flex items-center justify-between mb-6 gap-3 flex-wrap"> |
|
<div class="flex items-center gap-2"> |
|
<span class="material-symbols-outlined text-brand-500 text-2xl">bar_chart</span> |
|
<h1 class="text-2xl font-semibold text-ink-900">Статистика</h1> |
|
</div> |
|
<a href="{{ url_for('main.index') }}" |
|
class="inline-flex items-center gap-1 text-sm text-ink-500 hover:text-ink-800 transition"> |
|
<span class="material-symbols-outlined text-base">arrow_back</span> |
|
Главная |
|
</a> |
|
</div> |
|
|
|
{# Сводные метрики #} |
|
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 mb-6"> |
|
{% for icon, label, value in [ |
|
('quiz', 'Тестов всего', stats.total_tests), |
|
('people', 'Пользователей', stats.total_users), |
|
('fact_check', 'Прохождений', stats.total_completed), |
|
('check_circle', 'Сдали', stats.total_passed), |
|
('percent', 'Успешность', stats.pass_rate | string + '\u2009%'), |
|
] %} |
|
<div class="rounded-2xl bg-white border border-ink-300/50 shadow-sm p-4 flex flex-col gap-1"> |
|
<span class="material-symbols-outlined text-brand-500 text-xl">{{ icon }}</span> |
|
<div class="text-2xl font-bold text-ink-900 leading-tight">{{ value }}</div> |
|
<div class="text-xs text-ink-500">{{ label }}</div> |
|
</div> |
|
{% endfor %} |
|
</div> |
|
|
|
{# По отделам + последние прохождения #} |
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4"> |
|
|
|
<section class="rounded-2xl bg-white border border-ink-300/50 shadow-sm overflow-hidden"> |
|
<div class="px-4 py-3 border-b border-ink-100 flex items-center gap-2"> |
|
<span class="material-symbols-outlined text-brand-500 text-base">corporate_fare</span> |
|
<h2 class="font-semibold text-sm text-ink-900">По отделам</h2> |
|
</div> |
|
{% if stats.dept_stats %} |
|
<div class="overflow-x-auto"> |
|
<table class="w-full text-sm"> |
|
<thead> |
|
<tr class="border-b border-ink-100 text-xs text-ink-500 uppercase tracking-wide"> |
|
<th class="px-4 py-2 text-left font-medium">Отдел</th> |
|
<th class="px-4 py-2 text-right font-medium">Прошли</th> |
|
<th class="px-4 py-2 text-right font-medium">Сдали</th> |
|
<th class="px-4 py-2 text-right font-medium">%</th> |
|
</tr> |
|
</thead> |
|
<tbody class="divide-y divide-ink-100/60"> |
|
{% for d in stats.dept_stats %} |
|
<tr class="hover:bg-ink-100/40 transition-colors"> |
|
<td class="px-4 py-2.5 text-ink-800 max-w-[180px] truncate">{{ d.name }}</td> |
|
<td class="px-4 py-2.5 text-right text-ink-700">{{ d.total }}</td> |
|
<td class="px-4 py-2.5 text-right text-ink-700">{{ d.passed }}</td> |
|
<td class="px-4 py-2.5 text-right"> |
|
<span class="inline-block min-w-[38px] text-center rounded-full px-2 py-0.5 text-xs font-semibold |
|
{% if d.rate >= 80 %}bg-green-50 text-green-700 |
|
{% elif d.rate >= 50 %}bg-yellow-50 text-yellow-700 |
|
{% else %}bg-red-50 text-red-700{% endif %}"> |
|
{{ d.rate }}% |
|
</span> |
|
</td> |
|
</tr> |
|
{% endfor %} |
|
</tbody> |
|
</table> |
|
</div> |
|
{% else %} |
|
<p class="px-4 py-8 text-sm text-ink-500 text-center">Прохождений ещё нет.</p> |
|
{% endif %} |
|
</section> |
|
|
|
<section class="rounded-2xl bg-white border border-ink-300/50 shadow-sm overflow-hidden"> |
|
<div class="px-4 py-3 border-b border-ink-100 flex items-center gap-2"> |
|
<span class="material-symbols-outlined text-brand-500 text-base">history</span> |
|
<h2 class="font-semibold text-sm text-ink-900">Последние прохождения</h2> |
|
</div> |
|
{% if stats.recent %} |
|
<ul class="divide-y divide-ink-100/60"> |
|
{% for r in stats.recent %} |
|
<li class="px-4 py-2.5 flex items-start gap-3 hover:bg-ink-100/30 transition-colors"> |
|
<span class="material-symbols-outlined text-base mt-0.5 |
|
{% if r.passed == true %}text-green-500{% elif r.passed is none %}text-ink-300{% else %}text-red-400{% endif %}"> |
|
{% if r.passed == true %}check_circle{% elif r.passed is none %}radio_button_unchecked{% else %}cancel{% endif %} |
|
</span> |
|
<div class="flex-1 min-w-0"> |
|
<div class="text-sm text-ink-800 truncate font-medium">{{ r.test }}</div> |
|
<div class="text-xs text-ink-500 truncate">{{ r.user }} · {{ r.score }} · {{ r.at }}</div> |
|
</div> |
|
</li> |
|
{% endfor %} |
|
</ul> |
|
{% else %} |
|
<p class="px-4 py-8 text-sm text-ink-500 text-center">Прохождений ещё нет.</p> |
|
{% endif %} |
|
</section> |
|
|
|
</div> |
|
{% endblock %}
|
|
|