snauwcounter/app/templates/statistics.html
Michael Trip b56e866071
All checks were successful
Build and Push Image / build-and-push (push) Successful in 1m26s
initial commit
2026-01-09 21:58:53 +01:00

223 lines
7.5 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 %}Statistieken - Snauw Counter{% endblock %}
{% block head %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
{% endblock %}
{% block content %}
<h2>📈 Statistieken & Trends</h2>
<!-- Statistiek overzicht -->
<div class="stats-grid">
<div class="stat-card">
<span class="stat-number">{{ stats.total_incidents }}</span>
<span class="stat-label">Totaal incidenten</span>
</div>
<div class="stat-card">
<span class="stat-number">{{ stats.incidents_today }}</span>
<span class="stat-label">Vandaag</span>
</div>
<div class="stat-card">
<span class="stat-number">{{ stats.avg_severity }}</span>
<span class="stat-label">Gemiddelde Snauw-index</span>
</div>
<div class="stat-card">
<span class="stat-number">{{ stats.most_severe }}</span>
<span class="stat-label">Hoogste Snauw-index</span>
</div>
</div>
<!-- Trend grafiek -->
{% if stats.total_incidents > 0 %}
<div class="card">
<h3>📊 Trend laatste 7 dagen</h3>
<div class="chart-container">
<canvas id="trendChart"></canvas>
</div>
</div>
<!-- Periode statistieken -->
<div class="card">
<h3>📅 Periode overzicht</h3>
<div class="stats-grid">
<div class="stat-card">
<span class="stat-number">{{ stats.incidents_this_week }}</span>
<span class="stat-label">Deze week</span>
</div>
<div class="stat-card">
<span class="stat-number">{{ stats.incidents_this_month }}</span>
<span class="stat-label">Deze maand</span>
</div>
</div>
</div>
<!-- Recent incidents -->
<div class="card">
<h3>🕒 Recente incidenten</h3>
{% if incidents %}
<div style="max-height: 300px; overflow-y: auto;">
{% for incident in incidents[:10] %}
<div style="display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 0; border-bottom: 1px solid #e9ecef;">
<div>
<strong>Snauw-index {{ incident.severity }}/5</strong>
{% if incident.notes %}
<br><small style="color: #6c757d;">{{ incident.notes[:50] }}{% if incident.notes|length > 50 %}...{% endif %}</small>
{% endif %}
</div>
<small style="color: #6c757d;">
{{ incident.timestamp.strftime('%d/%m %H:%M') }}
</small>
</div>
{% endfor %}
</div>
{% if incidents|length > 10 %}
<p style="margin-top: 1rem; color: #6c757d; text-align: center;">
En {{ incidents|length - 10 }} andere incidenten...
</p>
{% endif %}
{% else %}
<p style="color: #6c757d;">Nog geen incidenten geregistreerd</p>
{% endif %}
</div>
{% else %}
<!-- Geen data yet -->
<div class="card" style="text-align: center; padding: 3rem;">
<h3>📊 Nog geen statistieken</h3>
<p style="color: #6c757d; margin-bottom: 2rem;">
Registreer je eerste incident om statistieken te zien
</p>
<a href="{{ url_for('main.index') }}" class="btn">📝 Eerste incident toevoegen</a>
</div>
{% endif %}
<!-- GDPR compliance section -->
<div class="card" style="border-left: 4px solid #ffc107;">
<h4>🔒 Privacy & Gegevensbeheer</h4>
<p>Je hebt altijd controle over je gegevens:</p>
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 1rem;">
<button onclick="exportData()" class="btn btn-secondary">📥 Data exporteren</button>
{% if current_user.is_authenticated %}
<form action="{{ url_for('main.delete_account') }}" method="POST" style="display: inline;"
onsubmit="return confirm('Type DELETE om te bevestigen') && prompt('Type DELETE:') === 'DELETE'">
<input type="hidden" name="confirm" value="DELETE">
<button type="submit" class="btn btn-danger">🗑️ Account verwijderen</button>
</form>
{% else %}
<button onclick="deleteAllData()" class="btn btn-danger">🗑️ Alle data wissen</button>
{% endif %}
</div>
<p style="margin-top: 1rem; font-size: 0.9rem; color: #6c757d;">
<a href="{{ url_for('main.privacy') }}" style="color: inherit;">Privacy beleid</a> |
Conform AVG/GDPR
</p>
</div>
{% endblock %}
{% block scripts %}
<script>
// Mark body as authenticated for JavaScript
document.body.dataset.isAuthenticated = {{ 'true' if current_user.is_authenticated else 'false' }};
{% if stats.total_incidents > 0 %}
// Chart.js implementation
const trendData = {{ stats.trend_data | tojson }};
const ctx = document.getElementById('trendChart').getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: trendData.map(d => d.date),
datasets: [{
label: 'Aantal incidenten',
data: trendData.map(d => d.count),
backgroundColor: 'rgba(102, 126, 234, 0.6)',
borderColor: 'rgba(102, 126, 234, 1)',
borderWidth: 2,
yAxisID: 'y'
}, {
label: 'Gemiddelde Snauw-index',
data: trendData.map(d => d.avg_severity),
type: 'line',
borderColor: 'rgba(220, 53, 69, 1)',
backgroundColor: 'rgba(220, 53, 69, 0.1)',
borderWidth: 3,
fill: false,
yAxisID: 'y1'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: 'Incident Trends (Laatste 7 dagen)'
},
legend: {
display: true
}
},
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
beginAtZero: true,
title: {
display: true,
text: 'Aantal incidenten'
}
},
y1: {
type: 'linear',
display: true,
position: 'right',
min: 0,
max: 5,
title: {
display: true,
text: 'Gemiddelde Snauw-index'
},
grid: {
drawOnChartArea: false,
}
}
},
interaction: {
mode: 'index',
intersect: false,
}
}
});
{% endif %}
// Load anonymous user data if not authenticated
if (!{{ 'true' if current_user.is_authenticated else 'false' }}) {
// This would enhance the statistics with localStorage data
enhanceWithLocalData();
}
function enhanceWithLocalData() {
// For anonymous users, we could enhance server statistics
// with localStorage data that might not be synced yet
const localIncidents = JSON.parse(localStorage.getItem('snauw_incidents') || '[]');
if (localIncidents.length > 0) {
// Add notification about local data
const notice = document.createElement('div');
notice.className = 'alert alert-info';
notice.innerHTML = `
Je hebt ${localIncidents.length} lokaal opgeslagen incidenten.
<a href="{{ url_for('main.register') }}">Maak een account</a> om deze veilig op te slaan.
`;
document.querySelector('main').insertBefore(notice, document.querySelector('main').firstChild);
}
}
</script>
{% endblock %}