From 72a2c86012819b46c436c9a1f96125c126606a28 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Tue, 27 Sep 2022 18:11:31 -0400 Subject: [PATCH] state election map --- web/components/usa-map/state-election-map.tsx | 63 +++++++++++++++++++ web/components/usa-map/usa-map.tsx | 3 +- web/components/usa-map/usa-state.tsx | 11 ++-- 3 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 web/components/usa-map/state-election-map.tsx diff --git a/web/components/usa-map/state-election-map.tsx b/web/components/usa-map/state-election-map.tsx new file mode 100644 index 00000000..6bbe26c7 --- /dev/null +++ b/web/components/usa-map/state-election-map.tsx @@ -0,0 +1,63 @@ +import { zip } from 'lodash' +import Router from 'next/router' +import { useEffect, useState } from 'react' + +import { getProbability } from 'common/calculate' +import { Contract, CPMMBinaryContract } from 'common/contract' +import { Customize, USAMap } from './usa-map' +import { getContractFromSlug } from 'web/lib/firebase/contracts' + +export interface StateElectionMarket { + creatorUsername: string + slug: string + isWinRepublican: boolean + state: string +} + +export function StateElectionMap(props: { markets: StateElectionMarket[] }) { + const { markets } = props + + const contracts = useContracts(markets.map((m) => m.slug)) + const probs = contracts.map((c) => + c ? getProbability(c as CPMMBinaryContract) : 0.5 + ) + const marketsWithProbs = zip(markets, probs) as [ + StateElectionMarket, + number + ][] + + const stateInfo = marketsWithProbs.map(([market, prob]) => [ + market.state, + { + fill: probToColor(prob, market.isWinRepublican), + clickHandler: () => + Router.push(`/${market.creatorUsername}/${market.slug}`), + }, + ]) + + const config = Object.fromEntries(stateInfo) as Customize + + return +} + +const probToColor = (prob: number, isWinRepublican: boolean) => { + const p = isWinRepublican ? prob : 1 - prob + const hue = p > 0.5 ? 350 : 240 + const saturation = 100 + const lightness = 100 - 50 * Math.abs(p - 0.5) + return `hsl(${hue}, ${saturation}%, ${lightness}%)` +} + +const useContracts = (slugs: string[]) => { + const [contracts, setContracts] = useState<(Contract | undefined)[]>( + slugs.map(() => undefined) + ) + + useEffect(() => { + Promise.all(slugs.map((slug) => getContractFromSlug(slug))).then( + (contracts) => setContracts(contracts) + ) + }, [slugs]) + + return contracts +} diff --git a/web/components/usa-map/usa-map.tsx b/web/components/usa-map/usa-map.tsx index 64a4dfaa..0e07c2ac 100644 --- a/web/components/usa-map/usa-map.tsx +++ b/web/components/usa-map/usa-map.tsx @@ -64,8 +64,7 @@ export const USAMap = ({ const stateClickHandler = (state: string) => customize?.[state]?.clickHandler - ? (customize[state].clickHandler as ClickHandler) - : onClick + return ( - - {stateName} - + {stateName} {hideStateTitle ? null : {stateName}}