feat: add RaceChart
This commit is contained in:
		
							
								
								
									
										29
									
								
								src/MVPChart.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/MVPChart.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import { useEffect, useState } from "react";
 | 
				
			||||||
 | 
					import { apiAuth } from "./api";
 | 
				
			||||||
 | 
					import BarChart from "./BarChart";
 | 
				
			||||||
 | 
					import { PlayerRanking } from "./types";
 | 
				
			||||||
 | 
					import RaceChart from "./RaceChart";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const MVPChart = () => {
 | 
				
			||||||
 | 
					  const [data, setData] = useState({} as PlayerRanking[]);
 | 
				
			||||||
 | 
					  const [loading, setLoading] = useState(true);
 | 
				
			||||||
 | 
					  const [showStd, setShowStd] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async function loadData() {
 | 
				
			||||||
 | 
					    setLoading(true);
 | 
				
			||||||
 | 
					    await apiAuth("analysis/mvp", null)
 | 
				
			||||||
 | 
					      .then(json => json as Promise<PlayerRanking[]>).then(json => { setData(json.sort((a, b) => a.rank - b.rank)) })
 | 
				
			||||||
 | 
					    setLoading(false);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => { loadData() }, [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      {loading ? <span className="loader" /> : <RaceChart std={showStd} players={data} />
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    </>)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default MVPChart;
 | 
				
			||||||
							
								
								
									
										71
									
								
								src/RaceChart.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/RaceChart.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					import { FC, useEffect, useState } from 'react';
 | 
				
			||||||
 | 
					import { PlayerRanking } from './types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface RaceChartProps {
 | 
				
			||||||
 | 
					  players: PlayerRanking[];
 | 
				
			||||||
 | 
					  std: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const determineNiceWidth = (width: number) => {
 | 
				
			||||||
 | 
					  const max = 1080;
 | 
				
			||||||
 | 
					  if (width >= max)
 | 
				
			||||||
 | 
					    return max
 | 
				
			||||||
 | 
					  else if (width > 768)
 | 
				
			||||||
 | 
					    return width * 0.8
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    return width * 0.96
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const RaceChart: FC<RaceChartProps> = ({ players, std }) => {
 | 
				
			||||||
 | 
					  // State to store window's width and height
 | 
				
			||||||
 | 
					  const [width, setWidth] = useState(determineNiceWidth(window.innerWidth));
 | 
				
			||||||
 | 
					  const [height, setHeight] = useState(window.innerHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Update state on  resize
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    const handleResize = () => {
 | 
				
			||||||
 | 
					      setWidth(determineNiceWidth(window.innerWidth));
 | 
				
			||||||
 | 
					      setHeight(window.innerHeight);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    window.addEventListener('resize', handleResize);
 | 
				
			||||||
 | 
					    return () => {
 | 
				
			||||||
 | 
					      window.removeEventListener('resize', handleResize);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
 | 
					  const padding = 24;
 | 
				
			||||||
 | 
					  const gap = 8
 | 
				
			||||||
 | 
					  const maxValue = Math.max(...players.map((player) => player.rank)) + 1;
 | 
				
			||||||
 | 
					  const barHeight = (height - 2 * padding) / players.length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <svg width={width} height={height}>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {players.map((player, index) => (
 | 
				
			||||||
 | 
					        <rect
 | 
				
			||||||
 | 
					          key={index}
 | 
				
			||||||
 | 
					          x={0}
 | 
				
			||||||
 | 
					          y={index * barHeight + padding}
 | 
				
			||||||
 | 
					          width={(1 - player.rank / maxValue) * width}
 | 
				
			||||||
 | 
					          height={barHeight - gap} // subtract 2 for some spacing between bars
 | 
				
			||||||
 | 
					          fill="#36c"
 | 
				
			||||||
 | 
					        />))}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {players.map((player, index) => (
 | 
				
			||||||
 | 
					        <text
 | 
				
			||||||
 | 
					          key={index}
 | 
				
			||||||
 | 
					          x={4}
 | 
				
			||||||
 | 
					          y={index * barHeight + barHeight / 2 + padding + gap / 2}
 | 
				
			||||||
 | 
					          width={(1 - player.rank / maxValue) * width}
 | 
				
			||||||
 | 
					          height={barHeight - 8} // subtract 2 for some spacing between bars
 | 
				
			||||||
 | 
					          fontSize="24px"
 | 
				
			||||||
 | 
					          fill="aliceblue"
 | 
				
			||||||
 | 
					          stroke='#36c'
 | 
				
			||||||
 | 
					          strokeWidth={0.8}
 | 
				
			||||||
 | 
					          fontWeight={"bold"}
 | 
				
			||||||
 | 
					        >{player.name}</text>
 | 
				
			||||||
 | 
					      ))}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    </svg>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export default RaceChart;
 | 
				
			||||||
		Reference in New Issue
	
	Block a user