react-spring#useTransition JavaScript Examples
The following examples show how to use
react-spring#useTransition.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: DistrictMap.js From dashboard with MIT License | 6 votes |
function DistrictMap({ filterDistrict, filterFacilityTypes, date }) {
const { data } = useSWR(
["Capacity", date, filterDistrict.id],
(url, date, district) =>
careSummary(
"facility",
dateString(getNDateBefore(date, 1)),
dateString(getNDateAfter(date, 1)),
district
)
);
const todayFiltered = useMemo(() => {
return processFacilities(data.results, filterFacilityTypes).filter(
(f) => f.date === dateString(date)
);
}, []);
const transitions = useTransition(null, {
enter: { opacity: 1 },
from: { opacity: 0 },
leave: { opacity: 0 },
});
return transitions.map(({ item, key, props }) => (
<animated.div key={key} style={props}>
<div id="capacity-map">
<SectionTitle>Map</SectionTitle>
</div>
<Suspense fallback={<ThemedSuspense />}>
<GMap
className="mb-8"
facilities={todayFiltered}
district={filterDistrict}
/>
</Suspense>
</animated.div>
));
}
Example #2
Source File: CheckInList.js From 1km.co.il with MIT License | 6 votes |
function CheckInList({ checkIns }) {
const transitions = useTransition(checkIns, (item) => item?.id, {
config: config.gentle,
from: { opacity: 0, transform: 'translate3d(25%, 0%, 0px)' },
enter: { opacity: 1, transform: 'translate3d(0%, 0px, 0px)' },
leave: { opacity: 0, height: 0, transform: 'translate3d(-25%, 0px, 0px)' },
});
return (
<CheckInListWrapper>
{checkIns?.length > 0 ? (
transitions.map(({ item, props, key }, i) => (
<CheckIn key={key} style={i === 0 ? props : {}}>
<UserAvatar src={item.pictureUrl === '' ? '/anonymousPofile.png' : item.pictureUrl} />
<CheckIn.Info>
<CheckIn.Name>
{item.firstName} {item.lastName}
</CheckIn.Name>
<CheckIn.Location>ב{item.protestCityName || item.protestStreetAddress}</CheckIn.Location>
</CheckIn.Info>
{item.userMessage && <CheckIn.Comment>{item.userMessage}</CheckIn.Comment>}
<CheckIn.TimeAgo>
<TimeAgo datetime={item.createdAt} locale="he" />
</CheckIn.TimeAgo>
</CheckIn>
))
) : (
<div style={{ textAlign: 'center', display: 'flex', flexDirection: 'column' }}>
<span>טוען...</span>
<LoadingSpinner style={{ marginTop: 15 }} />
</div>
)}
</CheckInListWrapper>
);
}
Example #3
Source File: index.js From sorbet-finance with GNU General Public License v3.0 | 6 votes |
export default function Modal({ isOpen, onDismiss, minHeight = false, initialFocusRef, children, maxHeight = 50 }) {
const transitions = useTransition(isOpen, null, {
config: { duration: 150 },
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 },
})
return transitions.map(
({ item, key, props }) =>
item && (
<StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
<StyledDialogContent hidden={true} minHeight={minHeight} maxHeight={maxHeight}>
<HiddenCloseButton onClick={onDismiss} />
{children}
</StyledDialogContent>
</StyledDialogOverlay>
)
)
}
Example #4
Source File: PicutreCardList.js From 1km.co.il with MIT License | 6 votes |
function PictureCardList({ pictures }) {
const transitions = useTransition(pictures, (picture) => picture?.id, {
config: config.gentle,
from: { opacity: 0, transform: 'translate3d(25%, 0%, 0px)' },
enter: { opacity: 1, transform: 'translate3d(0%, 0px, 0px)' },
leave: { opacity: 0, height: 0, transform: 'translate3d(-25%, 0px, 0px)' },
});
return (
<>
{transitions.map(({ item: picture, props, key }) => (
<Card key={key} style={props}>
<Card.Info>
<Link to={`/protest/${picture.protestId}`}>
<Card.Info.Title>
{picture.protestName}
{picture.cityName && `, ${picture.cityName}`}
</Card.Info.Title>
</Link>
{picture.uploaderName && (
<Card.Info.Subtitle>
<Avatar size={21} src={picture.userAvatar || 'https://1km.co.il/anonymousPofile.png'} style={{ marginLeft: 6 }} />
{picture.uploaderName}
</Card.Info.Subtitle>
)}
{picture.description && <Card.Description>{picture.description}</Card.Description>}
<Card.Info.Timestamp>
<TimeAgo datetime={picture.createdAt} locale="he" />
</Card.Info.Timestamp>
</Card.Info>
<Card.Image src={picture.imageUrl} alt="" />
</Card>
))}
</>
);
}
Example #5
Source File: AnimateText.js From Personal-Website with MIT License | 6 votes |
// function AnimateText({text, favourite}) {
//
// const slides = text.map((item,i) => ({text: item, id: i}))
// const [index, set] = useState(0);
// const transitions = useTransition(slides[index], item => item.id, {
// from: { opacity: 0 },
// enter: { opacity: 1 },
// leave: { opacity: 0 },
// config: config.molasses,
// });
// useEffect(() => void setInterval(() => set(state => (state + 1) % slides.length),500), [])
// return transitions.map(({ item, props, key }) => (
// <animated.div
// key={key}
// style={{ ...props}}
// >
//
// </animated.div>
// ))
// }
function AnimateText({text}) {
let [state, setState] = useState(0);
const transition = useTransition(text[state], null, {
from: {opacity: 0},
enter: {opacity: 1},
leave: {opacity: 0},
});
useEffect(() => void setInterval(() => setState(state => (state + 1) % text.length), 1500), [])
return transition.map(({item, key, state, props, phase}) => {
return (phase === "enter") &&
<animated.span style={{...props, textAlign: "center"}} key={key}>{item}</animated.span>
});
}
Example #6
Source File: index.js From pine-interface with GNU General Public License v3.0 | 6 votes |
export default function Modal({ isOpen, onDismiss, minHeight = false, initialFocusRef, children, maxHeight = 50 }) {
const transitions = useTransition(isOpen, null, {
config: { duration: 150 },
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 }
})
return transitions.map(
({ item, key, props }) =>
item && (
<StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
<StyledDialogContent hidden={true} minHeight={minHeight} maxHeight={maxHeight}>
<HiddenCloseButton onClick={onDismiss} />
{children}
</StyledDialogContent>
</StyledDialogOverlay>
)
)
}
Example #7
Source File: ThemeButton.js From umami with MIT License | 6 votes |
export default function ThemeButton() {
const [theme, setTheme] = useTheme();
const transitions = useTransition(theme, {
initial: { opacity: 1 },
from: {
opacity: 0,
transform: `translateY(${theme === 'light' ? '20px' : '-20px'}) scale(0.5)`,
},
enter: { opacity: 1, transform: 'translateY(0px) scale(1)' },
leave: {
opacity: 0,
transform: `translateY(${theme === 'light' ? '-20px' : '20px'}) scale(0.5)`,
},
});
function handleClick() {
setTheme(theme === 'light' ? 'dark' : 'light');
}
return (
<div className={styles.button} onClick={handleClick}>
{transitions((styles, item) => (
<animated.div key={item} style={styles}>
<Icon icon={item === 'light' ? <Sun /> : <Moon />} />
</animated.div>
))}
</div>
);
}
Example #8
Source File: BankSyncStatus.js From actual with MIT License | 5 votes |
function BankSyncStatus({ accountsSyncing }) {
let name = accountsSyncing
? accountsSyncing === '__all'
? 'accounts'
: accountsSyncing
: null;
const transitions = useTransition(name, null, {
from: { opacity: 0, transform: 'translateY(-100px)' },
enter: { opacity: 1, transform: 'translateY(0)' },
leave: { opacity: 0, transform: 'translateY(-100px)' },
unique: true
});
return (
<View
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
marginTop: 5,
alignItems: 'center',
zIndex: 501
}}
>
{transitions.map(
({ item, key, props }) =>
item && (
<animated.div key={key} style={props}>
<View
style={{
borderRadius: 4,
backgroundColor: colors.b9,
color: colors.b1,
padding: '5px 13px',
flexDirection: 'row',
alignItems: 'center',
boxShadow: styles.shadow
}}
>
<AnimatedRefresh
animating={true}
iconStyle={{ color: colors.b1 }}
/>
<Text>Syncing {item}</Text>
</View>
</animated.div>
)
)}
</View>
);
}
Example #9
Source File: OptionsDialog.js From instaclone with Apache License 2.0 | 5 votes |
OptionsDialog = ({
hide,
options,
children,
title,
cancelButton = true,
}) => {
const transitions = useTransition(true, null, {
from: { transform: 'scale(1.2)', opacity: 0.5 },
enter: { transform: 'scale(1)', opacity: 1 },
leave: { opacity: 0 },
config: {
mass: 1,
tension: 500,
friction: 30,
},
});
return transitions.map(({ item, key, props }) => (
<animated.div style={props} key={key} className="options-dialog">
{title && (
<header className="options-dialog__title">
<h1 className="heading-3">{title}</h1>
{!cancelButton && (
<TextButton style={{ fontSize: '3rem' }} onClick={() => hide()}>
✕
</TextButton>
)}
</header>
)}
{children}
{options.map((option, idx) => {
const buttonClassNames = classNames({
'options-dialog__button': true,
'options-dialog__button--warning': option.warning,
[option.className]: option.className,
});
return (
<button
onClick={(event) => {
if (option.hasOwnProperty('onClick')) {
event.stopPropagation();
option.onClick();
hide();
}
}}
className={buttonClassNames}
key={idx}
>
{option.text}
</button>
);
})}
{cancelButton && (
<button
className="options-dialog__button"
onClick={(event) => {
event.nativeEvent.stopImmediatePropagation();
hide();
}}
>
Cancel
</button>
)}
</animated.div>
));
}
Example #10
Source File: Router.jsx From Personal-Website with MIT License | 5 votes |
function Router() {
const location = useLocation();
const classes = useStyle();
const transitions = useTransition(location, location => location.pathname, {
from: {opacity: 0.9, transform: 'translate3d(50%,0,0)'},
enter: {opacity: 1, transform: 'translate3d(0%,0,0)'},
leave: {opacity: 0, transform: 'translate3d(50%,0,0)'},
config: {duration: 800},
});
const transitions2 = useTransition(location, location => location.pathname, {
from: {opacity: 0.9, transform: 'translate3d(-50%,0,0)'},
enter: {opacity: 1, transform: 'translate3d(0%,0,0)'},
leave: {opacity: 0, transform: 'translate3d(50%,0,0)'},
config: {duration: 800},
});
return !location.search ? transitions.map(({item: location, props, key}) => (
<animated.div key={key} style={{...props}} className={classes.root}>
<Switch>
<Route exact path="/" render={(props) => <HomePage {...props} />}/>
<Route exact path="/about" render={(props) => <About {...props}/>}/>
<Route exact path="/experience" render={(props) => <Experience {...props}/>}/>
<Route exact path="/work" render={(props) => <Work {...props}/>}/>
<Route exact path="/journey" render={(props) => <Journey {...props}/>}/>
{/*<Route exact path="/contact" render={(props) => <Contact {...props}/>}/>*/}
</Switch>
</animated.div>
)) : transitions2.map(({item: location, props, key}) => (
<animated.div key={key} style={{...props}} className={classes.root}>
<Switch>
<Route exact path="/" render={(props) => <HomePage {...props} />}/>
<Route exact path="/about" render={(props) => <About {...props}/>}/>
<Route exact path="/experience" render={(props) => <Experience {...props}/>}/>
<Route exact path="/work" render={(props) => <Work {...props}/>}/>
<Route exact path="/journey" render={(props) => <Journey {...props}/>}/>
{/*<Route exact path="/contact" render={(props) => <Contact {...props}/>}/>*/}
{/*<Route path="/" render={(props) => <Contact {...props}/>}/>*/}
</Switch>
</animated.div>
))
}
Example #11
Source File: LanguageSwitcher.js From covid19india-react with MIT License | 5 votes |
function LanguageSwitcher({showLanguageSwitcher, setShowLanguageSwitcher}) {
const {t, i18n} = useTranslation();
const currentLanguage = Object.keys(locales).includes(i18n?.language)
? i18n?.language
: i18n?.options?.fallbackLng[0];
const transitions = useTransition(showLanguageSwitcher, {
from: ENTER_OUT,
enter: ENTER_IN,
leave: ENTER_OUT,
config: {
mass: 1,
tension: 100,
friction: 15,
},
});
const languageSwitcherRef = useRef();
useClickAway(languageSwitcherRef, (e) => {
if (e.target.className !== 'navbar-left') {
setShowLanguageSwitcher(false);
}
});
const switchLanguage = useCallback(
(languageKey) => {
if (i18n) i18n.changeLanguage(languageKey);
},
[i18n]
);
return transitions(
(style, item) =>
item && (
<animated.div
className="LanguageSwitcher"
ref={languageSwitcherRef}
{...{style}}
>
<h3>{t('We speak the following languages')}</h3>
<div className="languages">
{Object.keys(locales).map((languageKey) => (
<div
key={languageKey}
className={classnames('language', {
'is-highlighted': currentLanguage === languageKey,
})}
onClick={switchLanguage.bind(this, languageKey)}
>
<span>{locales[languageKey]}</span>
</div>
))}
</div>
<div
className="close-button"
onClick={setShowLanguageSwitcher.bind(this, false)}
>
<ArrowUpIcon size={16} />
</div>
</animated.div>
)
);
}
Example #12
Source File: SlideIndicator.js From react-instagram-zoom-slider with MIT License | 5 votes |
export default function SlideIndicator({
currentSlide,
inFront,
slideIndicatorTimeout,
totalSlides,
}) {
const [isVisible, setVisible] = useState(true)
useEffect(() => {
if (slideIndicatorTimeout !== null) {
const timer = setTimeout(() => {
setVisible(false)
}, slideIndicatorTimeout)
return () => clearTimeout(timer)
}
}, [])
const transitions = useTransition(isVisible, null, {
from: { opacity: 1 },
enter: { opacity: 1 },
leave: { opacity: 0 },
})
if (totalSlides < 2) {
return null
}
return (
<>
{transitions.map(
({ item, key, props }) =>
item && (
<AnimatedSlideIndicator key={key} inFront={inFront} style={{ ...props }}>
{currentSlide + 1}/{totalSlides}
</AnimatedSlideIndicator>
)
)}
</>
)
}
Example #13
Source File: WithMeList.js From 1km.co.il with MIT License | 5 votes |
function WithMeList({ currentProtest }) {
const [withMeUsers, setWithMeUsers] = useState([]);
const [avatars, setAvatars] = useState([]);
const [loading, setLoading] = useState(true);
const avatarsFadeIn = useTransition(avatars, (avatar) => avatar.id, {
from: { opacity: 0 },
enter: { opacity: 1 },
config: { duration: 350 },
});
useEffect(() => {
if (currentProtest?.id) {
const withMeData = realtimeDB
.ref('24-10-20_check_ins')
.orderByChild('protestId')
.equalTo(currentProtest.id)
.limitToLast(35);
withMeData.on('child_added', (data) => {
const user = data.val();
setWithMeUsers((prevState) => {
return [{ ...user, id: data.key }, ...prevState];
});
if (user.pictureUrl) {
setAvatars((prevState) => {
return [...prevState, { url: user.pictureUrl, id: data.key }];
});
}
});
withMeData.once('value', () => setLoading(false));
}
}, [currentProtest]);
if (!currentProtest) {
return (
<WithMe>
<h2 style={{ textAlign: 'center' }}>עשו צ'ק אין להפגנה בשביל לראות מי מפגין איתכם</h2>
</WithMe>
);
}
if (loading) {
return (
<WithMe style={{ textAlign: 'center' }}>
<p>טוען נתונים...</p>
<LoadingSpinner />
</WithMe>
);
}
return (
<WithMe>
<WithMe.ProtestInfo>
<WithMe.ProtestInfo.Title>{currentProtest.displayName}</WithMe.ProtestInfo.Title>
<WithMe.ProtestInfo.Counter>{withMeUsers.length} מפגינות ומפגינים באתר</WithMe.ProtestInfo.Counter>
</WithMe.ProtestInfo>
<WithMe.Avatars>
{avatarsFadeIn.map(({ item, props, key }) => (
<UserAvatar style={props} src={item.url} key={key} />
))}
</WithMe.Avatars>
</WithMe>
);
}
Example #14
Source File: PulsatingIcon.js From instaclone with Apache License 2.0 | 5 votes |
PulsatingIcon = ({
toggle,
constantProps = {},
toggledProps,
elementRef
}) => {
const transitions = useTransition(toggle, null, {
from: { transform: 'scale(1.3)' },
enter: { transform: 'scale(1)' },
leave: { display: 'none' },
config: {
mass: 1,
tension: 500,
friction: 20
},
// Prevent animating on initial render
immediate: !elementRef.current
});
return (
<Fragment>
{transitions.map(({ item, key, props }) =>
item ? (
<Icon
{...constantProps}
{...toggledProps[0]}
style={props}
key={key}
/>
) : (
<Icon
{...constantProps}
{...toggledProps[1]}
style={props}
key={key}
/>
)
)}
</Fragment>
);
}
Example #15
Source File: SideDrawer.js From NeuVision-Gatsby-Template with BSD Zero Clause License | 5 votes |
SideDrawer = props => {
const handleClick = () => {
props.toggleMenu()
}
const transitions = useTransition(props.showMenu, null, {
from: { transform: "translateX(-100%)" },
enter: { transform: "translateX(0%)" },
leave: { transform: "translateX(-100%)" },
})
return (
<>
{transitions.map(({ item, key, props }) =>
item ? (
<SideDrawerWrap key={key} style={props}>
<CloseIcon onClick={handleClick}>
<Icon
name="close"
height="40px"
width="40px"
stroke="var(--text)"
fill="var(--text)"
viewBox="0 0 100 125"
/>
</CloseIcon>
<Logo>
<Link to="/" title={"NeuVision"}>
<h3>NeuVision</h3>
</Link>
</Logo>
<Ul>
<Li>
<ClickLink onClick={handleClick} to={`/`} title="Home">
Home
</ClickLink>
</Li>
{links.map((link, index) => (
<Li key={index}>
<ClickLink
onClick={handleClick}
to={`/${link.path}`}
title={link.title}
>
{link.title}
</ClickLink>
</Li>
))}
</Ul>
</SideDrawerWrap>
) : null
)}
</>
)
}
Example #16
Source File: Table.js From covid19india-react with MIT License | 4 votes |
function Table({
data: states,
date: timelineDate,
regionHighlighted,
setRegionHighlighted,
expandTable,
setExpandTable,
hideDistrictData,
hideDistrictTestData,
hideVaccinated,
lastDataDate,
noDistrictDataStates,
}) {
const {t} = useTranslation();
const [sortData, setSortData] = useSessionStorage('sortData', {
sortColumn: 'confirmed',
isAscending: false,
delta: false,
});
const [page, setPage] = useState(0);
const [delta7Mode, setDelta7Mode] = useState(false);
const [tableContainerRef, {width: tableWidth}] = useMeasure();
const handleSortClick = useCallback(
(statistic) => {
if (sortData.sortColumn !== statistic) {
setSortData(
produce(sortData, (draftSortData) => {
if (
sortData.sortColumn === 'regionName' ||
statistic === 'regionName'
) {
draftSortData.isAscending = !sortData.isAscending;
}
draftSortData.sortColumn = statistic;
})
);
} else {
setSortData(
produce(sortData, (draftSortData) => {
draftSortData.isAscending = !sortData.isAscending;
})
);
}
},
[sortData, setSortData]
);
const trail = useTrail(5, {
from: {transform: 'translate3d(0, 10px, 0)', opacity: 0},
to: {transform: 'translate3d(0, 0px, 0)', opacity: 1},
config: config.wobbly,
});
const [allDistricts, setAllDistricts] = useState();
const [tableOption, setTableOption] = useState('States');
const [isPerLakh, setIsPerLakh] = useState(false);
const [isInfoVisible, setIsInfoVisible] = useState(false);
const getTableStatistic = useCallback(
(data, statistic, type) => {
const statisticConfig = STATISTIC_CONFIGS[statistic];
if (type == 'total' && statisticConfig?.onlyDelta7) {
type = 'delta7';
}
if (statisticConfig?.showDelta && type === 'total' && delta7Mode) {
type = 'delta7';
}
return getStatistic(data, type, statistic, {
expiredDate: lastDataDate,
normalizedByPopulationPer: isPerLakh ? 'lakh' : null,
});
},
[isPerLakh, lastDataDate, delta7Mode]
);
const districts = useMemo(() => {
if (!isPerLakh) {
return allDistricts;
} else {
return Object.keys(allDistricts || {})
.filter(
(districtKey) =>
getStatistic(allDistricts[districtKey], 'total', 'population') > 0
)
.reduce((res, districtKey) => {
res[districtKey] = allDistricts[districtKey];
return res;
}, {});
}
}, [isPerLakh, allDistricts]);
const numPages = Math.ceil(
Object.keys(districts || {}).length / DISTRICT_TABLE_COUNT
);
const sortingFunction = useCallback(
(regionKeyA, regionKeyB) => {
if (sortData.sortColumn !== 'regionName') {
const statisticConfig = STATISTIC_CONFIGS[sortData.sortColumn];
const dataType =
sortData.delta && statisticConfig?.showDelta ? 'delta' : 'total';
const statisticA = getTableStatistic(
districts?.[regionKeyA] || states[regionKeyA],
sortData.sortColumn,
dataType
);
const statisticB = getTableStatistic(
districts?.[regionKeyB] || states[regionKeyB],
sortData.sortColumn,
dataType
);
return sortData.isAscending
? statisticA - statisticB
: statisticB - statisticA;
} else {
const regionNameA =
districts?.[regionKeyA]?.districtName || STATE_NAMES[regionKeyA];
const regionNameB =
districts?.[regionKeyB]?.districtName || STATE_NAMES[regionKeyB];
return sortData.isAscending
? regionNameA.localeCompare(regionNameB)
: regionNameB.localeCompare(regionNameA);
}
},
[
districts,
getTableStatistic,
sortData.delta,
sortData.isAscending,
sortData.sortColumn,
states,
]
);
const _setTableOption = useCallback(() => {
setTableOption((prevTableOption) =>
prevTableOption === 'States' ? 'Districts' : 'States'
);
}, []);
useEffect(() => {
const workerInstance = worker();
workerInstance.getDistricts(states);
workerInstance.addEventListener('message', (message) => {
if (message.data.type !== 'RPC') {
setAllDistricts(message.data);
workerInstance.terminate();
}
});
}, [tableOption, states]);
useEffect(() => {
setPage((p) => Math.max(0, Math.min(p, numPages - 1)));
}, [numPages]);
const handlePageClick = (direction) => {
if (Math.abs(direction) === 1) {
setPage(Math.min(Math.max(0, page + direction), numPages - 1));
} else if (direction < 0) {
setPage(0);
} else if (direction > 0) {
setPage(numPages - 1);
}
};
const transition = useTransition(isInfoVisible, {
from: TABLE_FADE_OUT,
enter: TABLE_FADE_IN,
leave: TABLE_FADE_OUT,
});
const tableStatistics = (
expandTable ? TABLE_STATISTICS_EXPANDED : TABLE_STATISTICS
).filter(
(statistic) =>
(tableOption === 'States' ||
STATISTIC_CONFIGS[statistic]?.category !== 'tested' ||
!hideDistrictTestData) &&
(STATISTIC_CONFIGS[statistic]?.category !== 'vaccinated' ||
!hideVaccinated)
);
const showDistricts = tableOption === 'Districts' && !hideDistrictData;
useEffect(() => {
if (!showDistricts) {
setPage(0);
}
}, [showDistricts]);
useKeyPressEvent('?', () => {
setIsInfoVisible(!isInfoVisible);
});
return (
<div className="Table">
<div className="table-top">
<div className="table-top-left">
<Tooltip message={'Toggle between states/districts'} hold>
<animated.div
className={classnames('toggle', 'option-toggle', {
'is-highlighted': showDistricts,
disabled: hideDistrictData,
})}
onClick={_setTableOption}
style={trail[0]}
>
<DistrictIcon />
</animated.div>
</Tooltip>
<Tooltip message={'Per lakh people'} hold>
<animated.div
className={classnames('toggle', 'lakh-toggle', {
'is-highlighted': isPerLakh,
})}
onClick={setIsPerLakh.bind(this, !isPerLakh)}
style={trail[1]}
>
<PerLakhIcon />
</animated.div>
</Tooltip>
<Tooltip message={'Last 7 day values'} hold>
<animated.div
className={classnames('toggle', 'delta-toggle', {
'is-highlighted': delta7Mode,
})}
style={trail[2]}
onClick={setDelta7Mode.bind(this, !delta7Mode)}
>
<Delta7Icon />
</animated.div>
</Tooltip>
<animated.div
className={classnames('toggle', 'info-toggle', {
'is-highlighted': isInfoVisible,
})}
onClick={setIsInfoVisible.bind(this, !isInfoVisible)}
style={trail[3]}
>
<QuestionIcon size={14} />
</animated.div>
</div>
<Tooltip message={`${expandTable ? 'Collapse' : 'Expand'} table`} hold>
<animated.div
className={classnames('toggle', 'expand-table-toggle', {
'is-highlighted': expandTable,
})}
style={trail[4]}
onClick={setExpandTable.bind(this, !expandTable)}
>
<FoldDownIcon size={16} />
</animated.div>
</Tooltip>
</div>
{transition(
(style, item) =>
item && (
<animated.div className="table-helper" {...{style}}>
<div className="helper-top">
<div className="helper-left">
<div className="info-item">
<div>
<OrganizationIcon size={14} />
</div>
<p>{t('Toggle between States/Districts')}</p>
</div>
<div className="info-item">
<div>
<PeopleIcon size={16} />
</div>
<p>{t('Per Lakh People')}</p>
</div>
<div className="info-item">
<div>
<PulseIcon size={16} />
</div>
<p>{t('Last 7 day values')}</p>
</div>
<div className="info-item sort">
<div>
<SortDescIcon size={14} />
</div>
<p>{t('Sorted by Descending')}</p>
</div>
<div className="info-item sort">
<div>
<SortAscIcon size={14} />
</div>
<p>{t('Sorted by Ascending')}</p>
</div>
<div className="info-item sort">
<TableDeltaHelper />
</div>
<div className="info-item notes">
<div>
<InfoIcon size={15} />
</div>
<p>{t('Notes')}</p>
</div>
</div>
<div className="helper-right">
<div className="info-item">
<p>{t('Units')}</p>
</div>
{Object.entries({'1K': 3, '1L': 5, '1Cr': 7}).map(
([abbr, exp]) => (
<div className="info-item abbr" key={abbr}>
<h5>{abbr}</h5>
<p>
10
<sup>{exp}</sup>
</p>
</div>
)
)}
</div>
</div>
<h5 className="text">
{t('Compiled from State Govt. numbers')},{' '}
<Link to="/about">{t('know more')}!</Link>
</h5>
</animated.div>
)
)}
<div className="table-container" ref={tableContainerRef}>
<div
className="table fadeInUp"
style={{
gridTemplateColumns: `repeat(${tableStatistics.length + 1}, auto)`,
}}
>
<div className="row heading">
<div
className="cell heading"
onClick={handleSortClick.bind(this, 'regionName')}
>
<div>{t(!showDistricts ? 'State/UT' : 'District')}</div>
{sortData.sortColumn === 'regionName' && (
<div className={'sort-icon'}>
{sortData.isAscending ? (
<SortAscIcon size={12} />
) : (
<SortDescIcon size={12} />
)}
</div>
)}
</div>
{tableStatistics.map((statistic) => (
<HeaderCell
key={statistic}
{...{
statistic,
sortData,
setSortData,
}}
handleSort={handleSortClick.bind(this, statistic)}
/>
))}
</div>
{!showDistricts &&
Object.keys(states)
.filter(
(stateCode) =>
stateCode !== 'TT' &&
!(stateCode === UNASSIGNED_STATE_CODE && isPerLakh)
)
.sort((a, b) => sortingFunction(a, b))
.map((stateCode) => {
return (
<Row
key={stateCode}
data={states[stateCode]}
noDistrictData={noDistrictDataStates[stateCode]}
{...{
stateCode,
regionHighlighted,
setRegionHighlighted,
expandTable,
tableStatistics,
getTableStatistic,
tableWidth,
}}
/>
);
})}
{showDistricts && !districts && <TableLoader />}
{showDistricts &&
districts &&
Object.keys(districts)
.sort((a, b) => sortingFunction(a, b))
.slice(
page * DISTRICT_TABLE_COUNT,
(page + 1) * DISTRICT_TABLE_COUNT
)
.map((districtKey) => {
const noDistrictData =
noDistrictDataStates[districts[districtKey].stateCode];
return (
<Row
key={districtKey}
data={districts[districtKey]}
districtName={districts[districtKey].districtName}
{...{
regionHighlighted,
setRegionHighlighted,
expandTable,
tableStatistics,
getTableStatistic,
noDistrictData,
}}
/>
);
})}
<Row
key={'TT'}
data={states['TT']}
stateCode={'TT'}
{...{
regionHighlighted,
setRegionHighlighted,
expandTable,
tableStatistics,
getTableStatistic,
}}
/>
</div>
</div>
{showDistricts && (
<div className="paginate">
<div
className={classnames('left', {disabled: page === 0})}
onClick={handlePageClick.bind(this, -2)}
>
<ChevronsLeft size={16} />
</div>
<div
className={classnames('left', {disabled: page === 0})}
onClick={handlePageClick.bind(this, -1)}
>
<ChevronLeft size={16} />
</div>
<h5>{`${page + 1} / ${numPages}`}</h5>
<div
className={classnames('right', {disabled: page === numPages - 1})}
onClick={handlePageClick.bind(this, 1)}
>
<ChevronRight size={16} />
</div>
<div
className={classnames('right', {disabled: page === numPages - 1})}
onClick={handlePageClick.bind(this, 2)}
>
<ChevronsRight size={16} />
</div>
</div>
)}
</div>
);
}
Example #17
Source File: mobile-menu.js From phirannodesigns-coding-challenge with MIT License | 4 votes |
export function MobileMenu({ isOpen, setIsOpen }) {
const AnimatedDialogOverlay = animated(DialogOverlay);
const AnimatedDialogContent = animated(DialogContent);
const transitions = useTransition(isOpen, null, {
from: { opacity: 0, x: 100 },
enter: { opacity: 1, x: 0 },
leave: { opacity: 0, x: 100 },
});
// Reach Dialog is supposed to handle closing the using the 'Escape' key but it doesn't seem to work so we're doing it ourselves
const handleEscape = (e) => {
if (typeof document !== 'undefined') {
if (e.key === 'Escape') {
setIsOpen(false);
}
}
};
if (typeof document !== 'undefined') {
document.addEventListener('keydown', handleEscape);
}
return transitions.map(
({ item, key, props: styles }) =>
item && (
<AnimatedDialogOverlay
key={key}
onClick={() => setIsOpen(false)}
style={{ opacity: styles.opacity }}
className="fixed absolute inset-0 z-40 md:hidden"
>
<div className="fixed inset-0 z-40 flex justify-end bg-gray-600 bg-opacity-75">
<AnimatedDialogContent
aria-label="Sidebar"
style={{
transform: styles.x.interpolate(
(value) => `translate3d(${value}%, 0, 0)`
),
}}
className="relative flex flex-col flex-1 w-full max-w-xs py-4 bg-teal-800 focus:outline-none"
>
<div className="flex-shrink-0 w-14">
{/* Dummy element to force sidebar to shrink to fit close icon */}
</div>
<div className="absolute top-0 left-0 p-1 -ml-14">
<button
type="button"
onClick={() => setIsOpen(false)}
aria-label="Close sidebar"
className="flex items-center justify-center w-12 h-12 rounded-full focus:outline-none focus:bg-gray-600"
>
<svg
className="w-6 h-6 text-white"
stroke="currentColor"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<div className="flex items-center flex-shrink-0 px-4">
<Logo className="w-auto h-10 text-teal-300 fill-current" />
</div>
<div className="flex-1 h-0 mt-5 overflow-y-auto">
<nav className="px-2">
{mainNavigation.map((node) => (
<Link
key={node.id}
to={node.slug}
className="flex items-center px-2 py-2 mt-1 text-base font-medium leading-6 text-teal-300 transition duration-150 ease-in-out rounded-md group hover:text-white hover:bg-teal-700 focus:outline-none focus:text-white focus:bg-teal-700"
activeClassName="flex items-center px-2 py-2 text-base font-medium leading-6 text-white transition duration-150 ease-in-out bg-teal-900 rounded-md group focus:outline-none focus:bg-teal-700"
>
<node.icon className="w-6 h-6 mr-4 text-teal-400 transition duration-150 ease-in-out group-hover:text-teal-300 group-focus:text-teal-300" />
{node.label}
</Link>
))}
</nav>
</div>
</AnimatedDialogContent>
</div>
</AnimatedDialogOverlay>
)
);
}
Example #18
Source File: Timeline.js From covid19india-react with MIT License | 4 votes |
function Timeline({date, setDate, dates, isTimelineMode, setIsTimelineMode}) {
const {t} = useTranslation();
const [sliderState, setSliderState] = useState(null);
const [play, setPlay] = useState(false);
const [showCalendar, setShowCalendar] = useState(false);
const timelineRef = useRef();
const timer = useRef();
useClickAway(timelineRef, () => {
setShowCalendar(false);
});
const [sliderRef, slider] = useKeenSlider({
initial: date === '' ? Math.max(0, dates.length - 2) : dates.indexOf(date),
dragSpeed: (val, instance) => {
const width = instance.details().widthOrHeight;
return (
val *
(width /
((width / 2) * Math.tan(slideDegree * (Math.PI / 180))) /
slidesPerView)
);
},
move: (s) => {
setSliderState(s.details());
},
afterChange: (s) => {
const slide = s.details().absoluteSlide;
if (slide === s.details().size - 1) {
ReactDOM.unstable_batchedUpdates(() => {
setIsTimelineMode(false);
setShowCalendar(false);
setDate('');
});
} else {
setDate(dates[slide]);
}
},
mode: 'free-snap',
slides: dates.length,
slidesPerView,
});
const [radius, setRadius] = useState(0);
useEffect(() => {
if (slider) setRadius(slider.details().widthOrHeight);
}, [slider]);
const formatSlideDate = (date) => {
if (date === getIndiaDateISO()) return t('Today');
else if (date === getIndiaDateYesterdayISO()) return t('Yesterday');
return formatDate(date, 'dd MMM y');
};
const slideValues = useMemo(() => {
if (!sliderState) return [];
const values = [];
for (let i = 0; i < sliderState.size; i++) {
const distance = sliderState.positions[i].distance * slidesPerView;
const rotate =
Math.abs(distance) > wheelSize / 2 ? 180 : distance * (360 / wheelSize);
const style = {
transform: `rotateY(${rotate}deg) translateZ(${radius}px)`,
WebkitTransform: `rotateY(${rotate}deg) translateZ(${radius}px)`,
};
const className = i === sliderState.absoluteSlide ? 'current' : '';
const slide = sliderState.absoluteSlide + Math.round(distance);
if (Math.abs(distance) < distanceThreshold)
values.push({className, style, slide});
}
return values;
}, [sliderState, radius]);
useKeyPressEvent('ArrowLeft', () => {
if (slider) slider.prev();
});
useKeyPressEvent('ArrowRight', () => {
if (slider) slider.next();
});
useKeyPressEvent('Escape', () => {
setPlay(false);
if (slider) slider.moveToSlide(sliderState.size - 1);
});
useKeyPressEvent('Enter', () => {
setPlay(!play);
});
const handleClick = (index) => {
if (index === sliderState?.absoluteSlide) {
setShowCalendar(!showCalendar);
} else if (slider) {
slider.moveToSlide(index);
}
};
const timeline = {
'2020-03-25': t('Beginning of Lockdown Phase 1'),
'2020-04-14': t('End of Lockdown Phase 1'),
'2020-04-15': t('Beginning of Lockdown Phase 2'),
'2020-05-03': t('End of Lockdown Phase 2'),
'2020-05-04': t('Beginning of Lockdown Phase 3'),
'2020-05-17': t('End of Lockdown Phase 3'),
'2020-05-18': t('Beginning of Lockdown Phase 4'),
'2020-05-31': t('End of Lockdown Phase 4'),
'2020-06-01': t('Beginning of Lockdown Phase 5'),
'2020-11-20': '?',
};
useEffect(() => {
timer.current = setInterval(() => {
if (play && slider) {
slider.next();
}
}, autoPlayDelay);
return () => {
clearInterval(timer.current);
};
}, [play, slider]);
const handleWheel = (event) => {
if (slider) {
if (event.deltaX > 0) {
slider.next();
} else if (event.deltaX < 0) {
slider.prev();
}
}
};
const transitions = useTransition(showCalendar, {
from: {
pointerEvents: 'none',
paddingTop: 0,
marginBottom: 0,
height: 0,
opacity: 0,
},
enter: {
pointerEvents: 'all',
paddingTop: 36,
marginBottom: 400,
opacity: 1,
},
leave: {
pointerEvents: 'none',
paddingTop: 0,
marginBottom: 0,
height: 0,
opacity: 0,
},
config: {
mass: 1,
tension: 100,
friction: 15,
},
});
return (
<div className={'Timeline'} ref={timelineRef}>
<div className="actions timeline fadeInUp" onWheel={handleWheel}>
<div className={'wheel-buttons'}>
<div
className={'wheel-button left'}
onClick={handleClick.bind(this, 0)}
>
<FastForward />
</div>
<div
className={classnames('wheel-button', {active: play})}
onClick={setPlay.bind(this, !play)}
>
{play ? <Pause /> : <Play />}
</div>
<div
className="wheel-button"
onClick={handleClick.bind(this, dates.length - 1)}
>
<FastForward />
</div>
</div>
<div className={'wheel'} ref={sliderRef}>
<div className="wheel__inner">
<div className="wheel__slides">
{slideValues.map(({className, style, slide}) => (
<div className={`wheel__slide`} style={style} key={slide}>
<h5 {...{className}} onClick={handleClick.bind(this, slide)}>
{formatSlideDate(dates[slide])}
</h5>
<div
className={classnames('calendar-icon', {
show: slide === sliderState?.absoluteSlide,
})}
onClick={setShowCalendar.bind(this, !showCalendar)}
>
{slide !== sliderState.size - 1 && (
<CalendarIcon size={12} />
)}
</div>
</div>
))}
</div>
</div>
{slideValues.map(
({slide}) =>
Object.keys(timeline).includes(dates[slide]) && (
<h5
className={classnames('highlight', {
current: slide === sliderState?.absoluteSlide,
})}
key={slide}
>
{timeline[dates[slide]]}
</h5>
)
)}
</div>
</div>
<Suspense fallback={<div />}>
{transitions(
(style, item) =>
item && (
<animated.div {...{style}}>
<Calendar {...{date, dates, slider}} />
</animated.div>
)
)}
</Suspense>
</div>
);
}
Example #19
Source File: index.js From uniswap-v1-frontend with GNU General Public License v3.0 | 4 votes |
export default function Modal({ isOpen, onDismiss, minHeight = false, maxHeight = 50, initialFocusRef, children }) {
const transitions = useTransition(isOpen, null, {
config: { duration: 200 },
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 }
})
const [{ xy }, set] = useSpring(() => ({ xy: [0, 0] }))
const bind = useGesture({
onDrag: state => {
let velocity = state.velocity
if (velocity < 1) {
velocity = 1
}
if (velocity > 8) {
velocity = 8
}
set({
xy: state.down ? state.movement : [0, 0],
config: { mass: 1, tension: 210, friction: 20 }
})
if (velocity > 3 && state.direction[1] > 0) {
onDismiss()
}
}
})
if (isMobile) {
return transitions.map(
({ item, key, props }) =>
item && (
<StyledDialogOverlay
key={key}
style={props}
onDismiss={onDismiss}
initialFocusRef={initialFocusRef}
mobile={isMobile}
>
<Spring // animation for entrance and exit
from={{
transform: isOpen ? 'translateY(200px)' : 'translateY(100px)'
}}
to={{
transform: isOpen ? 'translateY(0px)' : 'translateY(200px)'
}}
>
{props => (
<animated.div
{...bind()}
style={{ transform: xy.interpolate((x, y) => `translate3d(${0}px,${y > 0 ? y : 0}px,0)`) }}
>
<StyledDialogContent
style={props}
hidden={true}
minHeight={minHeight}
maxHeight={maxHeight}
mobile={isMobile}
>
<HiddenCloseButton onClick={onDismiss} />
{children}
</StyledDialogContent>
</animated.div>
)}
</Spring>
</StyledDialogOverlay>
)
)
} else {
return transitions.map(
({ item, key, props }) =>
item && (
<StyledDialogOverlay
key={key}
style={props}
onDismiss={onDismiss}
initialFocusRef={initialFocusRef}
mobile={isMobile}
>
<StyledDialogContent
hidden={true}
minHeight={minHeight}
maxHeight={maxHeight}
isOpen={isOpen}
mobile={isMobile}
>
<HiddenCloseButton onClick={onDismiss} />
{children}
</StyledDialogContent>
</StyledDialogOverlay>
)
)
}
}
Example #20
Source File: StateDropdown.js From covid19india-react with MIT License | 4 votes |
StateDropdown = ({stateCode, trail}) => {
const [showDropdown, setShowDropdown] = useState(false);
const dropdownRef = useRef();
const history = useHistory();
const {t} = useTranslation();
useClickAway(dropdownRef, () => {
setShowDropdown(false);
});
const transitions = useTransition(showDropdown, {
from: {
opacity: 0,
transform: 'translate3d(0, 2px, 0)',
zIndex: 999,
},
enter: {
opacity: 1,
transform: 'translate3d(0, 0px, 0)',
zIndex: 999,
},
leave: {
opacity: 0,
transform: 'translate3d(0, 2px, 0)',
zIndex: 999,
},
config: {
mass: 1,
tension: 210,
friction: 20,
},
});
const handleClick = useCallback(
(stateCodeItr) => {
setShowDropdown(false);
history.push(`/state/${stateCodeItr}`);
},
[history]
);
return (
<div className="StateDropdown" ref={dropdownRef}>
<animated.h1
className={classnames('state-name', 'fadeInUp', {
expanded: showDropdown,
})}
style={trail}
onClick={setShowDropdown.bind(this, !showDropdown)}
>
{t(STATE_NAMES[stateCode])}
</animated.h1>
{transitions(
(style, item) =>
item && (
<animated.div className="dropdown" {...{style}}>
{Object.keys(MAP_META)
.filter(
(stateCodeItr) =>
stateCodeItr !== 'TT' && stateCodeItr !== stateCode
)
.sort((code1, code2) =>
STATE_NAMES[code1].localeCompare(STATE_NAMES[code2])
)
.map((stateCodeItr) => (
<h1
key={stateCodeItr}
className="item"
onClick={handleClick.bind(this, stateCodeItr)}
>
{t(STATE_NAMES[stateCodeItr])}
</h1>
))}
</animated.div>
)
)}
{showDropdown && <div className="backdrop"></div>}
</div>
);
}
Example #21
Source File: Navbar.js From covid19india-react with MIT License | 4 votes |
function Navbar({pages, showLanguageSwitcher, setShowLanguageSwitcher}) {
const {i18n, t} = useTranslation();
const currentLanguage = Object.keys(locales).includes(i18n?.language)
? i18n?.language
: i18n?.options?.fallbackLng[0];
const [expand, setExpand] = useState(false);
const darkMode = useDarkMode(false);
useLockBodyScroll(expand);
const windowSize = useWindowSize();
usePageLeave(() => setExpand(false));
const navbarTransition = useTransition(true, {
from: {opacity: 0},
enter: {opacity: 1},
});
const expandTransition = useTransition(expand, {
from: windowSize.width < 769 ? SLIDE_IN_MOBILE : SLIDE_IN,
enter: windowSize.width < 769 ? SLIDE_OUT_MOBILE : SLIDE_OUT,
leave: windowSize.width < 769 ? SLIDE_IN_MOBILE : SLIDE_IN,
config: {mass: 1, tension: 210, friction: 26},
});
const handleMouseEnter = useCallback(() => {
if (windowSize.width >= 769) {
setExpand(true);
}
}, [windowSize.width]);
const handleLanguageSwitcher = useCallback(() => {
if (expand) setExpand(false);
setShowLanguageSwitcher(!showLanguageSwitcher);
}, [expand, showLanguageSwitcher, setExpand, setShowLanguageSwitcher]);
return navbarTransition((style, item) => (
<animated.div className="Navbar" {...{style}}>
<div className="navbar-left" onClick={handleLanguageSwitcher}>
{locales[currentLanguage]}
</div>
<div className="navbar-middle">
<Link to="/" onClick={setExpand.bind(this, false)}>
Covid19<span>India</span>
</Link>
</div>
<div
className="navbar-right"
onMouseEnter={handleMouseEnter}
{...(windowSize.width < 769 && {
onClick: setExpand.bind(this, !expand),
})}
>
{windowSize.width < 769 && (
<span>{expand ? t('Close') : t('Menu')}</span>
)}
{windowSize.width >= 769 && (
<>
<Link to="/">
<span>
<Home {...activeNavIcon('/')} />
</span>
</Link>
<Link to="/blog">
<span>
<Book {...activeNavIcon('/blog')} />
</span>
</Link>
<Link to="/volunteers">
<span>
<Users {...activeNavIcon('/volunteers')} />
</span>
</Link>
<Link to="/about">
<span>
<HelpCircle {...activeNavIcon('/about')} />
</span>
</Link>
<span>
<SunMoon {...{darkMode}} />
</span>
</>
)}
</div>
{expandTransition(
(style, item) =>
item && (
<animated.div {...{style}}>
<Expand {...{pages, setExpand, darkMode, windowSize}} />
</animated.div>
)
)}
</animated.div>
));
}
Example #22
Source File: DistrictDashboard.js From dashboard with MIT License | 4 votes |
function DistrictDashboard() {
const todayDate = new Date();
const params = useParams();
const [isOpen, setIsOpen] = useState(false);
const [timeseries, setTimeseries] = useState(false);
const [filterDistrict, setFilterDistrict] = useState(ACTIVATED_DISTRICTS[0]);
const [filterFacilityTypes, setFilterFacilityTypes] =
useState(FACILITY_TYPES);
const [content, setContent] = useState(
CONTENT[params.content?.toUpperCase()] || CONTENT.CAPACITY
);
const [dates, datesOnChange] = useState([
getNDateBefore(todayDate, 14),
todayDate,
]);
const [date, dateOnChange] = useState(todayDate);
const [ref, inView] = useInView({
threshold: 0,
});
const getDistrict = (name) => {
const district = ACTIVATED_DISTRICTS.find(
(district) => district.name.toLowerCase() === name?.toLowerCase()
);
return district === undefined ? ACTIVATED_DISTRICTS[0] : district;
};
useEffect(() => {
setFilterDistrict(getDistrict(params.district));
}, [params.district]);
useEffect(() => {
setContent(CONTENT[params.content?.toUpperCase()] || CONTENT.CAPACITY);
}, [params.content]);
useEffect(() => {
window.history.replaceState(
null,
"Care Dashboard",
`/district/${filterDistrict.name.toLowerCase()}/${Object.entries(CONTENT)
.find((a) => a[1] === content)[0]
.toLowerCase()}`
);
}, [content, filterDistrict]);
const renderContent = () => {
switch (content) {
case CONTENT.CAPACITY:
return !timeseries ? (
<Capacity
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
date={date}
/>
) : (
<CapacityTimeseries
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
dates={dates}
/>
);
case CONTENT.PATIENT:
return !timeseries ? (
<Patient
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
date={date}
/>
) : (
<PatientTimeseries
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
dates={dates}
/>
);
case CONTENT.TESTS:
return !timeseries ? (
<Tests
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
date={date}
/>
) : (
<TestsTimeseries
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
dates={dates}
/>
);
case CONTENT.TRIAGE:
return !timeseries ? (
<Triage
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
date={date}
/>
) : (
<TriageTimeseries
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
dates={dates}
/>
);
case CONTENT.LSG:
return !timeseries ? (
<Lsg filterDistrict={filterDistrict} date={date} />
) : (
<div>Work in Progress</div>
);
case CONTENT.OXYGEN:
return !timeseries ? (
<OxygenMonitor
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
date={date}
/>
) : (
<div>Work in Progress</div>
);
case CONTENT.MAP:
return !timeseries ? (
<DistrictMap
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
date={date}
/>
) : (
<div>Work in Progress</div>
);
default:
return <div />;
}
};
function ConditionalFilter({ floating }) {
return (
<Filter
floating={floating}
timeseries={timeseries}
setTimeseries={setTimeseries}
date={date}
dateOnChange={dateOnChange}
dates={dates}
datesOnChange={datesOnChange}
maxDate={todayDate}
filterFacilityTypes={filterFacilityTypes}
setFilterFacilityTypes={setFilterFacilityTypes}
content={content}
/>
);
}
const transitions = useTransition(content, null, {
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 1 },
});
return (
<div className="overflow-hidden md:overflow-auto">
<PageTitle>District Dashboard</PageTitle>
<div className="flex flex-col items-center justify-between mb-2 px-4 py-2 bg-primary-500 rounded-lg shadow-md md:flex-row">
<p className="text-white font-semibold">{filterDistrict.name}</p>
<div className="md:flex md:space-x-2">
<div className="flex flex-wrap justify-center dark:text-gray-700 dark:bg-gray-900 bg-white rounded-lg space-x-1 space-y-1 md:space-x-0 md:space-y-0">
{Object.keys(CONTENT).map((k, i) => {
let t = "shadow-xs ";
if (i === 0) {
t += "md:rounded-r-none";
} else if (i === Object.keys(CONTENT).length - 1) {
t += "md:rounded-l-none";
} else {
t += "md:rounded-l-none md:rounded-r-none";
}
return (
<Button
layout="link"
onClick={() => setContent(CONTENT[k])}
className={t}
disabled={content === CONTENT[k]}
key={i}
>
<span className="capitalize">{k.toLowerCase()}</span>
</Button>
);
})}
</div>
<div className="relative mt-2 dark:bg-gray-900 bg-white rounded-lg md:mt-0">
<Button
layout="link"
onClick={() => setIsOpen(!isOpen)}
aria-label="Select district"
aria-haspopup="true"
disabled={false}
iconRight={ChevronDown}
className="w-full shadow-xs"
>
{filterDistrict.name}
</Button>
<Dropdown
isOpen={isOpen}
align="right"
onClose={() => setIsOpen(false)}
className="z-40"
>
{ACTIVATED_DISTRICTS.map((d, i) => (
<DropdownItem
key={i}
onClick={() => {
setFilterDistrict(d);
setIsOpen(false);
}}
>
<span>{d.name}</span>
</DropdownItem>
))}
</Dropdown>
</div>
</div>
</div>
<div ref={ref}>
<ConditionalFilter floating={false} />
</div>
{!inView && <ConditionalFilter floating />}
<Suspense fallback={<ThemedSuspense />}>
<SWRConfig
value={{
suspense: true,
loadingTimeout: 10_000,
refreshInterval: 300_000,
onError: (error, key) => {
// eslint-disable-next-line no-console
console.error(error, key);
},
}}
>
{transitions.map(({ key, props }) => (
<animated.div key={key} style={props}>
{renderContent()}
</animated.div>
))}
</SWRConfig>
</Suspense>
</div>
);
}
Example #23
Source File: Capacity.js From dashboard with MIT License | 4 votes |
function Capacity({ filterDistrict, filterFacilityTypes, date }) {
const [forecast, setForecast] = useState(false);
const { data } = useSWR(
["Capacity", date, filterDistrict.id],
(url, date, district) =>
careSummary(
"facility",
dateString(getNDateBefore(date, 1)),
dateString(getNDateAfter(date, 1)),
district
)
);
const { facilitiesTrivia, exported, todayFiltered, capacityCardData } =
useMemo(() => {
const filtered = processFacilities(data.results, filterFacilityTypes);
const facilitiesTrivia = filtered.reduce(
(a, c) => {
const key = c.date === dateString(date) ? "current" : "previous";
a[key].count += 1;
a[key].oxygen += c.oxygenCapacity || 0;
a[key].actualLivePatients += c.actualLivePatients || 0;
a[key].actualDischargedPatients += c.actualDischargedPatients || 0;
Object.keys(AVAILABILITY_TYPES).forEach((k) => {
a[key][k].used += c.capacity[k]?.current_capacity || 0;
a[key][k].total += c.capacity[k]?.total_capacity || 0;
});
AVAILABILITY_TYPES_TOTAL_ORDERED.forEach((k) => {
const current_covid = c.capacity[k.covid]?.current_capacity || 0;
const current_non_covid =
c.capacity[k.non_covid]?.current_capacity || 0;
const total_covid = c.capacity[k.covid]?.total_capacity || 0;
const total_non_covid =
c.capacity[k.non_covid]?.total_capacity || 0;
a[key][k.id].used += current_covid + current_non_covid;
a[key][k.id].total += total_covid + total_non_covid;
});
return a;
},
{
current: JSON.parse(JSON.stringify(initialFacilitiesTrivia)),
previous: JSON.parse(JSON.stringify(initialFacilitiesTrivia)),
}
);
const exported = {
data: filtered.reduce((a, c) => {
if (c.date !== dateString(date)) {
return a;
}
return [
...a,
{
"Govt/Pvt": GOVT_FACILITY_TYPES.includes(c.facilityType)
? "Govt"
: "Pvt",
"Hops/CFLTC":
c.facilityType === "First Line Treatment Centre"
? "CFLTC"
: "Hops",
"Hospital/CFLTC Address": c.address,
"Hospital/CFLTC Name": c.name,
Mobile: c.phoneNumber,
...AVAILABILITY_TYPES_ORDERED.reduce((t, x) => {
const y = { ...t };
y[`Current ${AVAILABILITY_TYPES[x]}`] =
c.capacity[x]?.current_capacity || 0;
y[`Total ${AVAILABILITY_TYPES[x]}`] =
c.capacity[x]?.total_capacity || 0;
return y;
}, {}),
},
];
}, []),
filename: "capacity_export.csv",
};
const capacityCardData = filtered.reduce((acc, facility) => {
const covidData = getCapacityBedData([30, 120, 110, 100], facility);
const nonCovidData = getCapacityBedData([1, 150, 10, 20], facility);
const finalTotalData = getFinalTotalData(covidData, nonCovidData);
const noCapacity = finalTotalData.every((item) => item.total === 0);
if (facility.date !== dateString(date) || noCapacity) {
return acc;
}
return [
...acc,
{
facility_name: facility.name,
facility_id: facility.id,
facility_type: facility.facilityType,
phone_number: facility.phoneNumber,
last_updated: dayjs(facility.modifiedDate).fromNow(),
patient_discharged: `${facility.actualLivePatients || 0}/${
facility.actualDischargedPatients || 0
}`,
covid: covidData,
non_covid: nonCovidData,
final_total: finalTotalData,
},
];
}, []);
const todayFiltered = filtered.filter((f) => f.date === dateString(date));
return {
facilitiesTrivia,
exported,
todayFiltered,
capacityCardData,
};
}, [data, filterFacilityTypes]);
const transitions = useTransition(forecast, null, {
enter: { opacity: 1 },
from: { opacity: 0 },
leave: { opacity: 0 },
});
const [filteredData, setFilteredData] = useState(capacityCardData);
const [tableData, setTableData] = useState([]);
const [searchTerm, setSearchTerm] = useState("");
const [page, setPage] = useState(0);
const resultsPerPage = 10;
useEffect(() => {
const debounce_timer = setTimeout(() => {
setFilteredData(
searchTerm
? fuzzysort
.go(searchTerm, capacityCardData, { key: "facility_name" })
.map((v) => v.obj)
: capacityCardData
);
setPage(0);
}, 1000);
return () => clearTimeout(debounce_timer);
}, [searchTerm, capacityCardData]);
useEffect(() => {
setTableData(
filteredData.slice(page * resultsPerPage, (page + 1) * resultsPerPage)
);
}, [filteredData, page]);
return transitions.map(({ item, key, props }) =>
item ? (
<animated.div key={key} style={props}>
<CapacityForecast
filterDistrict={filterDistrict}
filterFacilityTypes={filterFacilityTypes}
date={date}
setForecast={setForecast}
/>
</animated.div>
) : (
<animated.div key={key} style={props}>
<div className="grid gap-1 grid-rows-none mb-8 sm:grid-flow-col-dense sm:grid-rows-1 sm:place-content-end">
<ValuePill
title="Facility Count"
value={facilitiesTrivia.current.count}
/>
<ValuePill
title="Oxygen Capacity"
value={facilitiesTrivia.current.oxygen}
/>
<ValuePill
title="Live Patients"
value={facilitiesTrivia.current.actualLivePatients}
/>
<ValuePill
title="Discharged Patients"
value={facilitiesTrivia.current.actualDischargedPatients}
/>
<Pill title="Forecast">
<Button
size="small"
onClick={() => setForecast(true)}
className="w-full bg-transparent shadow-xs"
>
<ArrowRight className="h-4" />
</Button>
</Pill>
</div>
<div className="grid-col-1 grid gap-6 mb-8 md:grid-cols-4">
{AVAILABILITY_TYPES_TOTAL_ORDERED.map((k) => (
<RadialCard
label={k.name}
count={facilitiesTrivia.current.count}
current={facilitiesTrivia.current[k.id]}
previous={facilitiesTrivia.previous[k.id]}
key={k.name}
/>
))}
</div>
<div className="grid-col-1 grid gap-6 mb-8 md:grid-cols-4">
{AVAILABILITY_TYPES_ORDERED.map((k) => (
<RadialCard
label={AVAILABILITY_TYPES[k]}
count={facilitiesTrivia.current.count}
current={facilitiesTrivia.current[k]}
previous={facilitiesTrivia.previous[k]}
key={k}
/>
))}
</div>
<div id="facility-capacity-cards" className="mb-16 mt-16">
<div className="flex flex-col items-center justify-between md:flex-row">
<SectionTitle>Facilities</SectionTitle>
<div className="flex max-w-full space-x-4">
{exported && (
<CSVLink data={exported.data} filename={exported.filename}>
<Button block>Export</Button>
</CSVLink>
)}
<Input
className="sw-40 rounded-lg sm:w-auto"
placeholder="Search Facility"
value={searchTerm}
onChange={(event) => setSearchTerm(event.target.value)}
/>
</div>
</div>
{tableData.map((data, index) => (
<CapacityCard data={data} key={index} />
))}
<Pagination
resultsPerPage={resultsPerPage}
totalResults={filteredData.length}
currentPage={page}
currentResults={tableData.length}
handlePageClick={setPage}
/>
</div>
<div id="capacity-map">
<SectionTitle>Map</SectionTitle>
</div>
<Suspense fallback={<ThemedSuspense />}>
<GMap
className="mb-8"
facilities={todayFiltered}
district={filterDistrict}
/>
</Suspense>
</animated.div>
)
);
}
Example #24
Source File: NotificationButton.js From instaclone with Apache License 2.0 | 4 votes |
NotificationButton = ({
notifications,
notificationState,
mobile,
icon,
}) => {
const [showNotifications, setShowNotifications] = useState(false);
const [showNotificationPopup, setShowNotificationPopup] = useState(false);
const [notificationPopupTimeout, setShowNotificationPopupTimeout] = useState(
null
);
useEffect(() => {
if (notificationPopupTimeout) {
clearTimeout(notificationPopupTimeout);
}
if (notificationState.unreadCount > 0) {
!showNotificationPopup && setShowNotificationPopup(true);
setShowNotificationPopupTimeout(
setTimeout(() => setShowNotificationPopup(false), 10000)
);
}
}, [notificationState.unreadCount]);
useEffect(() => {
if (showNotifications) {
clearTimeout(notificationPopupTimeout);
setShowNotificationPopup(false);
}
}, [showNotifications, notificationPopupTimeout]);
const transitions = useTransition(
notificationState.unreadCount > 0 && showNotificationPopup
? { notifications }
: false,
null,
{
from: {
transform: 'scale(0) translateX(-50%)',
opacity: 0,
},
enter: {
transform: 'scale(1) translateX(-50%)',
opacity: 1,
},
leave: {
transform: 'scale(0) translateX(-50%)',
opacity: 0,
},
config: {
tension: 280,
friction: 20,
},
}
);
return (
<div style={{ position: 'relative', height: '100%' }}>
<button className="notification-button">
<Icon
icon={icon ? icon : showNotifications ? 'heart' : 'heart-outline'}
className={notificationState.unreadCount > 0 ? 'icon--unread' : ''}
onClick={() =>
!mobile && setShowNotifications((previous) => !previous)
}
style={{ cursor: 'pointer' }}
/>
{transitions.map(
({ item, key, props }) =>
item && (
<NotificationPopup
style={props}
notifications={item.notifications}
key={key}
/>
)
)}
</button>
{showNotifications && !mobile && (
<PopupCard hide={() => setShowNotifications(false)} leftAlign>
<NotificationFeed setShowNotifications={setShowNotifications} />
</PopupCard>
)}
</div>
);
}
Example #25
Source File: App.js From instaclone with Apache License 2.0 | 4 votes |
export function UnconnectedApp({
signInStart,
modal,
alert,
currentUser,
connectSocket,
fetchNotificationsStart,
}) {
const token = localStorage.getItem('token');
const {
location: { pathname },
} = useHistory();
useEffect(() => {
if (token) {
signInStart(null, null, token);
connectSocket();
fetchNotificationsStart(token);
}
}, [signInStart, connectSocket, fetchNotificationsStart, token]);
const renderModals = () => {
if (modal.modals.length > 0) {
// Disable scrolling on the body while a modal is active
document.querySelector('body').setAttribute('style', 'overflow: hidden;');
return modal.modals.map((modal, idx) => (
<Modal key={idx} component={modal.component} {...modal.props} />
));
} else {
document.querySelector('body').setAttribute('style', '');
}
};
const transitions = useTransition(alert.showAlert, null, {
from: {
transform: 'translateY(4rem)',
},
enter: {
transform: 'translateY(0rem)',
},
leave: {
transform: 'translateY(4rem)',
},
config: {
tension: 500,
friction: 50,
},
});
const renderApp = () => {
// Wait for authentication
if (!currentUser && token) {
return <LoadingPage />;
}
return (
<Fragment>
{pathname !== '/login' && pathname !== '/signup' && <Header />}
{renderModals()}
{transitions.map(
({ item, props, key }) =>
item && (
<Alert key={key} style={props} onClick={alert.onClick}>
{alert.text}
</Alert>
)
)}
<Switch>
<Route path="/login" component={LoginPage} />
<Route path="/signup" component={SignUpPage} />
<ProtectedRoute exact path="/" component={HomePage} />
<ProtectedRoute path="/settings" component={SettingsPage} />
<ProtectedRoute path="/activity" component={ActivityPage} />
<ProtectedRoute path="/new" component={NewPostPage} />
<ProtectedRoute path="/explore" component={ExplorePage} />
<Route exact path="/:username" component={ProfilePage} />
<Route path="/post/:postId" component={PostPage} />
<ProtectedRoute path="/confirm/:token" component={ConfirmationPage} />
<Route component={NotFoundPage} />
</Switch>
{pathname !== '/' && <Footer />}
{pathname !== '/login' &&
pathname !== '/signup' &&
pathname !== '/new' &&
currentUser && <MobileNav currentUser={currentUser} />}
</Fragment>
);
};
return (
<div className="app" data-test="component-app">
<Suspense fallback={<LoadingPage />}>{renderApp()}</Suspense>
</div>
);
}
Example #26
Source File: _app.js From proof-of-humanity-web with MIT License | 4 votes |
export default function App({ Component, pageProps }) {
const router = useRouter();
const query = useMemo(
() => wrapConnection.parseAsPath(router.asPath).query,
[router.asPath]
);
const networkFromQuery = query?.network ?? network;
const [networkFromProvider, setNetworkFromProvider] = useState();
const [routeChangeConnection, setRouteChangeConnection] = useState();
const connectToRouteChange = useCallback((connection) => {
const wrappedConnection = wrapConnection(connection);
wrappedConnection(location.pathname + location.search);
setRouteChangeConnection(() => wrappedConnection);
}, []);
useEffect(() => {
if (routeChangeConnection) {
router.events.on("routeChangeStart", routeChangeConnection);
return () => router.events.off("routeChangeStart", routeChangeConnection);
}
}, [routeChangeConnection, router.events]);
const onNetworkChange = useCallback(
(ETHNet) => {
const { name: _network } = ETHNet;
if (networkFromQuery !== _network) {
const searchParameters = new URLSearchParams(location.search);
if (!_network) searchParameters.delete("network");
else searchParameters.set("network", _network);
router.replace({
pathname: location.pathname,
query: searchParameters.toString(),
});
}
setNetworkFromProvider(ETHNet);
},
[router, networkFromQuery]
);
const transitions = useTransition(
[{ key: router.route, Component, pageProps }],
(item) => item.key,
{
from: { opacity: 0, transform: "translate3d(0%,0,0)" },
enter: { opacity: 1, transform: "translate3d(0%,0,0)" },
leave: {
opacity: 0,
position: "absolute",
transform: "translate3d(-100%,0,0)",
},
}
);
if (
(networkFromProvider &&
networkFromProvider.name !== process.env.NEXT_PUBLIC_NETWORK) ||
network !== process.env.NEXT_PUBLIC_NETWORK
)
return (
<Flex
sx={{
alignItems: "center",
height: "100vh",
justifyContent: "center",
width: "100vw",
}}
>
Unsupported network. Please switch to {capitalize(network)} and refresh.
</Flex>
);
const apiKey = process.env.NEXT_PUBLIC_THEGRAPH_APIKEY;
const subgraphID = process.env.NEXT_PUBLIC_SUBGRAPHID;
const endpoint =
process.env.NEXT_PUBLIC_TESTING === "true"
? `https://api.thegraph.com/subgraphs/name/kleros/proof-of-humanity-${networkFromQuery}`
: `https://gateway.thegraph.com/api/${apiKey}/subgraphs/id/${subgraphID}`;
return (
<ThemeProvider theme={theme}>
<RelayProvider
endpoint={endpoint}
queries={queries}
connectToRouteChange={connectToRouteChange}
>
<Web3Provider
infuraURL={process.env.NEXT_PUBLIC_INFURA_ENDPOINT}
contracts={contracts}
onNetworkChange={onNetworkChange}
>
<ArchonProvider>
<Layout header={header} footer={footer}>
{transitions.map(({ key, props, item }) => (
<AnimatedBox
key={key}
style={{
...props,
transform: props.transform.interpolate((t) =>
t === "translate3d(0%,0,0)" ? undefined : t
),
}}
sx={{ padding: 3 }}
>
<item.Component {...item.pageProps} />
</AnimatedBox>
))}
</Layout>
</ArchonProvider>
</Web3Provider>
</RelayProvider>
</ThemeProvider>
);
}