state election map
This commit is contained in:
		
							parent
							
								
									2f25093a51
								
							
						
					
					
						commit
						72a2c86012
					
				
							
								
								
									
										63
									
								
								web/components/usa-map/state-election-map.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								web/components/usa-map/state-election-map.tsx
									
									
									
									
									
										Normal 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 | ||||||
|  | } | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user