"use client" import { useCallback, useMemo, useState } from 'react' import { AreaChart, Area, Line, CartesianGrid, XAxis, YAxis, Tooltip, ResponsiveContainer, } from 'recharts' import { DailyData, TimeRangeKey } from '@/lib/types' import { buildDailyTrendData, formatCurrency, formatTokens, getHeatmapColor, prepareHeatmapData, formatAxisLabel, formatTooltipDate, } from './utils' import type { ToolTheme } from '@/app/ai/theme' interface ActivityProps { daily: DailyData[] theme: ToolTheme timeRange: TimeRangeKey } export default function Activity({ daily, theme, timeRange }: ActivityProps) { const [viewMode, setViewMode] = useState<'heatmap' | 'chart'>('chart') const [selectedMetric, setSelectedMetric] = useState<'cost' | 'tokens'>('cost') const dailyTrendData = useMemo(() => buildDailyTrendData(daily), [daily]) const heatmapWeeks = useMemo(() => prepareHeatmapData(daily), [daily]) const maxCost = useMemo( () => (daily.length ? Math.max(...daily.map(d => d.totalCost)) : 0), [daily] ) const toggleStyles = { '--ring-color': theme.focusRing, '--knob-color': theme.button.activeBackground, } as React.CSSProperties const heatmapLegendColors = useMemo( () => [theme.heatmap.empty, ...theme.heatmap.steps], [theme] ) const xAxisFormatter = useCallback( (value: string) => formatAxisLabel(String(value), timeRange), [timeRange] ) const tooltipLabelFormatter = useCallback( (value: string) => formatTooltipDate(String(value)), [] ) const tooltipFormatter = useCallback( (value: number | string, name: string) => { const isTrend = name === 'Trend' const label = isTrend ? selectedMetric === 'cost' ? 'Cost Trend' : 'Token Trend' : selectedMetric === 'cost' ? 'Daily Cost' : 'Daily Tokens' if (typeof value !== 'number') { return ['—', label] } if (selectedMetric === 'cost') { return [formatCurrency(value), label] } return [`${formatTokens(value)} tokens`, label] }, [selectedMetric] ) return (

Activity

{viewMode === 'heatmap' ? 'Heatmap' : 'Chart'}
{viewMode === 'heatmap' ? (
{['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map((day) => (
{day}
))}
{(() => { const monthLabels: { month: string; position: number }[] = [] let lastMonth = -1 heatmapWeeks.forEach((week, weekIndex) => { const firstDay = week.find(d => d !== null) if (firstDay) { const date = new Date(firstDay.date + 'T00:00:00Z') const month = date.getUTCMonth() if (month !== lastMonth) { monthLabels.push({ month: date.toLocaleDateString('en-US', { month: 'short', timeZone: 'UTC' }), position: weekIndex * 20 }) lastMonth = month } } }) return (
{monthLabels.map((label, idx) => (
{label.month}
))}
) })()}
{heatmapWeeks.map((week, weekIndex) => (
{week.map((day, dayIndex) => (
{day && (

{day.formattedDate}

Cost: ${day.cost.toFixed(2)}

Tokens: {(day.tokens / 1000000).toFixed(2)}M

)}
))}
))}
Less
{heatmapLegendColors.map((color, idx) => (
))}
More
) : ( <>
)}
) }