// SVG Sparkline / Line Chart export function renderSparkline( points: Array, color: string, width: number, height: number, ): string { if (!points || points.length < 2) return ""; let maxVal = 0; let minVal = Infinity; for (const p of points) { const v = typeof p === "object" ? p.value || 0 : p; if (v > maxVal) maxVal = v; if (v < minVal) minVal = v; } const range = maxVal - minVal || 1; const padding = 2; const w = width - padding * 2; const h = height - padding * 2; const pathParts: string[] = []; for (let i = 0; i < points.length; i++) { const v = typeof points[i] === "object" ? (points[i] as { value: number }).value || 0 : (points[i] as number); const x = padding + (i / (points.length - 1)) * w; const y = padding + h - ((v - minVal) / range) * h; pathParts.push((i === 0 ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1)); } return ( `` + `` ); } export function renderSVGLineChart( points: Array>, valueKey: string, color: string, width: number, height: number, ): string { if (!points || points.length < 2) return '

Not enough data

'; let maxVal = 0; for (const p of points) { const v = p[valueKey] ?? p.value ?? 0; if (v > maxVal) maxVal = v; } if (maxVal === 0) maxVal = 1; const padding = 20; const chartW = width - padding * 2; const chartH = height - padding * 2; let svg = ``; for (let g = 0; g <= 4; g++) { const gy = padding + (g / 4) * chartH; svg += ``; } const pathParts: string[] = []; for (let i = 0; i < points.length; i++) { const v = points[i][valueKey] ?? points[i].value ?? 0; const x = padding + (i / (points.length - 1)) * chartW; const y = padding + chartH - (v / maxVal) * chartH; pathParts.push((i === 0 ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1)); } const lastX = padding + chartW; const firstX = padding; svg += ``; svg += ``; svg += ""; return svg; }