mirror of
https://github.com/NotAShelf/nix-evaluator-stats.git
synced 2026-04-12 06:17:43 +00:00
initial commit
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I16fd771478019a1b8e716ca4bb9e63b86a6a6964
This commit is contained in:
commit
3bedc467fd
22 changed files with 5172 additions and 0 deletions
94
src/components/MemoryChart.tsx
Normal file
94
src/components/MemoryChart.tsx
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import { Component, For, createMemo } from 'solid-js';
|
||||
import { formatBytes } from '../utils/formatters';
|
||||
|
||||
interface MemoryChartProps {
|
||||
data: Array<{
|
||||
label: string;
|
||||
value: number;
|
||||
total: number;
|
||||
colorClass: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
const MemoryChart: Component<MemoryChartProps> = props => {
|
||||
const chartData = createMemo(() => {
|
||||
const total = props.data.reduce((sum, item) => sum + item.value, 0);
|
||||
if (total === 0) return [];
|
||||
|
||||
let cumulative = 0;
|
||||
return props.data.map(item => {
|
||||
const startAngle = (cumulative / total) * 360;
|
||||
cumulative += item.value;
|
||||
const endAngle = (cumulative / total) * 360;
|
||||
const largeArc = endAngle - startAngle > 180 ? 1 : 0;
|
||||
return {
|
||||
...item,
|
||||
startAngle,
|
||||
endAngle,
|
||||
largeArc,
|
||||
percentage: ((item.value / total) * 100).toFixed(1),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const polarToCartesian = (cx: number, cy: number, r: number, angle: number) => {
|
||||
const rad = ((angle - 90) * Math.PI) / 180;
|
||||
return {
|
||||
x: cx + r * Math.cos(rad),
|
||||
y: cy + r * Math.sin(rad),
|
||||
};
|
||||
};
|
||||
|
||||
const describeArc = (
|
||||
cx: number,
|
||||
cy: number,
|
||||
r: number,
|
||||
startAngle: number,
|
||||
endAngle: number,
|
||||
largeArc: number,
|
||||
) => {
|
||||
const start = polarToCartesian(cx, cy, r, startAngle);
|
||||
const end = polarToCartesian(cx, cy, r, endAngle);
|
||||
return `M ${start.x} ${start.y} A ${r} ${r} 0 ${largeArc} 1 ${end.x} ${end.y}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<div class="memory-chart">
|
||||
<div class="chart-legend">
|
||||
<For each={chartData()}>
|
||||
{item => (
|
||||
<div class="legend-item">
|
||||
<span class="legend-color" classList={{ [item.colorClass]: true }} />
|
||||
<span class="legend-label">{item.label}</span>
|
||||
<span class="legend-value">{formatBytes(item.value)}</span>
|
||||
<span class="legend-percent">{item.percentage}%</span>
|
||||
</div>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
<div class="donut-chart">
|
||||
<svg viewBox="0 0 200 200">
|
||||
<For each={chartData()}>
|
||||
{item => (
|
||||
<path
|
||||
d={describeArc(100, 100, 70, item.startAngle, item.endAngle, item.largeArc)}
|
||||
fill="none"
|
||||
classList={{ [item.colorClass]: true }}
|
||||
stroke-width="35"
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
<circle cx="100" cy="100" r="52" fill="var(--card-bg)" />
|
||||
<text x="100" y="95" text-anchor="middle" class="chart-center-value">
|
||||
{formatBytes(props.data.reduce((sum, d) => sum + d.value, 0))}
|
||||
</text>
|
||||
<text x="100" y="110" text-anchor="middle" class="chart-center-label">
|
||||
Total
|
||||
</text>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MemoryChart;
|
||||
Loading…
Add table
Add a link
Reference in a new issue