diff --git a/package.json b/package.json
index 61a4748..5e7e065 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
"lucide-react": "^0.441.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "react-router-dom": "^6.26.0"
+ "react-router-dom": "^6.26.0",
+ "recharts": "^2.13.3"
},
"devDependencies": {
"@types/react": "^18.3.5",
diff --git a/src/components/BarChart.tsx b/src/components/BarChart.tsx
index 5439626..483ca8f 100644
--- a/src/components/BarChart.tsx
+++ b/src/components/BarChart.tsx
@@ -1,3 +1,5 @@
+import { BarChart as RBarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, ResponsiveContainer, Cell } from "recharts";
+
interface Row {
dimension: unknown;
value: unknown;
@@ -9,9 +11,12 @@ interface Props {
loading?: boolean;
}
+const RED_PALETTE = ["#C8102E", "#E84258", "#F26471", "#F69199", "#FABFBF"];
+
export default function BarChart({ title, rows, loading }: Props) {
- const data = (rows ?? []).map(r => ({ label: String(r.dimension ?? "—"), value: Number(r.value ?? 0) }));
- const max = Math.max(1, ...data.map(d => d.value));
+ const data = (rows ?? [])
+ .map(r => ({ name: String(r.dimension ?? "—"), value: Number(r.value ?? 0) }))
+ .filter(d => d.name && d.name !== "—" && d.value > 0);
return (
@@ -27,24 +32,18 @@ export default function BarChart({ title, rows, loading }: Props) {
) : data.length === 0 ? (
No data
) : (
-
- {data.map((d, i) => {
- const pct = (d.value / max) * 100;
- return (
-
-
{d.label}
-
-
- {d.value.toLocaleString("en-IN")}
-
-
- );
- })}
+
+
+
+
+
+
+
+
+ {data.map((_, i) => | )}
+
+
+
)}
diff --git a/src/components/PieChart.tsx b/src/components/PieChart.tsx
new file mode 100644
index 0000000..6c3d90e
--- /dev/null
+++ b/src/components/PieChart.tsx
@@ -0,0 +1,53 @@
+import { PieChart as RPieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer } from "recharts";
+
+interface Row {
+ dimension: unknown;
+ value: unknown;
+}
+
+interface Props {
+ title?: string;
+ rows: Row[];
+ loading?: boolean;
+}
+
+const RED_PALETTE = ["#C8102E", "#E84258", "#F26471", "#F69199", "#FABFBF", "#FFD7D7"];
+
+export default function PieChart({ title, rows, loading }: Props) {
+ const data = (rows ?? [])
+ .map(r => ({ name: String(r.dimension ?? "—"), value: Number(r.value ?? 0) }))
+ .filter(d => d.name && d.name !== "—" && d.value > 0);
+
+ return (
+
+ {title && (
+
+ {title}
+
+ )}
+ {loading ? (
+
+ ) : data.length === 0 ? (
+
No data
+ ) : (
+
+
+
+
+ {data.map((_, i) => | )}
+
+
+
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/RecordViewTable.tsx b/src/components/RecordViewTable.tsx
index ba047e2..bd1f196 100644
--- a/src/components/RecordViewTable.tsx
+++ b/src/components/RecordViewTable.tsx
@@ -8,6 +8,7 @@ import { getRVScreen, getRecordView, type RecordViewField, type SearchQuery, typ
import FormModal from "./FormModal";
import Tile from "./Tile";
import BarChart from "./BarChart";
+import PieChart from "./PieChart";
// ---------------------------------------------------------------------------
// Action column (config-driven from rv-screen layout)
@@ -147,7 +148,7 @@ interface Props {
type AnalyticsSpec =
| { kind: "tile"; uid: string; title?: string }
- | { kind: "chart"; uid: string; title?: string };
+ | { kind: "chart"; uid: string; title?: string; chartType?: string };
// Walk rv-screen layout to find rv_tile / rv_chart elements (the platform
// places them as sibling blocks above the rv_table).
@@ -157,7 +158,7 @@ function extractAnalyticsElements(layout: any): AnalyticsSpec[] {
for (const n of nodes ?? []) {
const cfg = n?.config;
if (cfg?.type === "rv_tile" && cfg.tile_uid) out.push({ kind: "tile", uid: cfg.tile_uid, title: cfg.title });
- if (cfg?.type === "rv_chart" && cfg.chart_uid) out.push({ kind: "chart", uid: cfg.chart_uid, title: cfg.title });
+ if (cfg?.type === "rv_chart" && cfg.chart_uid) out.push({ kind: "chart", uid: cfg.chart_uid, title: cfg.title, chartType: cfg.chart_type });
if (Array.isArray(n?.children)) walk(n.children);
}
};
@@ -275,7 +276,8 @@ export default function RecordViewTable({ viewId, onRowClick, toolbarAction }: P
return
;
}
const cd = chartData.find(c => c.chart_uid === a.uid);
- return
;
+ const Chart = a.chartType === "pie" ? PieChart : BarChart;
+ return
;
})}
) : null;