'use client'; /** * Analytics Detail Page — Tabbed drill-down view for analytics data. * * Displays detailed tables and summary panels for: * - Top Songs (MEJORES CANCIONES) * - Income Groups (GRUPOS DE INGRESOS MÁS ALTOS) * - Territories (TERRITORIOS PRINCIPALES) * - Exploitation Sources (RESUMEN DE FUENTES DE EXPLOTACIÓN) * * Accessed via "Ver más" links on the analytics cards. */ import { useState, useMemo, Suspense } from 'react'; import { useSearchParams } from 'next/navigation'; import { clientPortal } from '@/lib/mock-data'; import { useCompactCurrencyFormatter } from '@/lib/hooks/useCurrencyFormatter'; import { chartColorArray } from '@/lib/constants/theme'; import type { PortalSongDetail, PortalIncomeGroupDetail, PortalTerritoryDetail, PortalSourceDetail, } from '@/lib/mock-data/types'; import PieChartWidget from '@/components/charts/PieChartWidget'; import BarChartWidget from '@/components/charts/BarChartWidget'; // ─── Types ─────────────────────────────────────────────────────────────────── type TabId = 'songs' | 'income' | 'territories' | 'sources'; interface TabConfig { id: TabId; label: string; } const TABS: TabConfig[] = [ { id: 'songs', label: 'MEJORES CANCIONES' }, { id: 'income', label: 'GRUPOS DE INGRESOS MÁS ALTOS' }, { id: 'territories', label: 'TERRITORIOS PRINCIPALES' }, { id: 'sources', label: 'RESUMEN DE FUENTES DE EXPLOTACIÓN' }, ]; // ─── Helper Components ─────────────────────────────────────────────────────── function ChevronIcon({ expanded }: { expanded: boolean }) { return ( ); } function PercentageBadge({ value }: { value: number }) { const isPositive = value >= 0; return ( {isPositive ? '+' : ''}{value.toFixed(1)}% ); } function TotalEarningsCard({ total, trend }: { total: number; trend: number }) { const fmtMoney = useCompactCurrencyFormatter(); return (

Ganancias totales

