import { useFormatDateInterval } from '@/hooks/use-format-date-interval'; import { useNumber } from '@/hooks/use-numer-formatter'; import React from 'react'; import { ChartTooltipContainer, ChartTooltipHeader, ChartTooltipItem, createChartTooltip, } from '@/components/charts/chart-tooltip'; import type { IInterval } from '@openpanel/validation'; import { SerieIcon } from '../report-chart/common/serie-icon'; type Data = { date: string; timestamp: number; [key: `${string}:sessions`]: number; [key: `${string}:pageviews`]: number; [key: `${string}:revenue`]: number | undefined; [key: `${string}:payload`]: { name: string; prefix?: string; color: string; }; }; type Context = { interval: IInterval; }; export const OverviewLineChartTooltip = createChartTooltip( ({ context: { interval }, data }) => { const formatDate = useFormatDateInterval({ interval, short: false, }); const number = useNumber(); if (!data || data.length === 0) { return null; } const firstItem = data[0]; // Get all payload items from the first data point // Keys are in format "prefix:name:payload" or "name:payload" const payloadItems = Object.keys(firstItem) .filter((key) => key.endsWith(':payload')) .map((key) => { const payload = firstItem[key as keyof typeof firstItem] as { name: string; prefix?: string; color: string; }; // Extract the base key (without :payload) to access sessions/pageviews/revenue const baseKey = key.replace(':payload', ''); return { payload, baseKey, }; }) .filter( (item) => item.payload && typeof item.payload === 'object' && 'name' in item.payload, ); // Sort by sessions (descending) const sorted = payloadItems.sort((a, b) => { const aSessions = (firstItem[ `${a.baseKey}:sessions` as keyof typeof firstItem ] as number) ?? 0; const bSessions = (firstItem[ `${b.baseKey}:sessions` as keyof typeof firstItem ] as number) ?? 0; return bSessions - aSessions; }); const limit = 3; const visible = sorted.slice(0, limit); const hidden = sorted.slice(limit); return ( <> {visible.map((item, index) => { const sessions = (firstItem[ `${item.baseKey}:sessions` as keyof typeof firstItem ] as number) ?? 0; const pageviews = (firstItem[ `${item.baseKey}:pageviews` as keyof typeof firstItem ] as number) ?? 0; const revenue = firstItem[ `${item.baseKey}:revenue` as keyof typeof firstItem ] as number | undefined; return ( {index === 0 && firstItem.date && (
{formatDate(new Date(firstItem.date))}
)}
{item.payload.prefix && ( <> {item.payload.prefix} / )} {item.payload.name || 'Not set'}
{revenue !== undefined && revenue > 0 && (
Revenue {number.currency(revenue / 100, { short: true })}
)}
Pageviews {number.short(pageviews)}
Sessions {number.short(sessions)}
); })} {hidden.length > 0 && (
and {hidden.length} more {hidden.length === 1 ? 'item' : 'items'}
)} ); }, );