import { useMemo, useState } from 'react'; import { PosBadge } from './pos-helpers'; import type { VocabularyEntry } from '../../types/stats'; interface FrequencyRankTableProps { words: VocabularyEntry[]; knownWords: Set; onSelectWord?: (word: VocabularyEntry) => void; } const PAGE_SIZE = 25; export function FrequencyRankTable({ words, knownWords, onSelectWord }: FrequencyRankTableProps) { const [page, setPage] = useState(0); const [hideKnown, setHideKnown] = useState(true); const hasKnownData = knownWords.size > 0; const isWordKnown = (w: VocabularyEntry): boolean => { return knownWords.has(w.headword) || knownWords.has(w.word) || knownWords.has(w.reading); }; const ranked = useMemo(() => { let filtered = words.filter((w) => w.frequencyRank != null && w.frequencyRank > 0); if (hideKnown && hasKnownData) { filtered = filtered.filter((w) => !isWordKnown(w)); } return filtered.sort((a, b) => a.frequencyRank! - b.frequencyRank!); }, [words, knownWords, hideKnown, hasKnownData]); if (words.every((w) => w.frequencyRank == null)) { return (

Most Common Words Seen

No frequency rank data available. Run the frequency backfill script or install a frequency dictionary.
); } const totalPages = Math.ceil(ranked.length / PAGE_SIZE); const paged = ranked.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE); return (

{hideKnown && hasKnownData ? 'Common Words Not Yet Mined' : 'Most Common Words Seen'}

{hasKnownData && ( )} {ranked.length} words
{ranked.length === 0 ? (
{hideKnown ? 'All ranked words are already in Anki!' : 'No words with frequency data.'}
) : ( <>
{paged.map((w) => ( onSelectWord?.(w)} className="border-b border-ctp-surface1 last:border-0 cursor-pointer hover:bg-ctp-surface1/50 transition-colors" > ))}
Rank Word Reading POS Seen
#{w.frequencyRank!.toLocaleString()} {w.headword} {w.reading !== w.headword ? w.reading : ''} {w.partOfSpeech && } {w.frequency}x
{totalPages > 1 && (
{page + 1} / {totalPages}
)} )}
); }