food sale chart
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { type FC } from 'react'
|
import { type FC } from 'react'
|
||||||
import { Cell, Pie, PieChart, ResponsiveContainer } from 'recharts'
|
import { Cell, LabelList, Pie, PieChart, ResponsiveContainer } from 'recharts'
|
||||||
|
|
||||||
interface FoodSalesChartProps {
|
interface FoodSalesChartProps {
|
||||||
data?: Array<{ name: string; value: number; color: string }>
|
data?: Array<{ name: string; value: number; color: string }>
|
||||||
@@ -8,8 +8,8 @@ interface FoodSalesChartProps {
|
|||||||
const FoodSalesChart: FC<FoodSalesChartProps> = ({ data }) => {
|
const FoodSalesChart: FC<FoodSalesChartProps> = ({ data }) => {
|
||||||
const defaultData = [
|
const defaultData = [
|
||||||
{ name: 'پیتزا', value: 50, color: '#6B7FED' },
|
{ name: 'پیتزا', value: 50, color: '#6B7FED' },
|
||||||
{ name: 'پاستا', value: 25, color: '#A78BFA' },
|
{ name: 'برگر', value: 25, color: '#A78BFA' },
|
||||||
{ name: 'رامن', value: 15, color: '#FF6B9D' },
|
{ name: 'پاستا', value: 15, color: '#FF6B9D' },
|
||||||
{ name: 'نوشیدنی ها', value: 10, color: '#FF9A62' }
|
{ name: 'نوشیدنی ها', value: 10, color: '#FF9A62' }
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -17,18 +17,23 @@ const FoodSalesChart: FC<FoodSalesChartProps> = ({ data }) => {
|
|||||||
|
|
||||||
const total = chartData.reduce((sum, item) => sum + item.value, 0)
|
const total = chartData.reduce((sum, item) => sum + item.value, 0)
|
||||||
|
|
||||||
|
const dataWithPercent = chartData.map((item) => ({
|
||||||
|
...item,
|
||||||
|
percent: Math.round((item.value / total) * 100)
|
||||||
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='bg-white rounded-3xl p-6 shadow-sm h-full'>
|
<div className='bg-white h-fit rounded-3xl p-6 shadow-sm'>
|
||||||
<h3 className='text-base font-medium mb-6'>میزان فروش غذاها</h3>
|
<h3 className='text-base font-medium mb-6'>میزان فروش غذاها</h3>
|
||||||
|
|
||||||
<div className='flex items-center justify-center gap-6'>
|
<div className='flex items-center justify-center mb-6'>
|
||||||
<ResponsiveContainer
|
<ResponsiveContainer
|
||||||
width='60%'
|
width='100%'
|
||||||
height={280}
|
height={280}
|
||||||
>
|
>
|
||||||
<PieChart>
|
<PieChart>
|
||||||
<Pie
|
<Pie
|
||||||
data={chartData}
|
data={dataWithPercent}
|
||||||
cx='50%'
|
cx='50%'
|
||||||
cy='50%'
|
cy='50%'
|
||||||
innerRadius={70}
|
innerRadius={70}
|
||||||
@@ -36,38 +41,74 @@ const FoodSalesChart: FC<FoodSalesChartProps> = ({ data }) => {
|
|||||||
paddingAngle={3}
|
paddingAngle={3}
|
||||||
dataKey='value'
|
dataKey='value'
|
||||||
>
|
>
|
||||||
{chartData.map((entry, index) => (
|
{dataWithPercent.map((entry, index) => (
|
||||||
<Cell
|
<Cell
|
||||||
key={`cell-${index}`}
|
key={`cell-${index}`}
|
||||||
fill={entry.color}
|
fill={entry.color}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
<LabelList
|
||||||
|
dataKey='percent'
|
||||||
|
position='outside'
|
||||||
|
content={(props: unknown) => {
|
||||||
|
const labelProps = props as {
|
||||||
|
x?: number | string
|
||||||
|
y?: number | string
|
||||||
|
value?: number | string
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
labelProps.x === undefined ||
|
||||||
|
labelProps.y === undefined ||
|
||||||
|
labelProps.value === undefined
|
||||||
|
) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const x =
|
||||||
|
typeof labelProps.x === 'number'
|
||||||
|
? labelProps.x
|
||||||
|
: parseFloat(
|
||||||
|
String(labelProps.x)
|
||||||
|
) || 0
|
||||||
|
const y =
|
||||||
|
typeof labelProps.y === 'number'
|
||||||
|
? labelProps.y
|
||||||
|
: parseFloat(
|
||||||
|
String(labelProps.y)
|
||||||
|
) || 0
|
||||||
|
return (
|
||||||
|
<text
|
||||||
|
x={x}
|
||||||
|
y={y}
|
||||||
|
textAnchor='middle'
|
||||||
|
fontSize='14'
|
||||||
|
fontWeight={500}
|
||||||
|
fill='#1F2937'
|
||||||
|
>
|
||||||
|
{labelProps.value}%
|
||||||
|
</text>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Pie>
|
</Pie>
|
||||||
</PieChart>
|
</PieChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='flex flex-col gap-4'>
|
<div className='flex items-center justify-center gap-6 flex-wrap'>
|
||||||
{chartData.map((item, index) => {
|
{dataWithPercent.map((item, index) => (
|
||||||
const percent = Math.round((item.value / total) * 100)
|
<div
|
||||||
return (
|
key={index}
|
||||||
<div
|
className='flex items-center gap-2'
|
||||||
key={index}
|
>
|
||||||
className='flex items-center gap-3'
|
<div
|
||||||
>
|
className='w-3 h-3 rounded-full flex-shrink-0'
|
||||||
<div
|
style={{ backgroundColor: item.color }}
|
||||||
className='w-3 h-3 rounded-full flex-shrink-0'
|
/>
|
||||||
style={{ backgroundColor: item.color }}
|
<span className='text-sm text-gray-700'>
|
||||||
/>
|
{item.name}
|
||||||
<span className='text-sm text-gray-700 min-w-[80px]'>
|
</span>
|
||||||
{item.name}
|
</div>
|
||||||
</span>
|
))}
|
||||||
<span className='text-sm font-medium text-gray-900'>
|
|
||||||
{percent}%
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user