{
    "id": 40,
    "slug": "visitor-statistics",
    "page_content": "{{-- ============================================================================\n     PAGE CONTENT — Statistik Perkhidmatan Dalam Talian\n     Site  : nres  ·  Page slug: visitor-statistics  ·  Page ID: 40\n     URL   : /nres/visitor-statistics\n\n     Konsep: halaman portal asal\n       https://www.nres.gov.my/ms-my/Pages/StatistikPerkhidmatanDalamTalian2026.aspx\n       → jadual bulanan (Jan…Dis) + Jumlah untuk:\n           1. Bilangan Pelawat Portal Rasmi Kementerian\n           2. Perkhidmatan Dalam Talian (halaman paling dilawati)\n\n     Sumber data: modul VISITOR (tiada modul/jadual baharu)\n       · visitor_daily_counters → visited_on · visitor_hash · site_key\n       · visitor_page_views     → page_path · visitor_hash · viewed_at · site_key\n       · frontend_pages         → nama mesra bagi setiap page_path\n\n     Metrik:\n       · Bilangan Pelawat = COUNT(*) harian terkumpul sebulan (visitor_daily_counters)\n       · Pelawat Unik     = COUNT(DISTINCT visitor_hash) sebulan\n       · Paparan Halaman  = COUNT(*) visitor_page_views sebulan\n       · Perkhidmatan     = paparan halaman dikumpulkan ikut page_path\n\n     Skop: site_key = site:{id} bagi $siteSlug semasa (bukan global).\n     BM/EN ikut sesi. CSS sendiri (kelas .vs-*).\n     ============================================================================ --}}\n\n@php\n    $vsLang = ($lang ?? session('locale', 'ms')) === 'en' ? 'en' : 'ms';\n\n    // --- Skop site ---\n    $vsSiteId = DB::table('frontend_sites')->where('slug', $siteSlug ?? 'nres')->value('id');\n    $vsSiteKey = $vsSiteId ? 'site:'.$vsSiteId : null;\n    $vsScope = fn ($q) => $vsSiteKey ? $q->where('site_key', $vsSiteKey) : $q;\n\n    // --- Tahun: tahun data terakhir (fallback tahun semasa) ---\n    $vsYear = (int) ($vsScope(DB::table('visitor_page_views'))->selectRaw('MAX(YEAR(viewed_at)) as y')->first()->y ?? 0);\n    $vsYear = $vsYear ?: (int) now()->year;\n\n    $vsYearStart = $vsYear.'-01-01';\n    $vsYearEnd = $vsYear.'-12-31';\n\n    // --- Nama bulan ---\n    $vsMonthShort = $vsLang === 'en'\n        ? [1 => 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n        : [1 => 'Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Julai', 'Ogos', 'Sept', 'Okt', 'Nov', 'Dis'];\n\n    // --- 1. Pelawat (harian terkumpul) + unik, ikut bulan ---\n    $vsVisits = $vsScope(DB::table('visitor_daily_counters'))\n        ->whereBetween('visited_on', [$vsYearStart, $vsYearEnd])\n        ->selectRaw('MONTH(visited_on) as m, COUNT(*) as total, COUNT(DISTINCT visitor_hash) as uniq')\n        ->groupBy('m')\n        ->get()\n        ->keyBy('m');\n\n    // --- 2. Paparan halaman ikut bulan ---\n    $vsViews = $vsScope(DB::table('visitor_page_views'))\n        ->whereYear('viewed_at', $vsYear)\n        ->selectRaw('MONTH(viewed_at) as m, COUNT(*) as total')\n        ->groupBy('m')\n        ->get()\n        ->keyBy('m');\n\n    // --- 3. Perkhidmatan (page_path) ikut bulan ---\n    $vsPageRows = [];\n\n    foreach ($vsScope(DB::table('visitor_page_views'))\n        ->whereYear('viewed_at', $vsYear)\n        ->selectRaw('page_path, MONTH(viewed_at) as m, COUNT(*) as total')\n        ->groupBy('page_path', 'm')\n        ->get() as $r) {\n        $vsPageRows[$r->page_path]['m'][(int) $r->m] = (int) $r->total;\n        $vsPageRows[$r->page_path]['total'] = ($vsPageRows[$r->page_path]['total'] ?? 0) + (int) $r->total;\n    }\n\n    uasort($vsPageRows, fn ($a, $b) => $b['total'] <=> $a['total']);\n\n    // Nama mesra dari frontend_pages (page_path → slug → name)\n    $vsPageNames = DB::table('frontend_pages')\n        ->when($vsSiteId, fn ($q) => $q->where('site_fk', $vsSiteId))\n        ->pluck('name', 'slug');\n\n    // --- Jumlah tahun ---\n    $vsTotalVisits = (int) $vsVisits->sum('total');\n    $vsTotalUniq = (int) ($vsScope(DB::table('visitor_daily_counters'))\n        ->whereBetween('visited_on', [$vsYearStart, $vsYearEnd])\n        ->distinct()\n        ->count('visitor_hash'));\n    $vsTotalViews = (int) $vsViews->sum('total');\n    $vsTotalServices = count($vsPageRows);\n@endphp\n\n<style>\n.vs-title{font-weight:800;color:var(--deep);letter-spacing:.3px;font-size:clamp(1.2rem,2.6vw,1.85rem);margin:0 0 .35rem;text-transform:uppercase}\n.vs-sub{font-size:.85rem;color:var(--bs-secondary-color);margin:0}\n.vs-card{background:var(--bs-body-bg);border:1px solid var(--line);border-radius:14px;padding:1rem 1.1rem;height:100%;display:flex;flex-direction:column;gap:.15rem;box-shadow:0 4px 14px rgba(17,128,143,.06)}\n.vs-card-lbl{font-size:.7rem;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:var(--bs-secondary-color)}\n.vs-card-num{font-size:1.55rem;font-weight:800;color:var(--teal);line-height:1.15}\n.vs-card-note{font-size:.68rem;color:var(--bs-secondary-color)}\n.vs-panel{background:var(--bs-body-bg);border:1px solid var(--line);border-radius:18px;box-shadow:0 6px 24px rgba(17,128,143,.1);padding:1.1rem 1.1rem 1.2rem;margin-top:1.4rem}\n.vs-h2{font-weight:700;color:var(--green);font-size:1rem;margin:0 0 .9rem;text-transform:uppercase;letter-spacing:.3px}\n.vs-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}\n.vs-table{width:100%;border-collapse:collapse;font-size:.8rem;min-width:860px}\n.vs-table th,.vs-table td{border-bottom:1px solid var(--line);padding:.5rem .45rem;text-align:center;white-space:nowrap}\n.vs-table thead th{background:var(--fade);color:var(--deep);font-weight:700;font-size:.7rem;text-transform:uppercase;letter-spacing:.3px}\n.vs-table th.vs-th-l,.vs-table td.vs-td-l{text-align:left;white-space:normal;min-width:240px;font-weight:600;color:var(--ink)}\n.vs-table th.vs-th-tot,.vs-table td.vs-td-tot{font-weight:800;color:var(--teal);background:rgba(17,128,143,.07)}\n.vs-table tbody tr:hover td{background:rgba(17,128,143,.045)}\n.vs-table tbody tr:hover td.vs-td-tot{background:rgba(17,128,143,.12)}\n.vs-zero{color:var(--bs-secondary-color);opacity:.55}\n.vs-path{display:block;font-weight:400;font-size:.66rem;color:var(--bs-secondary-color);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}\n.vs-foot{font-size:.72rem;color:var(--bs-secondary-color);margin:.85rem 0 0}\n@media(max-width:575.98px){.vs-card-num{font-size:1.25rem}.vs-panel{padding:.85rem .8rem 1rem}}\n</style>\n\n<section class=\"py-4 py-lg-5\">\n  <div class=\"container-xl\">\n\n    <div class=\"text-center mb-4\">\n      <h1 class=\"vs-title\">{{ $vsLang === 'en' ? 'Online Service Statistics' : 'Statistik Perkhidmatan Dalam Talian' }} {{ $vsYear }}</h1>\n      <p class=\"vs-sub\">{{ $vsLang === 'en' ? 'Visitor and online service usage statistics for the official portal.' : 'Statistik pelawat dan penggunaan perkhidmatan dalam talian portal rasmi.' }}</p>\n    </div>\n\n    <div class=\"row g-3\">\n      @foreach ([\n          ['lbl' => $vsLang === 'en' ? 'Total Visitors' : 'Jumlah Pelawat', 'num' => $vsTotalVisits, 'note' => $vsLang === 'en' ? 'daily visits this year' : 'kunjungan harian tahun ini'],\n          ['lbl' => $vsLang === 'en' ? 'Unique Visitors' : 'Pelawat Unik', 'num' => $vsTotalUniq, 'note' => $vsLang === 'en' ? 'distinct visitors this year' : 'pelawat berbeza tahun ini'],\n          ['lbl' => $vsLang === 'en' ? 'Page Views' : 'Paparan Halaman', 'num' => $vsTotalViews, 'note' => $vsLang === 'en' ? 'total page views' : 'jumlah paparan halaman'],\n          ['lbl' => $vsLang === 'en' ? 'Online Services' : 'Perkhidmatan Dalam Talian', 'num' => $vsTotalServices, 'note' => $vsLang === 'en' ? 'pages tracked' : 'halaman dipantau'],\n      ] as $vsCard)\n      <div class=\"col-6 col-lg-3\">\n        <div class=\"vs-card\">\n          <span class=\"vs-card-lbl\">{{ $vsCard['lbl'] }}</span>\n          <b class=\"vs-card-num\">{{ number_format($vsCard['num']) }}</b>\n          <span class=\"vs-card-note\">{{ $vsCard['note'] }}</span>\n        </div>\n      </div>\n      @endforeach\n    </div>\n\n    <div class=\"vs-panel\">\n      <h2 class=\"vs-h2\">{{ $vsLang === 'en' ? 'Number of Visitors to the Ministry Official Portal' : 'Bilangan Pelawat Portal Rasmi Kementerian' }}</h2>\n      <div class=\"vs-scroll\">\n        <table class=\"vs-table\">\n          <thead>\n            <tr>\n              <th class=\"vs-th-l\">{{ $vsLang === 'en' ? 'Service' : 'Perkhidmatan' }}</th>\n              @foreach ($vsMonthShort as $vsLbl)\n                <th>{{ $vsLbl }}</th>\n              @endforeach\n              <th class=\"vs-th-tot\">{{ $vsLang === 'en' ? 'Total' : 'Jumlah' }}</th>\n            </tr>\n          </thead>\n          <tbody>\n            @foreach ([\n                ['lbl' => $vsLang === 'en' ? 'Number of Visitors' : 'Bilangan Pelawat', 'months' => $vsVisits->pluck('total', 'm'), 'total' => $vsTotalVisits],\n                ['lbl' => $vsLang === 'en' ? 'Unique Visitors' : 'Pelawat Unik', 'months' => $vsVisits->pluck('uniq', 'm'), 'total' => $vsTotalUniq],\n                ['lbl' => $vsLang === 'en' ? 'Page Views' : 'Paparan Halaman', 'months' => $vsViews->pluck('total', 'm'), 'total' => $vsTotalViews],\n            ] as $vsRow)\n            <tr>\n              <td class=\"vs-td-l\">{{ $vsRow['lbl'] }}</td>\n              @foreach (array_keys($vsMonthShort) as $vsM)\n                @php $vsV = (int) ($vsRow['months'][$vsM] ?? 0); @endphp\n                <td>@if ($vsV > 0){{ number_format($vsV) }}@else<span class=\"vs-zero\">–</span>@endif</td>\n              @endforeach\n              <td class=\"vs-td-tot\">{{ number_format($vsRow['total']) }}</td>\n            </tr>\n            @endforeach\n          </tbody>\n        </table>\n      </div>\n      <p class=\"vs-foot\">{{ $vsLang === 'en' ? 'Source: Visitor module (visitor_daily_counters & visitor_page_views), scoped to this portal. Updated on every visit.' : 'Sumber: modul Pelawat (visitor_daily_counters & visitor_page_views), skop portal ini sahaja. Dikemas kini pada setiap lawatan.' }}</p>\n    </div>\n\n    <div class=\"vs-panel\">\n      <h2 class=\"vs-h2\">{{ $vsLang === 'en' ? 'Online Services (Most Visited Pages)' : 'Perkhidmatan Dalam Talian (Halaman Paling Dilawati)' }}</h2>\n      <div class=\"vs-scroll\">\n        <table class=\"vs-table\">\n          <thead>\n            <tr>\n              <th class=\"vs-th-l\">{{ $vsLang === 'en' ? 'Service / Page' : 'Perkhidmatan / Halaman' }}</th>\n              @foreach ($vsMonthShort as $vsLbl)\n                <th>{{ $vsLbl }}</th>\n              @endforeach\n              <th class=\"vs-th-tot\">{{ $vsLang === 'en' ? 'Total' : 'Jumlah' }}</th>\n            </tr>\n          </thead>\n          <tbody>\n            @forelse ($vsPageRows as $vsPath => $vsRow)\n            @php\n                $vsSlug = ltrim((string) $vsPath, '/');\n                $vsName = $vsPageNames[$vsSlug] ?? null;\n            @endphp\n            <tr>\n              <td class=\"vs-td-l\">\n                {{ $vsName ?: ($vsSlug === '' ? ($vsLang === 'en' ? 'Home' : 'Utama') : $vsPath) }}\n                @if ($vsSlug !== '')\n                  <small class=\"vs-path\">{{ $vsPath }}</small>\n                @endif\n              </td>\n              @foreach (array_keys($vsMonthShort) as $vsM)\n                @php $vsV = (int) ($vsRow['m'][$vsM] ?? 0); @endphp\n                <td>@if ($vsV > 0){{ number_format($vsV) }}@else<span class=\"vs-zero\">–</span>@endif</td>\n              @endforeach\n              <td class=\"vs-td-tot\">{{ number_format($vsRow['total']) }}</td>\n            </tr>\n            @empty\n            <tr><td class=\"vs-td-l\" colspan=\"{{ count($vsMonthShort) + 2 }}\">—</td></tr>\n            @endforelse\n          </tbody>\n        </table>\n      </div>\n      <p class=\"vs-foot\">{{ $vsLang === 'en' ? 'Page views are grouped by URL path. Only recorded paths are listed. Counts are scoped to this portal.' : 'Paparan halaman dikumpulkan ikut laluan URL. Hanya laluan yang direkodkan dipaparkan. Kiraan adalah untuk portal ini sahaja.' }}</p>\n    </div>\n\n  </div>\n</section>\n"
}