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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
// 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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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()}>
              &#10005;
            </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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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>
  );
}