import { useState, useEffect } from 'react'; import { __ } from '../lib/i18n'; import { ScreenLoader } from './screen-loader'; import { readPageStatsResponse } from '@/lib/utils'; import { defaultBotLogo, getBotLogos } from '../lib/bot-logos'; interface PageStat { page_path: string; page_title: string; page_url: string; bot_visits: number; clicks: number; ctr: number; bots: string[]; } interface PagesOverviewProps { apiRoot: string; apiNamespace: string; pluginUrl: string; } export function PagesOverview({ apiRoot, apiNamespace }: PagesOverviewProps) { const [isLoading, setIsLoading] = useState(true); const [pageStats, setPageStats] = useState([]); const botLogos = getBotLogos(); const defaultLogo = defaultBotLogo(); useEffect(() => { fetchPageStats(); }, []); const fetchPageStats = async () => { try { setIsLoading(true); if (!(window as any).wpApiSettings || !(window as any).wpApiSettings.root) { throw new Error('WordPress REST API settings not available.'); } const apiUrl = `${apiRoot}${apiNamespace}/page-stats`; const response = await fetch(apiUrl, { headers: { 'X-WP-Nonce': (window as any).wpApiSettings?.nonce || '', }, credentials: 'same-origin', }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); if (data.error) { throw new Error(data.message || 'API returned an error'); } // This card is a top-5 widget. const statsArray = readPageStatsResponse(data).pages.slice(0, 5); setPageStats(statsArray); } catch (err: any) { console.error('Error fetching page stats:', err); // Don't show error, just show empty state setPageStats([]); } finally { setIsLoading(false); } }; return (

{__('Top Pages', 'llmagnet-llm-txt-generator')}

{__('View all', 'llmagnet-llm-txt-generator')}
{isLoading ? ( ) : pageStats.length === 0 ? (

{__('No page traffic yet.', 'llmagnet-llm-txt-generator')}

{__('Bot visits will appear here once crawlers access your pages.', 'llmagnet-llm-txt-generator')}

) : (
{pageStats.map((page, index) => { // Truncate title and path to ~50 characters const truncateText = (text: string, maxLength: number = 50) => { if (!text) return ''; return text.length > maxLength ? text.substring(0, maxLength) + '...' : text; }; return ( ); })}
{__('Pages', 'llmagnet-llm-txt-generator')} {__('Visit', 'llmagnet-llm-txt-generator')} {__('Models', 'llmagnet-llm-txt-generator')}
{truncateText(page.page_title, 50)}
{page.page_path === '/' ? ( {__('Site Homepage', 'llmagnet-llm-txt-generator')} ) : truncateText(page.page_path, 50)}
{page.bot_visits.toLocaleString()}
{page.bots.slice(0, 5).map((botName, botIndex) => { const logoUrl = botLogos[botName] || defaultLogo; return ( {botName} { (e.currentTarget as HTMLElement).style.transform = 'translateY(-4px)'; (e.currentTarget as HTMLElement).style.zIndex = '10'; }} onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.transform = 'translateY(0)'; (e.currentTarget as HTMLElement).style.zIndex = String(botIndex); }} onError={(e) => { const target = e.target as HTMLImageElement; if (target.src !== defaultLogo) { target.src = defaultLogo; } }} /> ); })} {page.bots.length > 5 && (
{ (e.currentTarget as HTMLElement).style.transform = 'translateY(-4px)'; (e.currentTarget as HTMLElement).style.zIndex = '10'; }} onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.transform = 'translateY(0)'; (e.currentTarget as HTMLElement).style.zIndex = '5'; }} > +{page.bots.length - 5}
)}
)}
); }