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;