Move pie chart labels to middle

This commit is contained in:
2025-01-17 20:06:09 -05:00
parent 7a3a6fdb52
commit 0727529edf
2 changed files with 112 additions and 10 deletions

View File

@@ -1,9 +1,10 @@
import { useQuery } from "@tanstack/react-query"
import { CardHeader, CardTitle, CardContent } from "@/components/ui/card"
import { PieChart, Pie, ResponsiveContainer, Cell, Tooltip } from "recharts"
import { PieChart, Pie, ResponsiveContainer, Cell, Tooltip, Sector } from "recharts"
import config from "@/config"
import { formatCurrency } from "@/lib/utils"
import { ClipboardList, AlertCircle, Layers, DollarSign, ShoppingCart } from "lucide-react" // Importing icons
import { useState } from "react"
interface PurchaseMetricsData {
activePurchaseOrders: number
@@ -31,7 +32,57 @@ const COLORS = [
"#FF7C43",
]
const renderActiveShape = (props: any) => {
const { cx, cy, innerRadius, vendor, cost } = props;
// Split vendor name into words and create lines of max 12 chars
const words = vendor.split(' ');
const lines: string[] = [];
let currentLine = '';
words.forEach((word: string) => {
if ((currentLine + ' ' + word).length <= 12) {
currentLine = currentLine ? `${currentLine} ${word}` : word;
} else {
if (currentLine) lines.push(currentLine);
currentLine = word;
}
});
if (currentLine) lines.push(currentLine);
return (
<g>
{lines.map((line, i) => (
<text
key={i}
x={cx}
y={cy}
dy={-20 + (i * 16)}
textAnchor="middle"
fill="#888888"
className="text-xs"
>
{line}
</text>
))}
<text
x={cx}
y={cy}
dy={lines.length * 16 - 10}
textAnchor="middle"
fill="#000000"
className="text-base font-medium"
>
{formatCurrency(cost)}
</text>
{props.children}
</g>
);
};
export function PurchaseMetrics() {
const [activeIndex, setActiveIndex] = useState<number | undefined>();
const { data } = useQuery<PurchaseMetricsData>({
queryKey: ["purchase-metrics"],
queryFn: async () => {
@@ -104,6 +155,10 @@ export function PurchaseMetrics() {
innerRadius={60}
outerRadius={80}
paddingAngle={2}
activeIndex={activeIndex}
activeShape={renderActiveShape}
onMouseEnter={(_, index) => setActiveIndex(index)}
onMouseLeave={() => setActiveIndex(undefined)}
>
{data?.vendorOrders?.map((entry, index) => (
<Cell
@@ -112,10 +167,6 @@ export function PurchaseMetrics() {
/>
))}
</Pie>
<Tooltip
formatter={(value: number) => formatCurrency(value)}
labelFormatter={(label: string) => `Vendor: ${label}`}
/>
</PieChart>
</ResponsiveContainer>
</div>

View File

@@ -1,9 +1,10 @@
import { useQuery } from "@tanstack/react-query"
import { CardHeader, CardTitle, CardContent } from "@/components/ui/card"
import { PieChart, Pie, ResponsiveContainer, Cell, Tooltip } from "recharts"
import { PieChart, Pie, ResponsiveContainer, Cell, Tooltip, Sector } from "recharts"
import config from "@/config"
import { formatCurrency } from "@/lib/utils"
import { Package, Layers, DollarSign, ShoppingCart } from "lucide-react" // Importing icons
import { useState } from "react"
interface StockMetricsData {
totalProducts: number
@@ -31,7 +32,57 @@ const COLORS = [
"#FF7C43",
]
const renderActiveShape = (props: any) => {
const { cx, cy, innerRadius, vendor, cost } = props;
// Split vendor name into words and create lines of max 12 chars
const words = vendor.split(' ');
const lines: string[] = [];
let currentLine = '';
words.forEach((word: string) => {
if ((currentLine + ' ' + word).length <= 12) {
currentLine = currentLine ? `${currentLine} ${word}` : word;
} else {
if (currentLine) lines.push(currentLine);
currentLine = word;
}
});
if (currentLine) lines.push(currentLine);
return (
<g>
{lines.map((line, i) => (
<text
key={i}
x={cx}
y={cy}
dy={-20 + (i * 16)}
textAnchor="middle"
fill="#888888"
className="text-xs"
>
{line}
</text>
))}
<text
x={cx}
y={cy}
dy={lines.length * 16 - 10}
textAnchor="middle"
fill="#000000"
className="text-base font-medium"
>
{formatCurrency(cost)}
</text>
{props.children}
</g>
);
};
export function StockMetrics() {
const [activeIndex, setActiveIndex] = useState<number | undefined>();
const { data } = useQuery<StockMetricsData>({
queryKey: ["stock-metrics"],
queryFn: async () => {
@@ -104,6 +155,10 @@ export function StockMetrics() {
innerRadius={60}
outerRadius={80}
paddingAngle={2}
activeIndex={activeIndex}
activeShape={renderActiveShape}
onMouseEnter={(_, index) => setActiveIndex(index)}
onMouseLeave={() => setActiveIndex(undefined)}
>
{data?.vendorStock?.map((entry, index) => (
<Cell
@@ -112,10 +167,6 @@ export function StockMetrics() {
/>
))}
</Pie>
<Tooltip
formatter={(value: number) => formatCurrency(value)}
labelFormatter={(label: string) => `Vendor: ${label}`}
/>
</PieChart>
</ResponsiveContainer>
</div>