Ajout du template stats_dashboard.html pour afficher le tableau de bord des statistiques, avec styles, graphiques Chart.js, tableaux dynamiques et gestion du contexte.
This commit is contained in:
parent
2c715a3af4
commit
ab8307b272
1 changed files with 135 additions and 0 deletions
135
templates/home/stats_dashboard.html
Normal file
135
templates/home/stats_dashboard.html
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
{% extends "layout.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}- Tableau de bord{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
||||
<style>
|
||||
.stats-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin:16px 0}
|
||||
.card{background:var(--bg-200);border-radius:12px;padding:16px;border:1px solid var(--bg-300)}
|
||||
.card h3{margin:0 0 8px 0;font-size:16px;color:var(--fg-300)}
|
||||
.kpi{font-size:28px;font-weight:700}
|
||||
.toolbar{display:flex;gap:8px;align-items:center;justify-content:space-between;margin:8px 0}
|
||||
.charts{display:grid;grid-template-columns:1fr;gap:24px;margin:24px 0}
|
||||
.tables{display:grid;grid-template-columns:1fr 1fr;gap:24px}
|
||||
@media (max-width: 960px){.stats-grid{grid-template-columns:repeat(2,1fr)}.tables{grid-template-columns:1fr}}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<h1>Tableau de bord statistiques</h1>
|
||||
|
||||
<form method="get" class="toolbar">
|
||||
<div>
|
||||
<label for="p">Période: </label>
|
||||
<select id="p" name="p" onchange="this.form.submit()">
|
||||
{% for opt in period_options %}
|
||||
<option value="{{ opt }}" {% if p == opt %}selected{% endif %}>{{ opt }} jours</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<span style="margin-left:8px;color:var(--fg-300)">Du {{ start_date }} au {{ end_date }}</span>
|
||||
</div>
|
||||
<div style="color:var(--fg-300)">Mise en cache 15 minutes</div>
|
||||
</form>
|
||||
|
||||
<section class="stats-grid">
|
||||
<div class="card">
|
||||
<h3>Utilisateurs (total)</h3>
|
||||
<div class="kpi">{{ kpi.total_users }}</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Nouveaux utilisateurs (période)</h3>
|
||||
<div class="kpi">{{ kpi.new_users_period }}</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Utilisateurs actifs (période)</h3>
|
||||
<div class="kpi">{{ kpi.active_users_period }}</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Cours (publiés / total)</h3>
|
||||
<div class="kpi">{{ kpi.courses_enabled }} / {{ kpi.total_courses }}</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Leçons (total)</h3>
|
||||
<div class="kpi">{{ kpi.total_lessons }}</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Articles de blog (total)</h3>
|
||||
<div class="kpi">{{ kpi.total_posts }}</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Revenus</h3>
|
||||
{% if revenus_disponibles %}
|
||||
<div class="kpi">—</div>
|
||||
{% else %}
|
||||
<div class="kpi" title="Aucune source de données">N/A</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Technique</h3>
|
||||
{% if technique_disponible %}
|
||||
<div class="kpi">—</div>
|
||||
{% else %}
|
||||
<div class="kpi" title="Aucune source de données">N/A</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="charts">
|
||||
<div class="card">
|
||||
<h3>Évolution quotidienne</h3>
|
||||
<canvas id="chartMain" height="120"></canvas>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="tables">
|
||||
<div class="card">
|
||||
<h3>Nouveaux utilisateurs par jour</h3>
|
||||
<table>
|
||||
<thead><tr><th>Jour</th><th>Nb</th></tr></thead>
|
||||
<tbody>
|
||||
{% for row in new_users_table %}
|
||||
<tr><td>{{ row.0 }}</td><td>{{ row.1 }}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Nouveaux cours par jour</h3>
|
||||
<table>
|
||||
<thead><tr><th>Jour</th><th>Nb</th></tr></thead>
|
||||
<tbody>
|
||||
{% for row in new_courses_table %}
|
||||
<tr><td>{{ row.0 }}</td><td>{{ row.1 }}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const labels = {{ labels_json|safe }};
|
||||
const series = {{ series_json|safe }};
|
||||
const ctx = document.getElementById('chartMain');
|
||||
const chart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{label: 'Nouveaux utilisateurs', data: series.new_users, borderColor: '#4f46e5', backgroundColor: 'rgba(79,70,229,.2)', tension:.2},
|
||||
{label: 'Nouveaux cours', data: series.new_courses, borderColor: '#059669', backgroundColor: 'rgba(5,150,105,.2)', tension:.2},
|
||||
{label: 'Nouveaux articles', data: series.new_posts, borderColor: '#f59e0b', backgroundColor: 'rgba(245,158,11,.2)', tension:.2},
|
||||
{label: 'Activité progression', data: series.activity_progress, borderColor: '#ef4444', backgroundColor: 'rgba(239,68,68,.2)', tension:.2}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {y: {beginAtZero: true}},
|
||||
plugins: {legend: {position: 'bottom'}}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Loading…
Add table
Add a link
Reference in a new issue