Files
OSINT/templates/analytics/reports.html
Iliyan Angelov ed94dd22dd update
2025-11-26 22:32:20 +02:00

284 lines
9.5 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 %}Аналитика на Докладите - Официален Портал{% endblock %}
{% block content %}
<div class="page-header">
<h1>Аналитика на Докладите</h1>
<p class="lead">Подробна статистика и аналитика за докладите за измами</p>
</div>
<!-- Overall Statistics -->
<div class="gov-card">
<div class="gov-card-header">
<h2>Обща Статистика</h2>
</div>
<div class="gov-card-body">
<div class="stats-grid">
<div class="stat-card">
<h3>{{ total_reports|default:0 }}</h3>
<p>Общо Доклади</p>
</div>
<div class="stat-card stat-pending">
<h3>{{ pending_reports|default:0 }}</h3>
<p>В Очакване</p>
</div>
<div class="stat-card stat-verified">
<h3>{{ verified_reports|default:0 }}</h3>
<p>Потвърдени</p>
</div>
<div class="stat-card stat-rejected">
<h3>{{ rejected_reports|default:0 }}</h3>
<p>Отхвърлени</p>
</div>
<div class="stat-card stat-review">
<h3>{{ under_review_reports|default:0 }}</h3>
<p>В Преглед</p>
</div>
</div>
</div>
</div>
<!-- Time-based Statistics -->
<div class="gov-card">
<div class="gov-card-header">
<h2>Статистика по Период</h2>
</div>
<div class="gov-card-body">
<div class="stats-grid">
<div class="stat-card">
<h3>{{ reports_last_7_days|default:0 }}</h3>
<p>Последните 7 Дни</p>
</div>
<div class="stat-card">
<h3>{{ reports_last_30_days|default:0 }}</h3>
<p>Последните 30 Дни</p>
</div>
<div class="stat-card">
<h3>{{ reports_last_90_days|default:0 }}</h3>
<p>Последните 90 Дни</p>
</div>
</div>
</div>
</div>
<!-- Scam Type Distribution -->
{% if scam_types %}
<div class="gov-card">
<div class="gov-card-header">
<h2>Разпределение по Видове Измами</h2>
</div>
<div class="gov-card-body">
<div class="scam-types-grid">
{% for type in scam_types %}
<div class="scam-type-card">
<div class="scam-type-header">
<span class="badge badge-{{ type.scam_type }}" style="font-size: 0.9rem; padding: 0.5rem 1rem;">
{{ type.display_name }}
</span>
<div class="scam-type-count">
<span class="count-number">{{ type.count }}</span>
<span class="count-label">доклад{{ type.count|pluralize:"а,а" }}</span>
</div>
</div>
<div class="scam-type-bar">
<div class="scam-type-bar-fill" style="width: {{ type.percentage }}%"></div>
</div>
<div class="scam-type-percentage">
{{ type.percentage }}% от общия брой
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
<!-- Moderation Statistics -->
<div class="gov-card">
<div class="gov-card-header">
<h2>Статистика на Модерация</h2>
</div>
<div class="gov-card-body">
<div class="stats-grid">
<div class="stat-card">
<h3>{{ total_moderations|default:0 }}</h3>
<p>Общо Модерации</p>
</div>
<div class="stat-card stat-verified">
<h3>{{ approvals|default:0 }}</h3>
<p>Одобрени</p>
</div>
<div class="stat-card stat-rejected">
<h3>{{ rejections|default:0 }}</h3>
<p>Отхвърлени</p>
</div>
</div>
{% if avg_moderation_time_hours %}
<div style="margin-top: 2rem; padding-top: 2rem; border-top: 1px solid #e0e0e0;">
<h3>Време за Модерация</h3>
<div class="stats-grid" style="margin-top: 1rem;">
<div class="stat-card">
<h3>{{ avg_moderation_time_hours }}ч</h3>
<p>Средно Време</p>
</div>
<div class="stat-card">
<h3>{{ min_moderation_time_hours }}ч</h3>
<p>Минимално Време</p>
</div>
<div class="stat-card">
<h3>{{ max_moderation_time_hours }}ч</h3>
<p>Максимално Време</p>
</div>
</div>
</div>
{% endif %}
</div>
</div>
<!-- Top Reporters -->
{% if top_reporters %}
<div class="gov-card">
<div class="gov-card-header">
<h2>Най-Активни Докладващи</h2>
</div>
<div class="gov-card-body">
<div class="table-responsive">
<table class="gov-table">
<thead>
<tr>
<th>Позиция</th>
<th>Потребител</th>
<th>Брой Доклади</th>
</tr>
</thead>
<tbody>
{% for reporter in top_reporters %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ reporter.reporter__username|default:"Анонимен" }}</td>
<td><strong>{{ reporter.report_count }}</strong></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}
<!-- Daily Reports Chart -->
{% if daily_reports %}
<div class="gov-card">
<div class="gov-card-header">
<h2>Дневна Статистика (Последните 30 Дни)</h2>
</div>
<div class="gov-card-body">
<div class="chart-container">
<canvas id="dailyReportsChart" style="max-height: 400px;"></canvas>
</div>
</div>
</div>
{% endif %}
<!-- Status Over Time -->
{% if status_over_time %}
<div class="gov-card">
<div class="gov-card-header">
<h2>Статуси по Време (Последните 7 Дни)</h2>
</div>
<div class="gov-card-body">
<div class="chart-container">
<canvas id="statusChart" style="max-height: 400px;"></canvas>
</div>
</div>
</div>
{% endif %}
<div style="margin-top: 2rem;">
<a href="{% url 'analytics:dashboard' %}" class="btn btn-secondary">Обратно към Таблото</a>
</div>
{% if daily_reports %}
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>
<script>
// Daily Reports Chart
const dailyCtx = document.getElementById('dailyReportsChart');
if (dailyCtx) {
const dailyData = {{ daily_reports }};
new Chart(dailyCtx, {
type: 'line',
data: {
labels: dailyData.map(d => new Date(d.date).toLocaleDateString('bg-BG')),
datasets: [{
label: 'Доклади',
data: dailyData.map(d => d.count),
borderColor: '#1e3a8a',
backgroundColor: 'rgba(30, 58, 138, 0.1)',
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
display: true
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
}
// Status Over Time Chart
const statusCtx = document.getElementById('statusChart');
if (statusCtx) {
const statusData = {{ status_over_time }};
new Chart(statusCtx, {
type: 'bar',
data: {
labels: statusData.map(d => new Date(d.date).toLocaleDateString('bg-BG')),
datasets: [
{
label: 'В Очакване',
data: statusData.map(d => d.pending),
backgroundColor: '#f59e0b'
},
{
label: 'Потвърдени',
data: statusData.map(d => d.verified),
backgroundColor: '#10b981'
},
{
label: 'Отхвърлени',
data: statusData.map(d => d.rejected),
backgroundColor: '#ef4444'
}
]
},
options: {
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
display: true
}
},
scales: {
y: {
beginAtZero: true,
stacked: false
}
}
}
});
}
</script>
{% endif %}
{% endblock %}