<xf:css>
.stat-pulse-dot {
display: inline-block;
width: 8px; height: 8px;
background-color: #4caf50;
border-radius: 50%;
margin-left: 8px;
margin-right: 6px;
box-shadow: 0 0 0 rgba(76, 175, 80, 0.4);
animation: statPulse 2s infinite;
vertical-align: middle;
}
@keyframes statPulse {
0% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.7); }
70% { box-shadow: 0 0 0 6px rgba(76, 175, 80, 0); }
100% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0); }
}
.stat-radar-icon {
color: #e53935;
animation: radarPulse 1.5s infinite;
}
@keyframes radarPulse {
0% { opacity: 0.6; transform: scale(0.9); }
50% { opacity: 1; transform: scale(1.1); text-shadow: 0 0 5px rgba(229, 57, 53, 0.5); }
100% { opacity: 0.6; transform: scale(0.9); }
}
@keyframes statTrill {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-3px); }
}
.stat-sparkline {
display: flex;
align-items: flex-end;
justify-content: space-between;
height: 60px;
margin-top: 5px;
margin-bottom: 15px;
padding-bottom: 0;
gap: 3px;
border-bottom: 1px solid @xf-borderColorLight;
}
.stat-spark-bar {
flex: 1;
background: linear-gradient(to top, #0288D1, #29B6F6);
border-radius: 3px 3px 0 0;
position: relative;
transition: all 0.3s ease;
display: flex;
align-items: flex-end;
justify-content: center;
padding-bottom: 2px;
}
.stat-spark-bar:hover {
transform: translateY(-2px);
filter: brightness(1.1);
}
.stat-spark-bar.today {
background: linear-gradient(to top, #F57C00, #FFCA28);
}
.stat-bar-text {
font-size: 9px;
font-weight: 700;
color: #fff;
text-shadow: 0 1px 1px rgba(0,0,0, 0.5);
pointer-events: none;
line-height: 1;
padding-bottom: 3px;
}
.stat-device-bar {
display: flex;
height: 6px;
border-radius: 3px;
overflow: hidden;
margin-top: 8px;
background: @xf-borderColorLight;
}
.stat-dev-segment { height: 100%; }
.stat-toggle-line {
text-align: center;
cursor: pointer;
margin: 10px 0 5px 0;
padding: 4px 0;
border-top: 1px dashed @xf-borderColorLight;
border-bottom: 1px dashed @xf-borderColorLight;
background: rgba(0,0,0,0.02);
color: @xf-textColorMuted;
font-size: 10px;
transition: background 0.2s;
}
.stat-toggle-line:hover {
background: rgba(0,0,0,0.05);
color: @xf-textColor;
}
.stat-toggle-line .stat-arrow {
display: inline-block;
transition: transform 0.3s ease;
animation: statTrill 2s infinite ease-in-out;
}
.stat-toggle-line.is-active .stat-arrow {
transform: rotate(180deg);
}
#stat-detailed-metrics {
display: none;
opacity: 0;
transition: opacity 0.3s ease;
}
#stat-detailed-metrics.is-active {
display: block;
opacity: 1;
animation: statFadeIn 0.3s;
}
@keyframes statFadeIn {
from { opacity: 0; transform: translateY(-5px); }
to { opacity: 1; transform: translateY(0); }
}
.stat-footer-btn {
border: 1px solid @xf-borderColor;
border-radius: 12px;
font-weight: 700;
color: @xf-textColor !important;
padding: 6px 15px;
display: inline-block;
text-decoration: none;
font-size: 13px;
background: @xf-contentAltBg;
transition: background 0.2s, transform 0.2s;
}
.stat-footer-btn:hover {
background: @xf-contentHighlightBg;
text-decoration: none;
transform: translateY(-1px);
}
.stat-glass-style .block-container {
background: rgba(30, 35, 45, 0.65) !important;
backdrop-filter: blur(10px) !important;
-webkit-backdrop-filter: blur(10px) !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37) !important;
color: #f0f0f0 !important;
}
.stat-glass-style .block-header,
.stat-glass-style .block-minorHeader {
background: transparent !important;
color: #ffffff !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
}
.stat-glass-style .block-body {
background: transparent !important;
}
.stat-glass-style a {
color: #81d4fa !important;
}
.stat-glass-style .u-muted {
color: #b0bec5 !important;
}
.stat-glass-style .stat-footer-btn {
background: rgba(255, 255, 255, 0.1) !important;
color: #fff !important;
border: 1px solid rgba(255, 255, 255, 0.3) !important;
}
.stat-glass-style .stat-footer-btn:hover {
background: rgba(255, 255, 255, 0.2) !important;
}
.stat-glass-style hr.formRowSep {
border-color: rgba(255, 255, 255, 0.1) !important;
}
.stat-glass-style .stat-toggle-line {
border-color: rgba(255, 255, 255, 0.1) !important;
background: rgba(255, 255, 255, 0.05) !important;
color: #aaa !important;
}
.stat-glass-style .stat-toggle-line:hover {
background: rgba(255, 255, 255, 0.1) !important;
color: #fff !important;
}
</xf:css>
<div class="block {{ $glassMode ? 'stat-glass-style' : '' }}" data-widget-key="statistiche_visite">
<div class="block-container">
{$layoutData|raw}
<h3 class="block-minorHeader">
<a href="{{ link('online') }}" style="text-decoration: none; color: inherit;">
{{ phrase('statistiche_real_time_header') }}
</a>
</h3>
<div class="block-body block-row">
<xf:if is="count($online.users)">
<div class="stats-user-scroll">
<ul class="listInline u-smaller">
<li><xf:fa icon="fa-users" /></li>
<xf:foreach loop="$online.users" value="$user">
<li>
<xf:username user="$user" rich="true" class="not-bold" /><xf:if is="!$loop.last">,</xf:if>
</li>
</xf:foreach>
</ul>
</div>
<hr class="formRowSep" />
</xf:if>
<dl class="pairs pairs--justified u-smaller">
<dt style="font-weight: bold; color: @xf-textColor;">
<xf:if is="$hasLicense">
<span class="stat-pulse-dot" title="Live Monitor"></span>
</xf:if>
<xf:fa icon="fa-user-clock" /> {{ phrase('statistiche_online_now') }}
</dt>
<dd><strong>{{ $online.total|number }}</strong></dd>
</dl>
<div class="u-muted u-smaller custom-stats-list" style="margin-bottom: 5px;">
<!-- Ratio Bar -->
<xf:set var="$totalAll" value="{{ $online.total + $online.robots }}" />
<xf:if is="$totalAll > 0">
<div class="stat-ratio-bar" style="margin-bottom: 8px;">
<div style="display: flex; justify-content: space-between; font-size: 9px; opacity: 0.8; margin-bottom: 2px;">
<span>Humans: {{ number($online.total / $totalAll * 100, 1) }}%</span>
<span>Robots: {{ number($online.robots / $totalAll * 100, 1) }}%</span>
</div>
<div style="display: flex; height: 4px; border-radius: 2px; overflow: hidden; background: rgba(255,255,255,0.1);">
<div style="width: {{ ($online.total / $totalAll) * 100 }}%; background: #4caf50;"></div>
<div style="width: {{ ($online.robots / $totalAll) * 100 }}%; background: #999;"></div>
</div>
</div>
</xf:if>
<!-- Online Details -->
<dl class="pairs pairs--justified"><dt><xf:fa icon="fa-user-check" /> {{ phrase('statistiche_members') }}</dt><dd>{{ $online.registered|number }}</dd></dl>
<dl class="pairs pairs--justified"><dt><xf:fa icon="fa-user-secret" /> {{ phrase('statistiche_guests') }}</dt><dd>{{ $online.guests|number }}</dd></dl>
<dl class="pairs pairs--justified"><dt><xf:fa icon="fa-spider" /> {{ phrase('statistiche_robots') }}</dt><dd>{{ $online.robots|number }}</dd></dl>
<!-- Blocked Stats (If applicable) -->
<xf:if is="$hasLicense AND $blockedToday > 0">
<div style="margin-top: 4px; color: #e53935; font-weight: bold;">
<xf:fa icon="fa-ban" class="stat-radar-icon" />
{$blockedToday|number} {{ phrase('statistiche_blocked_today') }}
</div>
</xf:if>
<!-- RESTORED VISITORS (Exposed outside of the hidden toggle) -->
<div class="visitors-exposed-block" style="margin-top: 10px; border-top: 1px dashed @xf-borderColorLight; padding-top: 8px;">
<dl class="pairs pairs--justified"><dt><xf:fa icon="fa-chart-line" /> {{ phrase('statistiche_visitors_today') }}</dt><dd>{$unici24h|number}</dd></dl>
<dl class="pairs pairs--justified"><dt><xf:fa icon="fa-calendar-alt" /> {{ phrase('statistiche_visitors_month') }}</dt><dd>{$uniciMese|number}</dd></dl>
<dl class="pairs pairs--justified"><dt><xf:fa icon="fa-globe" /> {{ phrase('statistiche_visitors_year') }}</dt><dd>{$uniciAnno|number}</dd></dl>
<dl class="pairs pairs--justified"><dt><xf:fa icon="fa-eye" /> {{ phrase('statistiche_unique_visitors') }}</dt><dd><strong>{{ $totalViews|number }}</strong></dd></dl>
</div>
</div>
<hr class="formRowSep" />
<!-- FORUM ANALYTICS SECTION -->
<h4 class="block-minorHeader" style="margin-top: 5px; margin-bottom: 10px; background: transparent; padding-left: 0; color: @xf-linkColor;">
<a href="{{ link('statistiche') }}" style="text-decoration: none; color: inherit;">
<xf:fa icon="fa-chart-bar" /> {{ phrase('statistiche_forum_stats') }}
</a>
</h4>
<div class="custom-stats-list u-smaller">
<!-- 1. Total Threads -->
<dl class="pairs pairs--justified">
<dt><xf:fa icon="fa-comments" /> {{ phrase('threads') }}</dt>
<dd>{{ $xf.app.forumStatistics.threads|number }}</dd>
</dl>
<!-- 2. Total Posts (Messages) -->
<dl class="pairs pairs--justified">
<dt><xf:fa icon="fa-comment-dots" /> {{ phrase('messages') }}</dt>
<dd>{{ $xf.app.forumStatistics.messages|number }}</dd>
</dl>
<!-- New Posts Today -->
<dl class="pairs pairs--justified">
<dt><xf:fa icon="fa-pencil-alt" /> {{ phrase('new_posts') }}</dt>
<dd>{{ $forumStats.new_posts_today|number }}</dd>
</dl>
<!-- Total Members -->
<dl class="pairs pairs--justified">
<dt><xf:fa icon="fa-users" /> {{ phrase('statistiche_members') }}</dt>
<dd>{{ $xf.app.forumStatistics.users|number }}</dd>
</dl>
<!-- 3. Latest Member -->
<dl class="pairs pairs--justified">
<dt><xf:fa icon="fa-user-plus" /> {{ phrase('latest_member') }}</dt>
<dd><xf:username user="{$xf.app.forumStatistics.latestUser}" rich="true" /></dd>
</dl>
</div>
<!-- NEWEST MEMBERS (Outside toggle) -->
<xf:if is="$xf.options.statistiche_show_latest">
<div class="u-muted u-smaller" style="margin-top: 10px; padding-top: 10px; border-top: 1px dashed @xf-borderColorLight;">
<div style="margin-bottom:6px; font-weight: bold;">{{ phrase('statistiche_newest_members') }}:</div>
<div style="display: flex; gap: 6px; justify-content: flex-start; flex-wrap: wrap;">
<xf:foreach loop="$latestUsers" value="$user">
<xf:avatar user="$user" size="s" data-xf-init="tooltip" title="{$user.username}" style="width: 28px; height: 28px; border-radius: 50%;" />
</xf:foreach>
</div>
</div>
</xf:if>
<hr class="formRowSep" />
<!-- FOOTER (No Toggle, Standard Placement) -->
<div style="text-align:center; margin-top:15px; padding-bottom: 5px;">
<xf:if is="$xf.visitor.hasPermission('general', 'view_report')">
<a href="{{ link('statistiche/') }}" class="stat-footer-btn">
<xf:fa icon="fa-list-alt" /> {{ phrase('statistiche_view_full_report') }}
</a>
</xf:if>
<xf:if is="$brandingHtml">
<div style="margin-top: 10px;">
{$brandingHtml|raw}
</div>
</xf:if>
</div>