From 1573d8dfbcc493e0656e3948295240908b39e098 Mon Sep 17 00:00:00 2001
From: Shaheer Sarfaraz <53654735+DaKheera47@users.noreply.github.com>
Date: Fri, 20 Feb 2026 01:39:54 +0000
Subject: [PATCH] response rate by source chart (#207)
* response rate by source
* docs
* add gpt improvements
* mobile resp
* UX
* chartkpi
---
docs-site/docs/features/overview.md | 29 +-
orchestrator/package.json | 1 +
.../components/charts/ChartKpiPanel.tsx | 43 +++
.../components/charts/ConversionAnalytics.tsx | 28 +-
.../charts/ResponseRateBySourceChart.tsx | 294 ++++++++++++++++++
.../src/client/components/charts/index.ts | 1 +
orchestrator/src/client/pages/HomePage.tsx | 8 +-
orchestrator/src/components/ui/switch.tsx | 27 ++
package-lock.json | 30 ++
9 files changed, 436 insertions(+), 25 deletions(-)
create mode 100644 orchestrator/src/client/components/charts/ChartKpiPanel.tsx
create mode 100644 orchestrator/src/client/components/charts/ResponseRateBySourceChart.tsx
create mode 100644 orchestrator/src/components/ui/switch.tsx
diff --git a/docs-site/docs/features/overview.md b/docs-site/docs/features/overview.md
index 2621942..f65797a 100644
--- a/docs-site/docs/features/overview.md
+++ b/docs-site/docs/features/overview.md
@@ -1,7 +1,7 @@
---
id: overview
title: Overview
-description: Dashboard analytics for application volume and conversion over selectable time windows.
+description: Dashboard analytics for application volume, conversion, and response rate by source over selectable time windows.
sidebar_position: 1
---
@@ -16,6 +16,7 @@ It visualizes:
- Applications per day
- Application-to-response conversion
- Funnel progression (Applied, Screening, Interview, Offer, Rejected)
+- Response rate by source
### Graph-level views
@@ -32,6 +33,7 @@ Use it to quickly answer:
- Are application volumes increasing or dropping?
- Is response conversion improving?
- Where are applications stalling in the funnel?
+- Which job boards are actually generating responses?
## How to use it
@@ -40,6 +42,7 @@ Use it to quickly answer:
3. Review:
- **Applications per day** for volume trend
- **Application → Response Conversion** for quality/outcome trend
+ - **Response Rate by Source** to compare job board effectiveness
4. Compare periods and adjust your sourcing terms, filters, or tailoring strategy.
### Data and calculation defaults
@@ -48,6 +51,20 @@ Use it to quickly answer:
- Only jobs in statuses `applied` and `in_progress` are used as input.
- Conversion counts any positive response-stage event (for example recruiter screen, assessment, interview stages, or offer).
- Conversion trend chart uses a rolling window up to 7 days.
+- Response rate by source is calculated across all time (not scoped to the duration selector), since response events may arrive well after the application window.
+- Sources with fewer than 5 applications are hidden by default in the Response Rate by Source chart. Check **Include small samples** to show them.
+
+### Response Rate by Source
+
+The **Response Rate by Source** chart shows, for each job board (LinkedIn, Indeed, Gradcracker, etc.), what percentage of your applications received a non-rejection response.
+
+**What counts as a response:** the application reached at least one of these stages — recruiter screen, assessment, hiring manager screen, technical interview, onsite, or offer. Ghosted applications (no stage events) and rejected outcomes are both excluded from the numerator.
+
+Each bar is labelled `X% (n=Y)` where `n` is the number of applications from that source, so you can immediately tell whether a high rate comes from a meaningful sample or a single lucky application. The full breakdown (response rate, responded, applied) is also shown in the tooltip.
+
+Sources are sorted by response rate descending. Sources with fewer than 5 applications are hidden by default to avoid misleading percentages from tiny samples. Check **Include small samples** to show them.
+
+Use this chart to identify which sources produce genuine engagement versus silence, and concentrate future sourcing effort accordingly.
## Common problems
@@ -66,6 +83,16 @@ Use it to quickly answer:
- Volume trend compares first-half vs second-half averages in the selected window.
- Changing the time window can materially change trend direction.
+### Response Rate by Source shows only one source
+
+- Only sources with at least one applied job appear in the chart.
+- If all your applications come from a single board, only that board will be shown.
+
+### Response rate for a source looks too high or too low
+
+- Check the `n=` value in the bar label or tooltip. A small sample (e.g. n=2) will produce an unreliable rate.
+- Sources with fewer than 5 applications are hidden by default. If you see a suspiciously high rate, you may be looking at a small-sample source — check the n.
+
## Related pages
- [Orchestrator](/docs/next/features/orchestrator)
diff --git a/orchestrator/package.json b/orchestrator/package.json
index 4f31008..f47921a 100644
--- a/orchestrator/package.json
+++ b/orchestrator/package.json
@@ -41,6 +41,7 @@
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
+ "@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@tailwindcss/vite": "^4.1.18",
diff --git a/orchestrator/src/client/components/charts/ChartKpiPanel.tsx b/orchestrator/src/client/components/charts/ChartKpiPanel.tsx
new file mode 100644
index 0000000..792ccaa
--- /dev/null
+++ b/orchestrator/src/client/components/charts/ChartKpiPanel.tsx
@@ -0,0 +1,43 @@
+/**
+ * ChartKpiPanel
+ * Reusable stat block used in card headers: label, bold rate, trend icon, subtext.
+ */
+
+import { TrendingDown, TrendingUp } from "lucide-react";
+
+interface ChartKpiPanelProps {
+ label: string;
+ rate: number;
+ subtext: string;
+ /** Rate below this threshold shows TrendingDown. Default 10. */
+ lowThreshold?: number;
+ /** Rate above this threshold shows TrendingUp. Default 25. */
+ highThreshold?: number;
+}
+
+export function ChartKpiPanel({
+ label,
+ rate,
+ subtext,
+ lowThreshold = 10,
+ highThreshold = 25,
+}: ChartKpiPanelProps) {
+ return (
+