import { useState } from 'react';
import { useTrends, type TimeRange, type GroupBy } from '../../hooks/useTrends';
import { DateRangeSelector } from './DateRangeSelector';
import { TrendChart } from './TrendChart';
import { StackedTrendChart } from './StackedTrendChart';
import {
buildAnimeVisibilityOptions,
filterHiddenAnimeData,
pruneHiddenAnime,
} from './anime-visibility';
import { LibrarySummarySection } from './LibrarySummarySection';
function SectionHeader({ children }: { children: React.ReactNode }) {
return (
);
}
interface AnimeVisibilityFilterProps {
animeTitles: string[];
hiddenAnime: ReadonlySet;
onShowAll: () => void;
onHideAll: () => void;
onToggleAnime: (title: string) => void;
}
export function AnimeVisibilityFilter({
animeTitles,
hiddenAnime,
onShowAll,
onHideAll,
onToggleAnime,
}: AnimeVisibilityFilterProps) {
if (animeTitles.length === 0) {
return null;
}
return (
Title Visibility
Shared across all anime trend charts. Default: show everything.
{animeTitles.map((title) => {
const isVisible = !hiddenAnime.has(title);
return (
);
})}
);
}
export function TrendsTab() {
const [range, setRange] = useState('30d');
const [groupBy, setGroupBy] = useState('day');
const [hiddenAnime, setHiddenAnime] = useState>(() => new Set());
const { data, loading, error } = useTrends(range, groupBy);
const cardsMinedColor = 'var(--color-ctp-cards-mined)';
const cardsMinedStackedColors = [
cardsMinedColor,
'#8aadf4',
'#c6a0f6',
'#f5a97f',
'#f5bde6',
'#91d7e3',
'#ee99a0',
'#f4dbd6',
];
if (loading) return Loading...
;
if (error) return Error: {error}
;
if (!data) return null;
const animeTitles = buildAnimeVisibilityOptions([
data.animeCumulative.episodes,
data.animeCumulative.cards,
data.animeCumulative.words,
data.animeCumulative.watchTime,
]);
const activeHiddenAnime = pruneHiddenAnime(hiddenAnime, animeTitles);
const filteredAnimeProgress = filterHiddenAnimeData(
data.animeCumulative.episodes,
activeHiddenAnime,
);
const filteredCardsProgress = filterHiddenAnimeData(
data.animeCumulative.cards,
activeHiddenAnime,
);
const filteredWordsProgress = filterHiddenAnimeData(
data.animeCumulative.words,
activeHiddenAnime,
);
const filteredWatchTimeProgress = filterHiddenAnimeData(
data.animeCumulative.watchTime,
activeHiddenAnime,
);
return (
Activity (per {groupBy === 'month' ? 'month' : 'day'})
Cumulative Totals
Efficiency
Patterns
Library — Cumulative
setHiddenAnime(new Set())}
onHideAll={() => setHiddenAnime(new Set(animeTitles))}
onToggleAnime={(title) =>
setHiddenAnime((current) => {
const next = new Set(current);
if (next.has(title)) {
next.delete(title);
} else {
next.add(title);
}
return next;
})
}
/>
Library — Summary
);
}