Sales dashboard
Revenue over time against target.
Revenue
Northwind subscriptions, fiscal year 2026 to date
Q3 revenue
$4.42M
+10.4% Increase, goodvs Q2 2026
Q3 target attained
103%
Target $4.29M
September revenue
$1.52M
Target $1.47M
Revenue in all regions beat the monthly target in most months and reached $1.52M in September.
View data as a table
| Month | Revenue | Target |
|---|---|---|
| Jan 2026 | $1,160,000 | $1,150,000 |
| Feb 2026 | $1,195,000 | $1,190,000 |
| Mar 2026 | $1,235,000 | $1,230,000 |
| Apr 2026 | $1,290,000 | $1,270,000 |
| May 2026 | $1,330,000 | $1,310,000 |
| Jun 2026 | $1,385,000 | $1,350,000 |
| Jul 2026 | $1,430,000 | $1,390,000 |
| Aug 2026 | $1,470,000 | $1,430,000 |
| Sep 2026 | $1,520,000 | $1,470,000 |
Growth plans bring in almost half of the revenue; Enterprise grew fastest this year.
View data as a table
| Month | Starter | Growth | Enterprise | Total |
|---|---|---|---|---|
| Jan 2026 | $278,000 | $534,000 | $348,000 | $1,160,000 |
| Feb 2026 | $280,000 | $550,000 | $365,000 | $1,195,000 |
| Mar 2026 | $282,000 | $568,000 | $385,000 | $1,235,000 |
| Apr 2026 | $286,000 | $593,000 | $411,000 | $1,290,000 |
| May 2026 | $287,000 | $612,000 | $431,000 | $1,330,000 |
| Jun 2026 | $291,000 | $637,000 | $457,000 | $1,385,000 |
| Jul 2026 | $292,000 | $658,000 | $480,000 | $1,430,000 |
| Aug 2026 | $291,000 | $676,000 | $503,000 | $1,470,000 |
| Sep 2026 | $292,000 | $699,000 | $529,000 | $1,520,000 |
sales-dashboard.tsx
"use client";
import { useState } from "react";
import { AreaChart, ComboChart, MetricCard, Segment, SegmentedControl } from "@nexera-ui/react";
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"];
const MONTH_TITLES = MONTHS.map((m) => `${m} 2026`);
// Monthly subscription revenue in thousands of US dollars, per region, with the plan target.
const REGIONS = {
emea: {
label: "EMEA",
revenue: [620, 640, 655, 690, 700, 735, 760, 770, 800],
target: [600, 620, 640, 660, 680, 700, 720, 740, 760],
},
americas: {
label: "Americas",
revenue: [540, 555, 580, 600, 630, 650, 670, 700, 720],
target: [550, 570, 590, 610, 630, 650, 670, 690, 710],
},
} as const;
type RegionKey = "all" | keyof typeof REGIONS;
const add = (a: readonly number[], b: readonly number[]) => a.map((v, i) => v + (b[i] ?? 0));
const sum = (values: readonly number[]) => values.reduce((total, v) => total + v, 0);
const money = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
notation: "compact",
maximumFractionDigits: 2,
});
const percent = new Intl.NumberFormat("en-US", { style: "percent", maximumFractionDigits: 1 });
const change = new Intl.NumberFormat("en-US", {
style: "percent",
maximumFractionDigits: 1,
signDisplay: "exceptZero",
});
function regionData(region: RegionKey) {
if (region !== "all")
return { revenue: [...REGIONS[region].revenue], target: [...REGIONS[region].target] };
return {
revenue: add(REGIONS.emea.revenue, REGIONS.americas.revenue),
target: add(REGIONS.emea.target, REGIONS.americas.target),
};
}
/** Sales dashboard: Northwind subscription revenue by month against target, by plan, filterable by region. */
export default function SalesDashboard() {
const [region, setRegion] = useState<RegionKey>("all");
const [range, setRange] = useState("9m");
const { revenue, target } = regionData(region);
const count = range === "3m" ? 3 : range === "6m" ? 6 : 9;
const q3 = sum(revenue.slice(6)) * 1000;
const q2 = sum(revenue.slice(3, 6)) * 1000;
const attainment = sum(revenue.slice(6)) / sum(target.slice(6));
const regionName = region === "all" ? "all regions" : REGIONS[region].label;
const usd = { style: "currency", currency: "USD", maximumFractionDigits: 0 } as const;
return (
<div className="@container bg-page px-4 py-8 @3xl:px-8">
<div className="mx-auto grid max-w-6xl gap-6">
<header className="flex flex-wrap items-end justify-between gap-4">
<div className="grid gap-1">
<h2 className="text-heading-h2 text-primary">Revenue</h2>
<p className="text-body-default text-secondary">
Northwind subscriptions, fiscal year 2026 to date
</p>
</div>
<SegmentedControl
aria-label="Region"
selectedKeys={[region]}
onSelectionChange={(keys) => {
setRegion(([...keys][0] ?? "all") as RegionKey);
}}
>
<Segment id="all" label="All regions" />
<Segment id="emea" label="EMEA" />
<Segment id="americas" label="Americas" />
</SegmentedControl>
</header>
<div className="grid gap-4 @3xl:grid-cols-3">
<MetricCard
type="trend"
label="Q3 revenue"
value={money.format(q3)}
delta={change.format(q3 / q2 - 1)}
caption="vs Q2 2026"
/>
<MetricCard
type="progress"
label="Q3 target attained"
value={percent.format(attainment)}
progress={Math.min(100, Math.round(attainment * 100))}
caption={`Target ${money.format(sum(target.slice(6)) * 1000)}`}
/>
<MetricCard
type="simple"
label="September revenue"
value={money.format((revenue[8] ?? 0) * 1000)}
caption={`Target ${money.format((target[8] ?? 0) * 1000)}`}
/>
</div>
<div className="grid gap-4 @5xl:grid-cols-2">
<ComboChart
title="Revenue against target"
description={`Per month, ${regionName}`}
summary={`Revenue in ${regionName} beat the monthly target in most months and reached ${money.format((revenue[8] ?? 0) * 1000)} in September.`}
categories={MONTHS.slice(-count)}
categoryTitles={MONTH_TITLES.slice(-count)}
series={[
{ name: "Revenue", type: "bar", data: revenue.slice(-count).map((v) => v * 1000) },
{
name: "Target",
type: "line",
data: target.slice(-count).map((v) => v * 1000),
styleIndex: 7,
},
]}
valueFormat={usd}
range={{
"aria-label": "Range",
options: [
{ id: "3m", label: "3M" },
{ id: "6m", label: "6M" },
{ id: "9m", label: "YTD" },
],
value: range,
onChange: setRange,
}}
table={{ categoryLabel: "Month" }}
/>
<AreaChart
title="Revenue by plan"
description={`Stacked, ${regionName}`}
summary="Growth plans bring in almost half of the revenue; Enterprise grew fastest this year."
categories={MONTHS}
categoryTitles={MONTH_TITLES}
series={[
{
name: "Starter",
data: revenue.map((v, i) => Math.round(v * (0.24 - i * 0.006)) * 1000),
},
{ name: "Growth", data: revenue.map((v) => Math.round(v * 0.46) * 1000) },
{
name: "Enterprise",
data: revenue.map(
(v, i) => (v - Math.round(v * (0.24 - i * 0.006)) - Math.round(v * 0.46)) * 1000,
),
},
]}
valueFormat={usd}
smooth
table={{ categoryLabel: "Month" }}
/>
</div>
</div>
</div>
);
}
More dashboards and analytics blocks
- KPI overviewFour headline metrics with trend and change.
- People analyticsHeadcount by team, type and tenure.
- Recruitment funnelApplicants at each stage and the drop-off between.
- Engagement survey resultseNPS score and check-in patterns across the week.
- Budget varianceHow the budget moved from plan to actual.
- Skills comparisonOne person against the team average.
- Live status boardReal-time counts with tiny trends.
- Chart statesLoading, empty and error versions of any chart.