Memoized heatmap

This commit is contained in:
Ben Grant 2021-06-01 01:02:48 +10:00
parent 2f23fcfd32
commit decfc2b7e6
3 changed files with 92 additions and 72 deletions

View file

@ -1,4 +1,4 @@
import { useState, useEffect, useRef, Fragment } from 'react'; import { useState, useEffect, useRef, useMemo, Fragment } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import localeData from 'dayjs/plugin/localeData'; import localeData from 'dayjs/plugin/localeData';
@ -65,49 +65,7 @@ const AvailabilityViewer = ({
setTouched(people.length <= 1); setTouched(people.length <= 1);
}, [people]); }, [people]);
return ( const heatmap = useMemo(() => (
<>
<StyledMain>
<Legend
min={Math.min(min, filteredPeople.length)}
max={Math.min(max, filteredPeople.length)}
total={people.filter(p => p.availability.length > 0).length}
onSegmentFocus={count => setFocusCount(count)}
/>
<Center style={{textAlign: 'center'}}>{t('event:group.info1')}</Center>
{people.length > 1 && (
<>
<Center style={{textAlign: 'center'}}>{t('event:group.info2')}</Center>
<People>
{people.map((person, i) =>
<Person
key={i}
filtered={filteredPeople.includes(person.name)}
onClick={() => {
setTempFocus(null);
if (filteredPeople.includes(person.name)) {
if (!touched) {
setTouched(true);
setFilteredPeople([person.name]);
} else {
setFilteredPeople(filteredPeople.filter(n => n !== person.name));
}
} else {
setFilteredPeople([...filteredPeople, person.name]);
}
}}
onMouseOver={() => setTempFocus(person.name)}
onMouseOut={() => setTempFocus(null)}
title={person.created && dayjs.unix(person.created).fromNow()}
>{person.name}</Person>
)}
</People>
</>
)}
</StyledMain>
<Wrapper ref={wrapper}>
<ScrollWrapper>
<Container> <Container>
<TimeLabels> <TimeLabels>
{!!timeLabels.length && timeLabels.map((label, i) => {!!timeLabels.length && timeLabels.map((label, i) =>
@ -178,6 +136,68 @@ const AvailabilityViewer = ({
); );
})} })}
</Container> </Container>
), [
people,
filteredPeople,
tempFocus,
focusCount,
highlight,
locale,
dates,
isSpecificDates,
max,
min,
t,
timeFormat,
timeLabels,
times,
]);
return (
<>
<StyledMain>
<Legend
min={Math.min(min, filteredPeople.length)}
max={Math.min(max, filteredPeople.length)}
total={people.filter(p => p.availability.length > 0).length}
onSegmentFocus={count => setFocusCount(count)}
/>
<Center style={{textAlign: 'center'}}>{t('event:group.info1')}</Center>
{people.length > 1 && (
<>
<Center style={{textAlign: 'center'}}>{t('event:group.info2')}</Center>
<People>
{people.map((person, i) =>
<Person
key={i}
filtered={filteredPeople.includes(person.name)}
onClick={() => {
setTempFocus(null);
if (filteredPeople.includes(person.name)) {
if (!touched) {
setTouched(true);
setFilteredPeople([person.name]);
} else {
setFilteredPeople(filteredPeople.filter(n => n !== person.name));
}
} else {
setFilteredPeople([...filteredPeople, person.name]);
}
}}
onMouseOver={() => setTempFocus(person.name)}
onMouseOut={() => setTempFocus(null)}
title={person.created && dayjs.unix(person.created).fromNow()}
>{person.name}</Person>
)}
</People>
</>
)}
</StyledMain>
<Wrapper ref={wrapper}>
<ScrollWrapper>
{heatmap}
{tooltip && ( {tooltip && (
<Tooltip <Tooltip
x={tooltip.x} x={tooltip.x}

View file

@ -80,7 +80,7 @@ export const Time = styled.div`
border-top: 2px dotted ${props.theme.text}; border-top: 2px dotted ${props.theme.text};
`} `}
${props => props.highlight && props.peopleCount === props.maxPeople ? ` ${props => props.highlight && props.peopleCount === props.maxPeople && props.peopleCount > 0 ? `
background-image: repeating-linear-gradient( background-image: repeating-linear-gradient(
45deg, 45deg,
${props.theme.primary}, ${props.theme.primary},

View file

@ -34,7 +34,7 @@ const Legend = ({
<Grade <Grade
key={i} key={i}
color={`${theme.primary}${Math.round((i/(max))*255).toString(16)}`} color={`${theme.primary}${Math.round((i/(max))*255).toString(16)}`}
highlight={highlight && i === max} highlight={highlight && i === max && max > 0}
onMouseOver={() => onSegmentFocus(i)} onMouseOver={() => onSegmentFocus(i)}
/> />
)} )}