{fmtMoney(total)}

); } // ─── Tab Content Components ────────────────────────────────────────────────── function SongsTab({ data }: { data: PortalSongDetail[] }) { const [expandedRows, setExpandedRows] = useState>(new Set()); const fmtMoney = useCompactCurrencyFormatter(); const sorted = useMemo( () => [...data].sort((a, b) => b.currentPeriodAmount - a.currentPeriodAmount), [data] ); const total = sorted.reduce((sum, s) => sum + s.currentPeriodAmount, 0); const totalLast = sorted.reduce((sum, s) => sum + s.lastPeriodAmount, 0); const trend = totalLast > 0 ? ((total - totalLast) / totalLast) * 100 : 0; const toggleRow = (id: string) => { setExpandedRows((prev) => { const next = new Set(prev); if (next.has(id)) next.delete(id); else next.add(id); return next; }); }; return (
{/* Left Panel */}
    {sorted.slice(0, 10).map((song, i) => { const pct = total > 0 ? (song.currentPeriodAmount / total) * 100 : 0; return (
  • {i + 1}. {song.title}

    {song.composers.join(', ')}

    {fmtMoney(song.currentPeriodAmount)}
    {pct.toFixed(1)}%
  • ); })}
{/* Right Panel - Table */}
{/* Table Header */}
# Las 20 Mejores Canciones Último Período Período Actual
{/* Table Body */}
{sorted.map((song, i) => { const isExpanded = expandedRows.has(song.id); return (
toggleRow(song.id)} > {i + 1}

{song.title}

{song.composers.join(', ')}

{fmtMoney(song.lastPeriodAmount)}
{fmtMoney(song.currentPeriodAmount)}
{/* Expanded sub-row */} {isExpanded && (

Categoría superior

{song.topCategory}

{fmtMoney(song.topCategoryAmount)}

Fuente principal

{song.topSource}

{fmtMoney(song.topSourceAmount)}

Territorio superior

{song.topTerritory}

{fmtMoney(song.topTerritoryAmount)}

)}
); })}
); } function IncomeTab({ data }: { data: PortalIncomeGroupDetail[] }) { const [expandedRows, setExpandedRows] = useState>(new Set()); const fmtMoney = useCompactCurrencyFormatter(); const sorted = useMemo( () => [...data].sort((a, b) => b.currentPeriodAmount - a.currentPeriodAmount), [data] ); const total = sorted.reduce((sum, g) => sum + g.currentPeriodAmount, 0); const totalLast = sorted.reduce((sum, g) => sum + g.lastPeriodAmount, 0); const trend = totalLast > 0 ? ((total - totalLast) / totalLast) * 100 : 0; const toggleRow = (category: string) => { setExpandedRows((prev) => { const next = new Set(prev); if (next.has(category)) next.delete(category); else next.add(category); return next; }); }; const chartData = sorted.map((g) => ({ name: g.category, value: g.currentPeriodAmount })); return (
{/* Left Panel */}
    {sorted.map((group, i) => (
  • {group.category} {fmtMoney(group.currentPeriodAmount)}
  • ))}
{/* Right Panel - Table */}
# Grupos De Ingresos Más Altos Último Período Período Actual
{sorted.map((group, i) => { const isExpanded = expandedRows.has(group.category); return (
toggleRow(group.category)} > {i + 1}
{group.category}
{fmtMoney(group.lastPeriodAmount)}
{fmtMoney(group.currentPeriodAmount)}
{isExpanded && (
{group.subCategories.map((sub) => (
{sub.name} {fmtMoney(sub.lastPeriodAmount)}
{fmtMoney(sub.currentPeriodAmount)}
))}
)}
); })}
); } function TerritoriesTab({ data }: { data: PortalTerritoryDetail[] }) { const fmtMoney = useCompactCurrencyFormatter(); const sorted = useMemo( () => [...data].sort((a, b) => b.currentPeriodAmount - a.currentPeriodAmount), [data] ); const total = sorted.reduce((sum, t) => sum + t.currentPeriodAmount, 0); const totalLast = sorted.reduce((sum, t) => sum + t.lastPeriodAmount, 0); const trend = totalLast > 0 ? ((total - totalLast) / totalLast) * 100 : 0; const chartData = sorted.slice(0, 10).map((t) => ({ country: t.country, amount: t.currentPeriodAmount, })); return (
{/* Left Panel */}
    {sorted.slice(0, 10).map((territory, i) => (
  • {territory.country} {fmtMoney(territory.currentPeriodAmount)}
  • ))}
{/* Right Panel - Table */}
# Los 32 Territorios Principales Último Período Período Actual
{sorted.map((territory, i) => (
{i + 1} {territory.country} {fmtMoney(territory.lastPeriodAmount)}
{fmtMoney(territory.currentPeriodAmount)}
))}
); } function SourcesTab({ data }: { data: PortalSourceDetail[] }) { const [expandedRows, setExpandedRows] = useState>(new Set()); const fmtMoney = useCompactCurrencyFormatter(); const sorted = useMemo( () => [...data].sort((a, b) => b.currentPeriodAmount - a.currentPeriodAmount), [data] ); const total = sorted.reduce((sum, s) => sum + s.currentPeriodAmount, 0); const totalLast = sorted.reduce((sum, s) => sum + s.lastPeriodAmount, 0); const trend = totalLast > 0 ? ((total - totalLast) / totalLast) * 100 : 0; const toggleRow = (platform: string) => { setExpandedRows((prev) => { const next = new Set(prev); if (next.has(platform)) next.delete(platform); else next.add(platform); return next; }); }; return (
{/* Left Panel */}
    {sorted.slice(0, 10).map((source, i) => { const pct = total > 0 ? (source.currentPeriodAmount / total) * 100 : 0; return (
  • {source.platform}
    {fmtMoney(source.currentPeriodAmount)}
    {pct.toFixed(1)}%
  • ); })}
{/* Right Panel - Table */}
# Las 20 Fuentes Último Período Período Actual
{sorted.map((source, i) => { const isExpanded = expandedRows.has(source.platform); return (
toggleRow(source.platform)} > {i + 1}
{source.platform}
{fmtMoney(source.lastPeriodAmount)}
{fmtMoney(source.currentPeriodAmount)}
{isExpanded && (

Top Canción

{source.topSong}

{fmtMoney(source.topSongAmount)}

Categoría superior

{source.topCategory}

{fmtMoney(source.topCategoryAmount)}

Territorio superior

{source.topTerritory}

{fmtMoney(source.topTerritoryAmount)}

)}
); })}
); } // ─── Inner Page Component (uses useSearchParams) ───────────────────────────── function AnalyticsDetailContent() { const searchParams = useSearchParams(); const tabParam = searchParams.get('tab') as TabId | null; const initialTab: TabId = tabParam && TABS.some((t) => t.id === tabParam) ? tabParam : 'songs'; const [activeTab, setActiveTab] = useState(initialTab); const selectedPeriod = clientPortal.periods[0]; return (
{/* Period Selector */}
Período de regalías: {selectedPeriod?.label ?? 'N/A'}
{/* Tab Navigation */}
{/* Tab Content */} {activeTab === 'songs' && } {activeTab === 'income' && } {activeTab === 'territories' && } {activeTab === 'sources' && }
); } // ─── Page Export ────────────────────────────────────────────────────────────── export default function AnalyticsDetailPage() { return ( Cargando...}> ); }