diff --git a/public/assets/js/admin-stats.js b/public/assets/js/admin-stats.js index 41060b8..50865a4 100644 --- a/public/assets/js/admin-stats.js +++ b/public/assets/js/admin-stats.js @@ -1,20 +1,87 @@ /* Admin stats : groupes AS + chargement pages via flux RSS XML /trending?period=14d */ -// ── Groupes de réseaux ──────────────────────────────────────────────────────── + +// ── Visiteurs par pays ──────────────────────────────────────────────────────── (function () { - var addBtn = document.getElementById('as-group-add'); - if (!addBtn) { return; } + var el = document.getElementById('stats-country-container'); + var asList = (typeof FOLIO_AS_LIST !== 'undefined') ? FOLIO_AS_LIST : []; + if (!el || !asList.length) { return; } - addBtn.addEventListener('click', function () { - var tpl = document.getElementById('as-group-tpl').content.cloneNode(true); - document.getElementById('as-groups-list').appendChild(tpl); + // Noms de pays en français via l'API Intl + var dispNames = null; + try { dispNames = new Intl.DisplayNames(['fr'], { type: 'region' }); } catch (e) {} + function countryName(code) { + if (!code || code === '??') { return 'Inconnu'; } + try { return dispNames ? dispNames.of(code) : code; } catch (e) { return code; } + } + + // Drapeau emoji depuis le code ISO-2 + function flag(code) { + if (!code || code.length !== 2) { return ''; } + var cp = Array.from(code.toUpperCase()).map(function (c) { + return 0x1F1E6 + c.charCodeAt(0) - 65; + }); + return String.fromCodePoint(cp[0], cp[1]) + ' '; + } + + // Agréger par pays + var byCountry = {}; + var asByCountry = {}; // country → [{name, asn, hits}] + asList.forEach(function (as) { + var c = as.country || '??'; + byCountry[c] = (byCountry[c] || 0) + as.hits; + if (!asByCountry[c]) { asByCountry[c] = []; } + asByCountry[c].push(as); }); - document.getElementById('as-groups-list').addEventListener('click', function (e) { - if (e.target.classList.contains('as-group-delete')) { - e.target.closest('.as-group-row').remove(); - } + var countries = Object.keys(byCountry).map(function (c) { + return { code: c, hits: byCountry[c], networks: asByCountry[c] }; + }).sort(function (a, b) { return b.hits - a.hits; }).slice(0, 20); + + if (!countries.length) { el.innerHTML = '

Aucune donnée.

'; return; } + + var maxH = countries[0].hits || 1; + + var html = '
'; + countries.forEach(function (c, i) { + var pct = Math.round(c.hits / maxH * 100); + var cname = flag(c.code) + countryName(c.code); + var vis = c.hits.toLocaleString('fr-FR'); + var accId = 'acc-country-' + i; + var nets = c.networks.slice().sort(function (a, b) { return b.hits - a.hits; }); + var maxN = nets[0] ? nets[0].hits : 1; + + var netRows = nets.map(function (n) { + var npct = Math.round(n.hits / maxN * 100); + return '
' + + '
' + + (n.name || '?') + (n.asn ? ' AS' + n.asn + '' : '') + '
' + + '
' + + '
' + + '
' + + '
' + + n.hits.toLocaleString('fr-FR') + '
' + + '
'; + }).join(''); + + html += '
' + + '' + + '
' + + '
' + netRows + '
' + + '
' + + '
'; }); + html += '
'; + el.innerHTML = html; }()); // ── Pages les plus visitées (RSS XML + sparklines) ─────────────────────────── diff --git a/templates/admin_stats.php b/templates/admin_stats.php index 0383d5c..c0468f8 100644 --- a/templates/admin_stats.php +++ b/templates/admin_stats.php @@ -25,7 +25,10 @@ $_activeGroup = trim($_GET['group'] ?? '');

14 derniers jours · visiteurs uniques · flux RSS XML

- +
@@ -39,6 +42,13 @@ $_activeGroup = trim($_GET['group'] ?? '');
+
+
Visiteurs par pays
+
+

Chargement…

+
+
+
@@ -157,44 +167,5 @@ $_activeGroup = trim($_GET['group'] ?? ''); - -
-
Groupes de réseaux
-
-

Regroupez plusieurs réseaux sous un label. Chaque ligne est un motif cherché dans le nom du réseau (insensible à la casse).

-
-
- $g): ?> -
-
- - -
- -
- -
-
- - -
-
-
-
- -