'use client'; import { Area, AreaChart, CartesianGrid, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts'; import type { UmamiPageviewsSeries } from '@/lib/services/umami.service'; interface Props { data: UmamiPageviewsSeries | null; } /** * Stacks pageviews on top of sessions in a simple area chart. Umami's * timeseries comes pre-bucketed (the service picks bucket size based on * range span - minute/hour/day/month). * * X-axis labels are kept short to avoid overflow on dense ranges. */ export function PageviewsChart({ data }: Props) { if (!data || data.pageviews.length === 0) { return (
No data in this range
); } // Merge the two series (Umami returns them separately) into one row per // bucket so we can drive a single chart. const byX = new Map(); for (const p of data.pageviews) { byX.set(p.x, { x: p.x, pageviews: p.y, sessions: 0 }); } for (const s of data.sessions) { const row = byX.get(s.x); if (row) row.sessions = s.y; else byX.set(s.x, { x: s.x, pageviews: 0, sessions: s.y }); } const merged = Array.from(byX.values()).sort((a, b) => a.x.localeCompare(b.x)); return ( ); } /** Compact tick labels: full datetime → just MM-DD or MM-DD HH:00. */ function formatXTick(value: string): string { // Umami can return either "YYYY-MM-DD HH:mm:ss" or "YYYY-MM-DD". if (value.length >= 16) { return value.slice(5, 16); // "MM-DD HH:mm" } return value.slice(5); // "MM-DD" }