"use client"
/**
* Catalog detail-pane previews — compose real DS components (no bespoke stand-ins).
*/
import * as React from "react"
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"
import {
ChartCard,
ChartLeoPlotInsightOverlay,
CATALOG_PREVIEW_CHART_LEO,
type ChartCardVariant,
} from "@/components/charts-overview"
import { KeyMetrics, type MetricItem } from "@/components/key-metrics"
import { LibraryBoardCard, LibraryBoardView, LibraryListRowCard } from "@/components/library-board-view"
import { buildLibraryHubColumnDefs } from "@/components/library-table"
import { PageHeader } from "@/components/page-header"
import { Button } from "@/components/ui/button"
import { ColumnTypesRuleDemoTable } from "@/components/column-types-rule-demo-client"
import { DataTable, DataTableToolbar } from "@/components/data-table"
import { useTableState } from "@/components/data-table/use-table-state"
import type { ColumnDef } from "@/components/data-table/types"
import { HubTable } from "@/components/data-views"
import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
import { ViewSegmentedControl } from "@/components/ui/view-segmented-control"
import { CHART_AXIS_TICK } from "@/lib/chart-typography"
import { toggleLibraryItemFavorite } from "@/lib/library-nav"
import { LIBRARY_ITEMS, type LibraryItem } from "@/lib/mock/library"
import { cn } from "@/lib/utils"
const CATALOG_LIBRARY_ROWS: LibraryItem[] = LIBRARY_ITEMS.slice(0, 9)
const CATALOG_METRICS: MetricItem[] = [
{
id: "published",
label: "Published",
value: 128,
delta: "+6",
trend: "up",
trendPolarity: "higher_is_better",
progress: 82,
description: "82% of Q2 publishing goal",
},
{
id: "draft",
label: "Draft",
value: 14,
delta: "−2",
trend: "down",
trendPolarity: "higher_is_better",
progress: 28,
progressTone: "info",
description: "14 drafts awaiting faculty sign-off",
},
{
id: "review",
label: "In review",
value: 9,
delta: "",
trend: "neutral",
trendPolarity: "informational",
progress: 45,
description: "Median review time 3.2 days",
},
]
const CATALOG_CHART_DATA = [
{ month: "Jan", placements: 42 },
{ month: "Feb", placements: 58 },
{ month: "Mar", placements: 74 },
{ month: "Apr", placements: 68 },
{ month: "May", placements: 81 },
]
const catalogChartConfig = {
placements: { label: "Placements", color: "var(--brand-color)" },
} as const
const CATALOG_CHART_FILTER_OPTIONS = [
{ value: "30d", label: "Last 30 days" },
{ value: "90d", label: "Last quarter" },
{ value: "1y", label: "Last year" },
]
const CATALOG_CHART_VARIANT_OPTIONS: {
value: ChartCardVariant
label: string
icon: string
}[] = [
{ value: "normal", label: "Normal", icon: "fa-light fa-chart-column" },
{ value: "tabs", label: "Tabs", icon: "fa-light fa-table-columns" },
{ value: "selector", label: "Selector", icon: "fa-light fa-filter" },
{ value: "metrics-tabs", label: "Metrics", icon: "fa-light fa-gauge-high" },
{ value: "kpi-chart", label: "KPI", icon: "fa-light fa-hashtag" },
]
function CatalogMiniBarChart() {
return (
} />
)
}
const CATALOG_CHART_MINI_METRICS = [
{ label: "Placements", value: "128", trend: "up" as const, trendPolarity: "higher_is_better" as const },
{ label: "Applications", value: "214", trend: "up" as const, trendPolarity: "informational" as const },
{ label: "Reviews", value: "42", trend: "neutral" as const, trendPolarity: "informational" as const },
]
export function CatalogChartCardVariantPreview({
variant,
className,
}: {
variant: ChartCardVariant
className?: string
}) {
const needsMiniMetrics = variant === "metrics-tabs" || variant === "kpi-chart"
const needsSelectorFilter = variant === "selector"
return (
)
}
export function CatalogChartCardPreview({ className }: { className?: string }) {
const [variant, setVariant] = React.useState("metrics-tabs")
return (
setVariant(v as ChartCardVariant)}
aria-label="ChartCard variant"
options={CATALOG_CHART_VARIANT_OPTIONS}
/>
)
}
export function CatalogKeyMetricsPreview({ className }: { className?: string }) {
const [variant, setVariant] = React.useState<"flat" | "card" | "cards">("flat")
return (
)
}
export function CatalogPageHeaderPreview() {
return (
New question
}
/>
)
}
export function CatalogBoardCardPreview() {
return (
{}}
/>
)
}
export function CatalogLibraryListRowPreview() {
return (
{}}
/>
)
}
function CatalogLibraryHubTablePreview({
rows,
onRowsChange,
}: {
rows: LibraryItem[]
onRowsChange: React.Dispatch>
}) {
const toggleFavorite = React.useCallback(
(row: LibraryItem) => {
onRowsChange((prev) =>
prev.map((item) => (item.id === row.id ? toggleLibraryItemFavorite(item) : item)),
)
},
[onRowsChange],
)
const columns = React.useMemo(
() => buildLibraryHubColumnDefs(rows, toggleFavorite),
[rows, toggleFavorite],
)
return (
rows={rows}
columns={columns}
view="table"
hubLabel="Question bank"
lifecycleTabLabel="All questions"
searchAriaLabel="Search questions"
getRowId={(row) => row.id}
getRowSelectionLabel={(row) => row.stem}
defaultSort={{ key: "stem", dir: "asc" }}
emptyState="No questions."
renderers={{}}
supportedViewTypes={["table"]}
persistKey="catalog-preview:library-hub-table"
pagination={false}
/>
)
}
export function CatalogLibraryHubLivePreview({ className }: { className?: string }) {
const [view, setView] = React.useState<"table" | "board">("board")
const [rows, setRows] = React.useState(CATALOG_LIBRARY_ROWS)
const toggleFavorite = React.useCallback((row: LibraryItem) => {
setRows((prev) =>
prev.map((item) => (item.id === row.id ? toggleLibraryItemFavorite(item) : item)),
)
}, [])
return (
{view === "board" ? (
) : (
)}
)
}
export function CatalogHubTablePreview({ className }: { className?: string }) {
return (
)
}
type CatalogGridRow = {
id: string
name: string
status: string
updated: string
} & Record
const CATALOG_GRID_ROWS: CatalogGridRow[] = [
{ id: "q_101", name: "Diaphragm innervation", status: "Published", updated: "2026-06-01" },
{ id: "q_102", name: "Brachial plexus roots", status: "Draft", updated: "2026-06-02" },
{ id: "q_103", name: "Cranial nerve functions", status: "In review", updated: "2026-06-03" },
{ id: "q_104", name: "Lower limb dermatomes", status: "Published", updated: "2026-06-04" },
{ id: "q_105", name: "Spinal cord tracts", status: "Draft", updated: "2026-06-05" },
]
const CATALOG_GRID_COLUMNS: ColumnDef[] = [
{
key: "name",
label: "Question",
width: 280,
filter: { type: "text" },
},
{
key: "status",
label: "Status",
width: 120,
filter: {
type: "select",
options: [
{ value: "Published", label: "Published" },
{ value: "Draft", label: "Draft" },
{ value: "In review", label: "In review" },
],
},
},
{
key: "updated",
label: "Updated",
width: 120,
filter: { type: "date" },
},
]
/** Core grid only — sort, filters, resize. Hubs wrap this in HubTable (+ Properties, views). */
export function CatalogDataTablePreview({ className }: { className?: string }) {
const columns = React.useMemo(() => CATALOG_GRID_COLUMNS, [])
const state = useTableState(CATALOG_GRID_ROWS, columns, { key: "name", dir: "asc" })
return (
DataTable — the grid primitive. List hubs compose it
via HubTable (toolbar + Properties + board/list/dashboard).
row.id}
getRowSelectionLabel={(row) => row.name}
state={state}
defaultSort={{ key: "name", dir: "asc" }}
emptyState="No questions match your filters."
/>
)
}