state election map

This commit is contained in:
mantikoros 2022-09-27 18:11:31 -04:00
parent 2f25093a51
commit 72a2c86012
3 changed files with 70 additions and 7 deletions

View File

@ -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 <USAMap customize={config} />
}
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
}

View File

@ -64,8 +64,7 @@ export const USAMap = ({
const stateClickHandler = (state: string) => const stateClickHandler = (state: string) =>
customize?.[state]?.clickHandler customize?.[state]?.clickHandler
? (customize[state].clickHandler as ClickHandler)
: onClick
return ( return (
<svg <svg

View File

@ -1,10 +1,11 @@
import clsx from 'clsx'
import { ClickHandler } from './usa-map' import { ClickHandler } from './usa-map'
type USAStateProps = { type USAStateProps = {
state: string state: string
dimensions: string dimensions: string
fill: string fill: string
onClickState: ClickHandler onClickState?: ClickHandler
stateName: string stateName: string
hideStateTitle?: boolean hideStateTitle?: boolean
} }
@ -21,14 +22,14 @@ export const USAState = ({
d={dimensions} d={dimensions}
fill={fill} fill={fill}
data-name={state} data-name={state}
className={`${state} state hover:cursor-pointer hover:contrast-125`} className={clsx(
!!onClickState && 'hover:cursor-pointer hover:contrast-125'
)}
onClick={onClickState} onClick={onClickState}
id={state} id={state}
> >
<text> <text>
<textPath xlinkHref={`#${state}`}> <textPath xlinkHref={`#${state}`}>{stateName}</textPath>
{stateName}
</textPath>
</text> </text>
{hideStateTitle ? null : <title>{stateName}</title>} {hideStateTitle ? null : <title>{stateName}</title>}
</path> </path>