import {useEffect, useLayoutEffect, useRef, useState} from 'react'; import {GradeResultInterface, MeritProfileInterface} from '@services/type'; import {getMajorityGrade} from '@services/majorityJudgment'; interface ParamsInterface { numVotes: number; outgaugeThreshold: number; } interface GradeBarInterface { grade: GradeResultInterface; size: number; index: number; params: ParamsInterface; } const GradeBar = ({index, grade, size, params}: GradeBarInterface) => { const width = `${size * 100}%`; const textWidth = Math.floor(100 * size); const left = `${(size * 100) / 2}%`; const top = index % 2 ? '20px' : '-20px'; if (size < 0.001) { return null; } return (
{/* size < params.outgaugeThreshold ? ( {textWidth}% ) : ( {Math.floor(100 * size)}% ) */}
); }; const DashedMedian = () => { return (
); }; const MajorityGrade = ({grade, left}) => { // const spanRef = useRef(); const spanRef = useRef(); const [width, setWidth] = useState(0); const offsetWidth = spanRef && spanRef.current && spanRef.current.offsetWidth; useEffect(() => { setTimeout(() => { setWidth(spanRef.current.offsetWidth); }, 100); }, [offsetWidth]); return (
{grade.name}
); }; interface MeritProfileBarInterface { profile: MeritProfileInterface; grades: Array; } const MeritProfileBar = ({profile, grades}: MeritProfileBarInterface) => { const gradesByValue: {[key: number]: GradeResultInterface} = {}; grades.forEach((g) => (gradesByValue[g.value] = g)); const numVotes = Object.values(profile).reduce((a, b) => a + b, 0); const values = grades.map((g) => g.value).sort(); const normalized = {}; values.forEach((v) => (normalized[v] = profile[v] / numVotes || 0)); // low values means great grade // find the majority grade const majorityValue = getMajorityGrade(normalized); const majorityGrade = gradesByValue[majorityValue]; const proponentSizes = values .filter((v) => v > majorityGrade.value) .map((v) => normalized[v]); const proponentWidth = proponentSizes.reduce((a, b) => a + b, 0); const opponentSizes = values .filter((v) => v < majorityGrade.value) .map((v) => normalized[v]); const opponentWidth = opponentSizes.reduce((a, b) => a + b, 0); // is proponent higher than opposant? const proponentMajority = proponentWidth > opponentWidth; // for mobile phone, we outgauge earlier than on desktop const innerWidth = typeof window !== 'undefined' && window.innerWidth ? window.innerWidth : 1000; const params: ParamsInterface = { outgaugeThreshold: innerWidth <= 760 ? 0.05 : 0.03, numVotes, }; return ( <>
{proponentWidth > 1e-5 ? (
{values .filter((v) => v > majorityGrade.value) .map((v) => { const index = values.indexOf(v); const size = proponentWidth < 1e-3 ? 0 : normalized[index] / proponentWidth; return ( ); })}
) : (
)}
{values .filter((v) => v === majorityGrade.value) .map((v) => { const index = values.indexOf(v); return ( ); })}
{opponentWidth > 1e-5 ? (
{values .filter((v) => v < majorityGrade.value) .map((v) => { const index = values.indexOf(v); const size = opponentWidth < 1e-3 ? 0 : normalized[index] / opponentWidth; return ( ); })}
) : (
)}
{/*
*/} ); }; export default MeritProfileBar;