"use client" /** * Library **Data** view — KPI strip + Recharts cards. Loaded via `next/dynamic` * from `library-table` so table/list/board/folder routes do not eagerly bundle Recharts. */ import * as React from "react" import { Bar, BarChart, CartesianGrid, Cell, XAxis, YAxis } from "recharts" import { ChartCard, ChartDataTable, ChartFigure } from "@/components/charts-overview" import { KeyMetrics } from "@/components/key-metrics" import { ChartContainer, ChartTooltip, chartTooltipKeyboardSyncProps, ChartTooltipContent, type ChartConfig, } from "@/components/ui/chart" import { CHART_KBD_ACTIVE_BAR } from "@/lib/chart-keyboard-selection" import type { LibraryItem, LibraryItemType } from "@/lib/mock/library" import { libraryKpiInsight, libraryKpiMetrics } from "@/lib/mock/library-kpi" const activeIndexProps = (activeIndex: number | null) => activeIndex == null ? {} : ({ activeIndex } as Record) const BAR_CFG: ChartConfig = { count: { label: "Questions", color: "var(--color-chart-2)" }, } const TYPE_LABEL: Record = { multiple_choice: "Multiple choice", true_false: "True / false", short_answer: "Short answer", } function aggregateByType(rows: LibraryItem[]) { const c: Record = { multiple_choice: 0, true_false: 0, short_answer: 0, } for (const r of rows) c[r.type]++ return (Object.keys(c) as LibraryItemType[]).map(key => ({ name: TYPE_LABEL[key], value: c[key], key, })) } function aggregateByTopic(rows: LibraryItem[]) { const map = new Map() for (const r of rows) map.set(r.topic, (map.get(r.topic) ?? 0) + 1) return [...map.entries()] .map(([name, value]) => ({ name: name.length > 20 ? `${name.slice(0, 18)}…` : name, value })) .sort((a, b) => b.value - a.value) .slice(0, 8) } function QuestionsByTypeChart({ rows }: { rows: LibraryItem[] }) { const data = React.useMemo(() => aggregateByType(rows), [rows]) if (rows.length === 0) { return (
No questions in this view.
) } const summary = `Item types: ${data.map(d => `${d.name} ${d.value}`).join(", ")}. Total ${rows.length}.` return ( {(activeIndex) => ( <> } /> {data.map((_, i) => ( ))} [d.name, d.value])} /> )} ) } function QuestionsByTopicChart({ rows }: { rows: LibraryItem[] }) { const data = React.useMemo(() => aggregateByTopic(rows), [rows]) if (rows.length === 0) { return (
No questions in this view.
) } const summary = `${data.length} topics shown. Total ${rows.length} questions.` return ( {(activeIndex) => ( <> } /> {data.map((_, i) => ( ))} [d.name, d.value])} /> )} ) } export function LibraryDashboardChartsSection({ rows }: { rows: LibraryItem[] }) { const kpi = React.useMemo( () => ({ metrics: libraryKpiMetrics(rows), insight: libraryKpiInsight(rows), }), [rows], ) return (
) }