Highly ambitious ATProtocol AppView service and sdks
at fix-postgres 94 lines 2.2 kB view raw
1import { graphql, useFragment } from "react-relay"; 2import type { Sparkline_sparklines$key } from "../__generated__/Sparkline_sparklines.graphql.ts"; 3 4interface SparklineProps { 5 sparklines: Sparkline_sparklines$key; 6 width?: number; 7 height?: number; 8 className?: string; 9} 10 11export function Sparkline({ 12 sparklines, 13 width = 200, 14 height = 40, 15 className = "", 16}: SparklineProps) { 17 const data = useFragment( 18 graphql` 19 fragment Sparkline_sparklines on SparklinePoint @relay(plural: true) { 20 timestamp 21 count 22 } 23 `, 24 sparklines 25 ); 26 27 if (!data || data.length === 0) { 28 return null; 29 } 30 31 // Calculate min/max for scaling 32 const counts = data.map((d) => d.count); 33 const max = Math.max(...counts, 1); 34 const min = Math.min(...counts, 0); 35 const range = max - min || 1; 36 37 // Max height is 75% of the available height 38 const maxHeight = height * 0.75; 39 40 // Generate SVG path 41 const points = data 42 .map((point, index) => { 43 const x = (index / (data.length - 1 || 1)) * width; 44 const y = height - ((point.count - min) / range) * maxHeight; 45 return `${x},${y}`; 46 }) 47 .join(" "); 48 49 // Create area path for gradient fill 50 const areaPath = `M 0,${height} L ${points} L ${width},${height} Z`; 51 52 return ( 53 <svg 54 width={width} 55 height={height} 56 className={className} 57 viewBox={`0 0 ${width} ${height}`} 58 preserveAspectRatio="none" 59 > 60 {/* Gradient definition */} 61 <defs> 62 <linearGradient 63 id="sparklineGradient" 64 x1="0%" 65 y1="0%" 66 x2="0%" 67 y2="100%" 68 > 69 <stop 70 offset="0%" 71 style={{ stopColor: "#22d3ee", stopOpacity: 0.5 }} 72 /> 73 <stop 74 offset="100%" 75 style={{ stopColor: "#22d3ee", stopOpacity: 0.1 }} 76 /> 77 </linearGradient> 78 </defs> 79 80 {/* Area fill */} 81 <path d={areaPath} fill="url(#sparklineGradient)" strokeWidth="0" /> 82 83 {/* Line */} 84 <polyline 85 points={points} 86 fill="none" 87 stroke="#22d3ee" 88 strokeWidth="2" 89 strokeLinecap="round" 90 strokeLinejoin="round" 91 /> 92 </svg> 93 ); 94}