'use client';
/**
* Exploitation Sources Page — Standalone page for the Sources analytics detail view.
*
* Renders the SourcesTab content from the analytics detail page as its own route.
* Accessible via sidebar navigation under Analítica > Exploitation Sources.
*/
import { useState, useMemo } from 'react';
import { clientPortal } from '@/lib/mock-data';
import { useCompactCurrencyFormatter } from '@/lib/hooks/useCurrencyFormatter';
import { chartColorArray } from '@/lib/constants/theme';
import type { PortalSourceDetail } from '@/lib/mock-data/types';
// ─── 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)}
);
}
// ─── Main Component ──────────────────────────────────────────────────────────
function SourcesDetailView({ 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 (
Resumen de Fuentes de Explotación
{/* Left Panel */}
{sorted.slice(0, 10).map((source, i) => {
const pct = total > 0 ? (source.currentPeriodAmount / total) * 100 : 0;
return (
-
{source.platform}
{fmtMoney(source.currentPeriodAmount)}
);
})}
{/* 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)}
)}
);
})}
);
}
export default function SourcesPage() {
return ;
}