Reports & Analytics
Last updated on 2026-09-02
The reports module provides four analytics screens covering sales performance, pipeline health, team metrics, and revenue segmentation. All data comes from aggregate Supabase queries executed via Server Actions in lib/actions/reports.ts. Charts use Recharts wrapped in shadcn/ui ChartContainer for consistent theming.
Sales Overview
Route: /reports
The main reporting dashboard with configurable date range and high-level sales metrics.
- Date range selector -- pill-style buttons for 7d, 30d, 90d, and All time; the selected range is passed to Supabase queries as date filters
- KPI cards -- four
StatCardcomponents with data from aggregate queries:- Revenue --
SUM(deals.value) WHERE stage = 'closed_won'with trend percentage vs previous period - Deals Won --
COUNT(deals) WHERE stage = 'closed_won'with trend - Average Deal Size --
AVG(deals.value) WHERE stage = 'closed_won' - Win Rate --
closed_won / (closed_won + closed_lost) * 100
- Revenue --
- Revenue trend area chart -- Recharts
AreaChartwith data points aggregated by day/week/month fromdeals.created_at - Deals won vs lost bar chart -- grouped
BarChartcomparing won and lost deal counts by month - Revenue by source pie chart --
PieChartwith revenue grouped bydeals.source - Top performing reps table -- ranked by total revenue from won deals, joined with
profilesfor avatar and name
Sales Overview Layout
+----------+----------+----------+----------+
| Revenue | Deals | Avg Deal | Win |
| | Won | Size | Rate |
+----------+----------+----------+----------+
| Revenue Trend | Won vs Lost |
| (area chart) | (bar chart) |
+---------------------+---------------------+
| Revenue by Source | Top Performing |
| (pie chart) | Reps (table) |
+---------------------+---------------------+
Example Query
// lib/actions/reports.ts (simplified)
export async function getRevenueBySource(dateRange: DateRange) {
const supabase = await createServerClient()
const { data } = await supabase
.from("deals")
.select("source, value")
.eq("stage_id", closedWonStageId)
.gte("created_at", dateRange.start)
.lte("created_at", dateRange.end)
// Group and sum by source
return groupBy(data, "source").map(([source, deals]) => ({
source,
revenue: deals.reduce((sum, d) => sum + d.value, 0),
}))
}
Pipeline Analytics
Route: /reports/pipeline
Pipeline health metrics and conversion analysis with data from the deals, pipeline_stages, and activities tables.
- Conversion funnel -- horizontal funnel showing deal count and conversion rate at each stage transition, calculated from deal stage history in
activities - Deals by stage bar chart -- vertical
BarChartwith deal count per stage, colored to match pipeline stage colors - Average time in stage -- horizontal bar chart showing mean days deals spend in each stage, calculated from
activitiestimestamps - Pipeline velocity metrics -- four cards:
- Average Sales Cycle -- mean days from first stage to Closed Won
- Pipeline Value --
SUM(deals.value)for all open deals - Weighted Pipeline --
SUM(deals.value * deals.probability / 100) - Conversion Rate --
closed_won / (closed_won + closed_lost) * 100
- Stalled deals alert -- deals not changing stage in 14+ days, identified by comparing
deals.updated_atto current date
Pipeline Velocity Metrics
| Metric | Calculation | Description |
|---|---|---|
| Average Sales Cycle | Mean days from Lead to Closed Won | How long deals take to close |
| Pipeline Value | Sum of all open deal values | Total potential revenue |
| Weighted Pipeline | Sum of (value x probability) for open deals | Probability-adjusted revenue |
| Conversion Rate | Closed Won / Total Closed | Percentage of deals won |
Team Performance
Route: /reports/team
Individual and team performance analytics with data joined from profiles, deals, and activities.
- Leaderboard table -- ranked by revenue:
- Rank badges -- gold (1st), silver (2nd), bronze (3rd) medal icons
- Rep info -- avatar and name from
profiles - Deals won --
COUNT(deals) WHERE stage = closed_won AND owner_id = profile.id - Revenue --
SUM(deals.value)for won deals - Win rate -- won / total closed percentage
- Quota attainment --
SUM(won revenue) / profiles.quota * 100with progress bar
- Expandable rep details -- per-rep deal breakdown, monthly trend, and recent activities
- Team radar chart -- Recharts
RadarChartcomparing performance across 6 dimensions - Activity donut chart --
PieChartshowing activity type distribution fromactivitiesgrouped bytype
Leaderboard Layout
+----+--------------+-------+----------+--------+------------------+
| # | Rep | Won | Revenue | Win % | Quota Attainment |
+----+--------------+-------+----------+--------+------------------+
| 1 | Sarah Chen | 12 | $485,000 | 68% | ############ 112%|
| 2 | Mike Johnson | 10 | $392,000 | 62% | #########... 89% |
| 3 | Lisa Park | 9 | $367,000 | 58% | ########.... 82% |
| 4 | Tom Wilson | 7 | $284,000 | 54% | ######...... 64% |
+----+--------------+-------+----------+--------+------------------+
Revenue Breakdown
Route: /reports/revenue
Detailed revenue segmentation with data from deals, companies, and deal_products.
- Revenue by product -- horizontal
BarChartwith revenue per product fromdeal_productsjoined withdeals(closed won), sorted by revenue descending - Revenue by industry --
PieChart(donut) breaking down revenue bycompanies.industryfor won deals - Deal size distribution -- histogram
BarChartshowing deal count in value ranges ($0-10K, $10-25K, $25-50K, $50-100K, $100K+) - Recurring vs one-time revenue -- stacked
AreaChartshowing revenue trends over time - Customer lifetime value table -- top companies ranked by total deal value, with columns for company name, total revenue, deal count, first deal date, average deal size, and LTV
Revenue Breakdown Layout
+---------------------+---------------------+
| Revenue by Product | Revenue by Industry |
| (horizontal bar) | (donut chart) |
+---------------------+---------------------+
| Deal Size | Recurring vs |
| Distribution | One-Time Revenue |
| (histogram) | (stacked area) |
+---------------------+---------------------+
| Customer Lifetime Value (table) |
+-------------------------------------------+
Charts Architecture
All report charts follow a consistent pattern using Recharts wrapped in shadcn/ui ChartContainer:
import { ChartContainer, ChartConfig, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
import { AreaChart, Area, XAxis, YAxis } from "recharts"
const chartConfig: ChartConfig = {
revenue: {
label: "Revenue",
color: "oklch(0.585 0.233 270)",
},
}
function RevenueTrendChart({ data }: { data: RevenueDataPoint[] }) {
return (
<ChartContainer config={chartConfig}>
<AreaChart data={data}>
<XAxis dataKey="month" />
<YAxis />
<ChartTooltip content={<ChartTooltipContent />} />
<Area
type="monotone"
dataKey="revenue"
fill="var(--color-revenue)"
stroke="var(--color-revenue)"
fillOpacity={0.2}
/>
</AreaChart>
</ChartContainer>
)
}
Next Steps
- Server Actions -- complete reference for the
reports.tsServer Actions - Deals & Pipeline -- Kanban pipeline board and deal management
- Design Tokens -- oklch color system and theming