"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,
type ChartCardVariant,
} from "@/components/charts-core";
import { CATALOG_PREVIEW_CHART_LEO } from "@/lib/catalog-preview-chart-leo";
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 } 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",
href: "#published",
chart: {
kind: "sparkline",
series: [
{ value: 98, label: "Jan" },
{ value: 104, label: "Feb" },
{ value: 110, label: "Mar" },
{ value: 116, label: "Apr" },
{ value: 122, label: "May" },
{ value: 128, label: "Jun" },
],
},
},
{
id: "draft",
label: "Draft",
value: 14,
delta: "-2",
trend: "down",
trendPolarity: "higher_is_better",
href: "#draft",
chart: {
kind: "bars",
tone: "info",
series: [
{ value: 18, label: "Mon" },
{ value: 16, label: "Tue" },
{ value: 15, label: "Wed" },
{ value: 17, label: "Thu" },
{ value: 14, label: "Fri" },
{ value: 14, label: "Sat" },
{ value: 14, label: "Sun" },
],
},
},
{
id: "review",
label: "In review",
value: 9,
delta: "",
trend: "neutral",
trendPolarity: "informational",
href: "#review",
progress: 45,
},
{
id: "flags",
label: "Review flags",
value: 2,
delta: "+1",
trend: "up",
trendPolarity: "lower_is_better",
href: "#flags",
alert: "danger",
chart: {
kind: "sparkline",
tone: "danger",
series: [
{ value: 1, label: "Week 1" },
{ value: 0, label: "Week 2" },
{ value: 1, label: "Week 3" },
{ value: 1, label: "Week 4" },
{ value: 2, label: "Week 5" },
],
},
},
];
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<"cards" | "card" | "flat">(
"cards",
);
const [size, setSize] = React.useState<"sm" | "md" | "lg">("md");
return (
);
}
export function CatalogPageHeaderPreview() {
return (
New record
}
/>
);
}
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."
/>
);
}