c-chart-22.tsx
"use client"
import { CSSProperties } from "react"
import { Label, Pie, PieChart, Sector, type PieSectorDataItem } from "recharts"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import {
ChartContainer,
ChartLegend,
ChartLegendContent,
ChartTooltip,
ChartTooltipContent,
type ChartConfig,
} from "@/components/ui/chart"
const chartData = [
{ plan: "free", users: 12800, fill: "var(--color-free)" },
{ plan: "starter", users: 5400, fill: "var(--color-starter)" },
{ plan: "pro", users: 3600, fill: "var(--color-pro)" },
{ plan: "enterprise", users: 1200, fill: "var(--color-enterprise)" },
]
const totalUsers = chartData.reduce((sum, d) => sum + d.users, 0)
const paidUsers = totalUsers - chartData[0].users
const conversionRate = ((paidUsers / totalUsers) * 100).toFixed(1)
const chartConfig = {
users: { label: "Users" },
free: { label: "Free", color: "var(--chart-5)" },
starter: { label: "Starter", color: "var(--chart-3)" },
pro: { label: "Pro", color: "var(--chart-2)" },
enterprise: { label: "Enterprise", color: "var(--chart-1)" },
} satisfies ChartConfig
export function Pattern() {
return (
<Card className="w-full max-w-xs">
<CardHeader className="items-center pb-0">
<CardTitle>Conversion Funnel</CardTitle>
<CardDescription>
{conversionRate}% of users are on paid plans
</CardDescription>
</CardHeader>
<CardContent className="flex-1 pb-0">
<ChartContainer
config={chartConfig}
className="mx-auto aspect-square max-h-[300px]"
>
<PieChart accessibilityLayer>
<ChartTooltip
content={
<ChartTooltipContent
className="min-w-40 gap-2.5"
formatter={(value, name) => (
<div className="flex w-full items-center justify-between gap-2">
<div className="flex items-center gap-1.5">
<div
className="h-2.5 w-2.5 shrink-0 rounded-xs bg-(--color-bg)"
style={
{
"--color-bg": `var(--color-${name})`,
} as CSSProperties
}
/>
<span className="text-muted-foreground">
{chartConfig[name as keyof typeof chartConfig]
?.label || name}
</span>
</div>
<span className="text-foreground font-semibold tabular-nums">
{Number(value).toLocaleString()}
</span>
</div>
)}
/>
}
/>
<ChartLegend
content={<ChartLegendContent nameKey="plan" />}
className="-translate-y-2"
/>
<Pie
data={chartData}
dataKey="users"
nameKey="plan"
innerRadius={55}
cornerRadius={5}
paddingAngle={3}
stroke="var(--background)"
strokeWidth={3}
activeShape={({
outerRadius = 0,
...props
}: PieSectorDataItem) => (
<Sector {...props} outerRadius={outerRadius + 10} />
)}
>
<Label
content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return (
<text
x={viewBox.cx}
y={viewBox.cy}
textAnchor="middle"
dominantBaseline="middle"
>
<tspan
x={viewBox.cx}
y={viewBox.cy}
className="fill-foreground text-2xl font-bold tabular-nums"
>
{paidUsers.toLocaleString()}
</tspan>
<tspan
x={viewBox.cx}
y={(viewBox.cy || 0) + 20}
className="fill-muted-foreground text-xs"
>
Paid Users
</tspan>
</text>
)
}
}}
/>
</Pie>
</PieChart>
</ChartContainer>
</CardContent>
</Card>
)
}


























