Cursor

import { useMemo } from "react";

import { InsightCard } from "./InsightCard";

import { FindingsChart } from "./FindingsChart";

import { ResearchFilters } from "./ResearchFilters";

type Finding = {

id: string;

label: string;

confidence: number;

trend: number[];

category: "product" | "market" | "ops";

};

export function ResearchDashboard({

findings,

}: {

findings: Finding[];

}) {

const summary = useMemo(() => {

return findings.reduce(

(acc, finding) => {

acc.total += 1;

acc.avgConfidence += finding.confidence;

if (finding.category === "product") acc.product += 1;

return acc;

},

{ total: 0, avgConfidence: 0, product: 0 },

);

}, [findings]);

const avgConfidence =

summary.total > 0 ? Math.round(summary.avgConfidence / summary.total) : 0;

return (

<section className="grid gap-6">

<header className="flex items-end justify-between">

<div>

<h1 className="text-2xl font-semibold">Research Dashboard</h1>

<p className="text-sm text-slate-500">

Explore findings, confidence, and rollout readiness.

</p>

</div>

<ResearchFilters />

</header>

<div className="grid grid-cols-3 gap-4">

<InsightCard label="Findings" value={summary.total} />

<InsightCard label="Avg confidence" value={`${avgConfidence}%`} />

<InsightCard label="Product signals" value={summary.product} />

</div>

<div className="rounded-2xl border border-slate-200 p-5">

<FindingsChart

series={findings.map((finding) => ({

id: finding.id,

label: finding.label,

points: finding.trend,

}))}

/>

</div>

</section>

);

}

Read the original on cursor.com ↗