'use client' import { useMemo, useState } from 'react' import { cn } from '@/lib/utils' import { useLanguage } from '@/lib/i18n' interface HeatmapDay { date: string count: number } interface RevisionHeatmapProps { data: HeatmapDay[] className?: string /** Révisions de flashcards, ou notes modifiées sur le tableau de bord. */ kind?: 'reviews' | 'edits' } function intensityClass(count: number, max: number): string { if (count <= 0) return 'bg-black/[0.06] dark:bg-white/[0.08]' const ratio = count / Math.max(max, 1) if (ratio >= 0.75) return 'bg-brand-accent' if (ratio >= 0.5) return 'bg-brand-accent/70' if (ratio >= 0.25) return 'bg-brand-accent/40' return 'bg-brand-accent/20' } function resolveDateLocale(langCode: string): string { if (langCode === 'fa') return 'fa-IR-u-ca-persian-nu-arabext' return langCode } export function RevisionHeatmap({ data, className, kind = 'reviews' }: RevisionHeatmapProps) { const { t, language } = useLanguage() const [hovered, setHovered] = useState<{ label: string; count: number; date: string } | null>(null) const [selected, setSelected] = useState<{ label: string; count: number; date: string } | null>(null) const dateLocale = resolveDateLocale(language ?? 'en') const prefix = kind === 'edits' ? 'homeDashboard.activityHeatmap' : 'flashcards.heatmap' const dayLabel = (count: number) => { if (count <= 0) return t(`${prefix}DayNone`) if (count === 1) return t(`${prefix}DayOne`) return t(`${prefix}Day`, { count }) } const { cells, maxCount, totalReviews, monthLabels } = useMemo(() => { const map = new Map(data.map((d) => [d.date, d.count])) const now = new Date() const todayUTC = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())) const cells: { date: string; count: number; label: string }[] = [] const monthLabels: { index: number; label: string }[] = [] let lastMonth = -1 for (let i = 89; i >= 0; i--) { const d = new Date(todayUTC) d.setUTCDate(d.getUTCDate() - i) const key = d.toISOString().slice(0, 10) const count = map.get(key) || 0 const month = d.getUTCMonth() if (month !== lastMonth) { monthLabels.push({ index: 89 - i, label: d.toLocaleDateString(dateLocale, { month: 'short', timeZone: 'UTC' }), }) lastMonth = month } cells.push({ date: key, count, label: d.toLocaleDateString(dateLocale, { weekday: 'long', day: 'numeric', month: 'long', timeZone: 'UTC' }), }) } const maxCount = Math.max(1, ...cells.map((c) => c.count)) const totalReviews = cells.reduce((s, c) => s + c.count, 0) return { cells, maxCount, totalReviews, monthLabels } }, [data, dateLocale]) const pct = (index: number) => `${(index / 90) * 100}%` const activeInfo = hovered || selected return (
{t(`${prefix}Title`)}
{totalReviews > 0 ? t(`${prefix}Total`, { count: totalReviews }) : t(kind === 'edits' ? 'homeDashboard.activityHeatmapLast90' : 'flashcards.heatmapLast90')}{dayLabel(activeInfo.count)} · {activeInfo.label}
) : ({t(`${prefix}Hint`)}
)}