diff --git a/src/app/src/components/AnimatedMap.tsx b/src/app/src/components/AnimatedMap.tsx index 53a87ef..652355f 100644 --- a/src/app/src/components/AnimatedMap.tsx +++ b/src/app/src/components/AnimatedMap.tsx @@ -3,13 +3,11 @@ import { useMap } from 'react-leaflet'; import { Heading, Spacer, - HStack, - Slider, Box, - SliderTrack, - SliderFilledTrack, - SliderThumb, - SliderMark, + IconButton, + Progress, + Tag, + TagLabel, } from '@chakra-ui/react'; import L from 'leaflet'; @@ -17,12 +15,14 @@ import UsaMapContainer from './UsaMapContainer'; import { StateGeometry, StateProperties } from './states.geojson'; import StatesLayer from './StatesLayer'; +import TimeControlIcon from './TimeControlIcon'; import { MonthlySpendingOverTimeResponse, SpendingByGeographyAtMonth, } from '../types/api'; import { spendingDataByMonth } from './dummySpendingDataByMonth'; +import AnimatedMapLegend from './AnimatedMapLegend'; export default function AnimatedMap() { return ( @@ -31,32 +31,10 @@ export default function AnimatedMap() { Allocation of announced award funding over time + - - - - ≥1% BIL - - - ≥2% BIL - - ); } @@ -66,11 +44,14 @@ function StatesAndSliderLayer({ }: { spending: MonthlySpendingOverTimeResponse; }) { - const SLIDER_PRESENT_STEP = 26; + const PROGRESS_FINAL_MONTH = 26; const map = useMap(); + const [timeValue, setTimeValue] = useState(0); const [spendingAtTimeByState, setSpendingAtTimeByState] = useState(() => getSpendingByStateAtTime(1, spending) ); + const [animationEnabled, setAnimationEnabled] = useState(false); + const [restartTimeControl, setRestartTimeControl] = useState(false); useEffect(() => { map && @@ -95,8 +76,33 @@ function StatesAndSliderLayer({ }); }, [map, spendingAtTimeByState]); - function onSliderChange(timeValue: number) { - setSpendingAtTimeByState(getSpendingByStateAtTime(timeValue, spending)); + useEffect(() => { + (timeValue % 1 === 0) && spending && setSpendingAtTimeByState(getSpendingByStateAtTime(timeValue, spending)); + if(timeValue === PROGRESS_FINAL_MONTH){ + setAnimationEnabled(false); + setRestartTimeControl(true); + } + }, [timeValue, spending]) + + useEffect(() => { + if(animationEnabled){ + const monthlyInterval = setInterval(() => { + setTimeValue(currentTimeValue => Math.round((currentTimeValue + 0.1)*10)/10); + }, + 25 + ); + return () => { + clearInterval(monthlyInterval); + }; + } + }, [animationEnabled]); + + function onSelectTimeAnimation(){ + if(restartTimeControl){ + setTimeValue(0); + setRestartTimeControl(false); + } + setAnimationEnabled(true); } return ( @@ -118,34 +124,26 @@ function StatesAndSliderLayer({ }); }} /> - onSliderChange(val)} - step={1} - mt='575px' - width='50%' - ml='20%' - > - - - 2021 - - - present - - - - - + + } mr='25px' background='none' onClick={onSelectTimeAnimation} isDisabled={animationEnabled} /> + + 2021 + + Now + + ); } diff --git a/src/app/src/components/AnimatedMapLegend.tsx b/src/app/src/components/AnimatedMapLegend.tsx new file mode 100644 index 0000000..10f57fc --- /dev/null +++ b/src/app/src/components/AnimatedMapLegend.tsx @@ -0,0 +1,29 @@ +import { HStack, Box } from '@chakra-ui/react'; + +export function ColorRangeBox({ bg, text }: { bg: string, text?: String }) { + return ( + + {text} + + ); +} + +export default function AnimatedMapLegend() { + return ( + + + + + + + + ); +} diff --git a/src/app/src/components/TimeControlIcon.tsx b/src/app/src/components/TimeControlIcon.tsx new file mode 100644 index 0000000..90a2475 --- /dev/null +++ b/src/app/src/components/TimeControlIcon.tsx @@ -0,0 +1,21 @@ +import { Icon } from '@chakra-ui/react'; + +export default function TimeControlIcon({ restart }: { restart: boolean }) { + return restart ? ( + + + + ) : ( + + + + ); +} diff --git a/src/app/src/theme.ts b/src/app/src/theme.ts index 3e63d1d..5faafee 100644 --- a/src/app/src/theme.ts +++ b/src/app/src/theme.ts @@ -24,7 +24,10 @@ const theme = extendTheme({ }, colors: { tooltip: { - 500: '#465EB5', + 500: '#465EB5', + }, + progress: { + 500: '#000000', }, }, });