51 lines
1.5 KiB
JavaScript
51 lines
1.5 KiB
JavaScript
import { useMemo } from 'react'
|
|
import './PieChart.css'
|
|
|
|
const RADIUS = 10
|
|
const CIRCUMFERENCE = 2 * Math.PI * RADIUS
|
|
|
|
function PieChart({ segments }) {
|
|
const computedSegments = useMemo(() => {
|
|
const total = segments.reduce((acc, seg) => acc + seg.value, 0)
|
|
let currentOffset = 0
|
|
return segments.map(seg => {
|
|
const fraction = seg.value / total
|
|
const segmentLength = fraction * CIRCUMFERENCE
|
|
const offset = currentOffset
|
|
currentOffset += segmentLength
|
|
return { ...seg, segmentLength, offset }
|
|
})
|
|
}, [segments])
|
|
|
|
return (
|
|
<div className="chart-container">
|
|
<svg width="350" height="350" viewBox="0 0 42 42">
|
|
<circle cx="21" cy="21" r={RADIUS} fill="transparent" stroke="var(--color-chart-track)" strokeWidth="20" />
|
|
{computedSegments.map((seg, i) => (
|
|
<circle
|
|
key={i}
|
|
cx="21"
|
|
cy="21"
|
|
r={RADIUS}
|
|
fill="transparent"
|
|
stroke={seg.color}
|
|
strokeWidth="20"
|
|
strokeDasharray={`${seg.segmentLength} ${CIRCUMFERENCE}`}
|
|
strokeDashoffset={-seg.offset}
|
|
/>
|
|
))}
|
|
</svg>
|
|
<div className="legend">
|
|
{segments.map((seg, i) => (
|
|
<div className="legend-item" key={i}>
|
|
<span className="dot" style={{ background: seg.color }} />
|
|
<span>{seg.label}: <strong>{seg.value}</strong></span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default PieChart
|