48hr.email/infrastructure/web/views/stats.twig
2026-01-05 06:49:21 +01:00

201 lines
9.4 KiB
Twig

{% extends 'layout.twig' %}
{% block metaTags %}
<!-- Statistics Page - Custom Meta Tags -->
<meta name="description" content="Live email statistics: {{ metaStats.currentCount }} emails in system, {{ metaStats.allTimeTotal }} processed all-time. Real-time monitoring, historical patterns, and predictions over {{ purgeTimeRaw | readablePurgeTime }}.">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="{{ config.http.baseUrl }}/stats">
<meta property="og:title" content="Email Statistics - {{ branding.0 }}">
<meta property="og:description" content="{{ metaStats.currentCount }} emails in system | {{ metaStats.allTimeTotal }} all-time total | Real-time monitoring and predictions">
<meta property="og:image" content="{{ config.http.baseUrl }}/images/logo.png">
<meta property="og:site_name" content="{{ branding.0 }}">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary">
<meta name="twitter:url" content="{{ config.http.baseUrl }}/stats">
<meta name="twitter:title" content="Email Statistics - {{ branding.0 }}">
<meta name="twitter:description" content="{{ metaStats.currentCount }} emails | {{ metaStats.allTimeTotal }} all-time | Live monitoring">
<meta name="twitter:image" content="{{ config.http.baseUrl }}/images/logo.png">
{% endblock %}
{% block header %}
<div class="action-links">
{% if currentUser %}
<!-- Account Dropdown (logged in) -->
{% if authEnabled %}
<div class="action-dropdown">
<button class="dropdown-toggle" aria-label="Account menu">Account ▾</button>
<div class="dropdown-menu" data-section-title="Account">
<a href="/account" aria-label="Account settings">Settings</a>
<a href="/logout?redirect=/stats" aria-label="Logout">Logout</a>
</div>
</div>
{% endif %}
{% else %}
{% if authEnabled %}
<a href="/auth" aria-label="Login or Register">Account</a>
{% endif %}
{% endif %}
<a href="/" aria-label="Return to home">Home</a>
<button class="theme-toggle" id="themeToggle" aria-label="Toggle dark/light mode">
<svg class="theme-icon theme-icon-dark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
</svg>
<svg class="theme-icon theme-icon-light" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
</svg>
</button>
</div>
{% endblock %}
{% block body %}
<div class="stats-container">
<h1 class="page-title">Email Statistics</h1>
<p class="stats-subtitle">Historical patterns, real-time activity, and predictions over {{ purgeTime|striptags }}</p>
<div class="stats-grid">
<!-- Current Count -->
<div class="stat-card">
<div class="stat-value" id="currentCount">{{ stats.currentCount }}</div>
<div class="stat-label">Emails in System</div>
</div>
<!-- All-Time Total -->
<div class="stat-card">
<div class="stat-value" id="historicalTotal">{{ stats.allTimeTotal }}</div>
<div class="stat-label">All-Time Total</div>
</div>
<!-- Receives (Purge Window) -->
<div class="stat-card">
<div class="stat-value" id="receives24h">{{ stats.last24Hours.receives }}</div>
<div class="stat-label">Received</div>
</div>
<!-- Deletes (Purge Window) -->
<div class="stat-card">
<div class="stat-value" id="deletes24h">{{ stats.last24Hours.deletes }}</div>
<div class="stat-label">Deleted</div>
</div>
<!-- Forwards (Purge Window) -->
<div class="stat-card">
<div class="stat-value" id="forwards24h">{{ stats.last24Hours.forwards }}</div>
<div class="stat-label">Forwarded</div>
</div>
</div>
{% if stats.enhanced %}
<!-- Enhanced Statistics Grid -->
<div class="enhanced-stats-grid">
<!-- Top Sender Domains -->
<div class="stat-card-detailed">
<h3 class="section-header-small">
Top Sender Domains
</h3>
<ul class="stat-list" data-stats="top-sender-domains">
{% if stats.enhanced.topSenderDomains|length > 0 %}
{% for item in stats.enhanced.topSenderDomains|slice(0, 5) %}
<li class="stat-list-item">
<span class="stat-list-label">{{ item.domain }}</span>
<span class="stat-list-value">{{ item.count }}</span>
</li>
{% endfor %}
{% else %}
<li class="stat-empty">Loading...</li>
{% endif %}
</ul>
<p class="stat-footer"><span data-stats="unique-sender-domains">{{ stats.enhanced.uniqueSenderDomains }}</span> unique domains</p>
</div>
<!-- Top Recipient Domains -->
<div class="stat-card-detailed">
<h3 class="section-header-small">
Top Recipient Domains
</h3>
<ul class="stat-list" data-stats="top-recipient-domains">
{% if stats.enhanced.topRecipientDomains|length > 0 %}
{% for item in stats.enhanced.topRecipientDomains|slice(0, 5) %}
<li class="stat-list-item">
<span class="stat-list-label">{{ item.domain }}</span>
<span class="stat-list-value">{{ item.count }}</span>
</li>
{% endfor %}
{% else %}
<li class="stat-empty">Loading...</li>
{% endif %}
</ul>
<p class="stat-footer"><span data-stats="unique-recipient-domains">{{ stats.enhanced.uniqueRecipientDomains }}</span> unique domains</p>
</div>
<!-- Busiest Hours -->
<div class="stat-card-detailed">
<h3 class="section-header-small">
Busiest Hours
</h3>
<ul class="stat-list" data-stats="busiest-hours">
{% if stats.enhanced.busiestHours|length > 0 %}
{% for item in stats.enhanced.busiestHours %}
<li class="stat-list-item">
<span class="stat-list-label">{{ item.hour }}:00 - {{ item.hour + 1 }}:00</span>
<span class="stat-list-value">{{ item.count }}</span>
</li>
{% endfor %}
{% else %}
<li class="stat-empty">Loading...</li>
{% endif %}
</ul>
</div>
<!-- Quick Stats -->
<div class="stat-card-detailed">
<h3 class="section-header-small">
Quick Insights
</h3>
<div class="quick-stats">
<div class="quick-stat-item">
<div class="quick-stat-value" data-stats="average-subject-length">{{ stats.enhanced.averageSubjectLength }}</div>
<div class="quick-stat-label">Avg Subject Length</div>
</div>
<div class="quick-stat-item">
<div class="quick-stat-value" data-stats="unique-sender-domains-value">{{ stats.enhanced.uniqueSenderDomains }}</div>
<div class="quick-stat-label">Unique Senders</div>
</div>
<div class="quick-stat-item">
<div class="quick-stat-value" data-stats="unique-recipient-domains-value">{{ stats.enhanced.uniqueRecipientDomains }}</div>
<div class="quick-stat-label">Unique Recipients</div>
</div>
<div class="quick-stat-item">
<div class="quick-stat-value" data-stats="peak-hour-percentage">{{ stats.enhanced.peakHourPercentage }}%</div>
<div class="quick-stat-label">Peak Hour Traffic</div>
</div>
<div class="quick-stat-item">
<div class="quick-stat-value" data-stats="emails-per-hour">{{ stats.enhanced.emailsPerHour }}</div>
<div class="quick-stat-label">Emails per Hour</div>
</div>
<div class="quick-stat-item">
<div class="quick-stat-value" data-stats="day-percentage">{{ stats.enhanced.dayPercentage }}%</div>
<div class="quick-stat-label">Daytime (6am-6pm)</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Chart -->
<div class="chart-container">
<h2>Email Activity Timeline</h2>
<canvas id="statsChart"></canvas>
</div>
</div>
<script>
// Set initial data for stats.js to consume
window.initialStatsData = {{ stats.last24Hours.timeline|json_encode|raw }};
window.historicalData = {{ stats.historical|json_encode|raw }};
window.predictionData = {{ stats.prediction|json_encode|raw }};
</script>
{% endblock %}