@reach/router#useLocation TypeScript Examples

The following examples show how to use @reach/router#useLocation. 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: useSearchModal.ts    From usehooks-ts with MIT License 6 votes vote down vote up
useSearchModal = (): [boolean, Record<string, () => void>] => {
  const { value, setTrue: openModal, setFalse: closeModal } = useBoolean(false)
  const location = useLocation()

  useUpdateEffect(() => {
    closeModal()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [location])

  return [value, { openModal, closeModal }]
}
Example #2
Source File: Feedback.tsx    From website-docs with MIT License 6 votes vote down vote up
export function FeedbackDoc({ pathConfig, filePath }: Props) {
  const { site } = useStaticQuery(graphql`
    query {
      site {
        siteMetadata {
          siteUrl
        }
      }
    }
  `)
  let { pathname } = useLocation()
  if (pathname.endsWith('/')) {
    pathname = pathname.slice(0, -1) // unify client and ssr
  }

  return (
    <a
      className="doc-help-link feedback"
      href={`https://github.com/${getRepo(
        pathConfig
      )}/issues/new?body=File:%20[/${pathConfig.branch}/${filePath}](${
        site.siteMetadata.siteUrl
      }${pathname})`}
      target="_blank"
      rel="noreferrer">
      <Trans i18nKey="doc.feedback" />
    </a>
  )
}
Example #3
Source File: announcement.tsx    From web with Apache License 2.0 6 votes vote down vote up
Announcement = ({
  longText,
  shortText,
  link,
  className,
  openInNewWindow = false
}: PropTypes) => {
  const location = useLocation()

  if (location.pathname.replace(/\/+$/, '') === link.replace(/\/+$/, '')) {
    return null
  }

  return (
    <div className={className}>
      <AnnouncementBanner
        text={longText}
        link={link}
        lengthy={true}
        openInNewWindow={openInNewWindow}
      />
      <AnnouncementBanner
        text={shortText}
        link={link}
        lengthy={false}
        openInNewWindow={openInNewWindow}
      />
    </div>
  )
}
Example #4
Source File: SignInView.tsx    From Frontend with MIT License 5 votes vote down vote up
LoginView: React.FC<RouteComponentProps> = (props) => {
  const { search } = useLocation();
  const { locationStore } = useStores();
  const intl = useIntl();

  const queryParams = queryString.parse(search) as any;

  if (queryParams.next) {
    locationStore.setNext(queryParams.next);
  } else {
    locationStore.setNext('/me');
  }

  console.log(props);

  return (
    <>
      <PageHeader
        heading={intl.formatMessage({ id: 'SigninView.heading' })}
        lead={intl.formatMessage({ id: 'SigninView.lead' })}
      />
      <FormState.Provider>
        <Tabs variant="soft-rounded" variantColor="teal">
          <TabList>
            <Tab>Sign In</Tab>
            <Tab>Sign Up</Tab>
          </TabList>

          <TabPanels>
            <TabPanel>
              <SignInForm></SignInForm>
            </TabPanel>
            <TabPanel>
              <SignUpForm></SignUpForm>
            </TabPanel>
          </TabPanels>
        </Tabs>

        <Form
          onLoginSuccess={(user) => {
            navigate('/me');
          }}
        ></Form>
      </FormState.Provider>
    </>
  );
}
Example #5
Source File: tab-navigation.tsx    From desktop with MIT License 5 votes vote down vote up
export function SiteTabLink({ site, ...props }: ITabProps): JSX.Element {
  const { removeTab } = useSiteTabs()

  const location = useLocation()

  const url = `/sites/${site.hash}`

  const isActive = location.pathname === url

  const remove = useCallback(() => {
    if (isActive) {
      navigate(`/sites`)
    }
    removeTab(site.hash)
  }, [removeTab, site, isActive])

  return (
    <Flex
      sx={{
        alignItems: `center`,
        pr: 2,
        py: 3,
        ...(isActive && {
          backgroundColor: `purple.80`,
          color: `white`,
        }),
      }}
    >
      <TabLink {...props} to={url}>
        <SiteStatusDot status={site.siteStatus.status} sx={{ mr: 2 }} />
        {site.name}
      </TabLink>
      <button
        onClick={remove}
        aria-label="Close tab"
        sx={{
          p: 3,
          background: `none`,
          border: `none`,
          fontFamily: `sans`,
          fontWeight: 500,
          textDecoration: `none`,
          color: `primaryBackground`,
          display: `flex`,
          alignItems: `center`,
        }}
      >
        <MdClear />
      </button>
    </Flex>
  )
}
Example #6
Source File: seo.tsx    From usehooks-ts with MIT License 5 votes vote down vote up
SEO: FC<SEOProps> = ({
  title,
  description = '',
  lang = 'en',
  meta = [],
}) => {
  const location = useLocation()
  const siteMetadata = useSiteMetadata()
  const metaDescription = description || siteMetadata.description
  const url = `${siteMetadata.siteUrl}${location.pathname}`
  const hookPageRegExp = new RegExp('/react-hook/')
  const isHookPage = hookPageRegExp.test(url)

  // Build image from title using "Typescript blue" optimized for Facebook banned
  const image = `https://via.placeholder.com/1200x630.png/007ACC/fff/?text=${title}`

  return (
    <Helmet
      htmlAttributes={{
        lang,
      }}
      title={title}
      titleTemplate={`%s`}
      link={[{ rel: 'canonical', key: url, href: url }]}
      meta={[
        {
          name: `description`,
          content: metaDescription,
        },
        {
          property: `og:title`,
          content: title,
        },
        {
          property: `og:image`,
          content: image,
        },
        {
          property: `og:description`,
          content: metaDescription,
        },
        {
          property: `og:site_name`,
          content: siteMetadata.title,
        },
        {
          property: `og:type`,
          content: isHookPage ? `article` : `website`,
        },
        {
          property: `og:url`,
          content: url,
        },
        {
          name: `twitter:card`,
          content: `summary`,
        },
        // {
        //   name: `twitter:creator`,
        //   content: siteMetadata.author,
        // },
        {
          name: `twitter:title`,

          content: title,
        },
        {
          name: `twitter:description`,
          content: metaDescription,
        },
      ].concat(meta)}
    />
  )
}
Example #7
Source File: NavbarDocsCategory.tsx    From mantine with MIT License 5 votes vote down vote up
export default function NavbarDocsCategory({ group, onLinkClick }: NavbarDocsCategoryProps) {
  const { classes, cx } = useStyles();
  const { pathname } = useLocation();
  const [collapsed, setCollapsed] = useState(!hasActiveLink(group, pathname));
  const itemRefs = useRef<Record<string, HTMLElement>>({});

  useEffect(() => {
    if (hasActiveLink(group, pathname) && itemRefs.current[pathname]) {
      const element = itemRefs.current[pathname];
      const height = typeof window !== 'undefined' ? window.innerHeight : 0;
      const { top, bottom } = element.getBoundingClientRect();

      if (top < HEADER_HEIGHT || bottom > height) {
        element.scrollIntoView({ block: 'center' });
      }
    }
  }, [pathname]);

  const uncategorized = (
    group.group === 'changelog' ? [...group.uncategorized].reverse() : group.uncategorized
  ).map((link) => (
    <Link
      key={link.slug}
      className={classes.link}
      activeClassName={classes.linkActive}
      to={link.slug}
      onClick={onLinkClick}
      ref={(r) => {
        itemRefs.current[link.slug] = r;
      }}
    >
      {link.title}
    </Link>
  ));

  const categorized = !Array.isArray(group.groups)
    ? []
    : group.groups.map((part) => {
        if (!part || !Array.isArray(part.pages)) {
          return null;
        }
        const links = part.pages.map((link) => (
          <Link
            key={link.slug}
            className={classes.link}
            activeClassName={classes.linkActive}
            to={link.slug}
            onClick={onLinkClick}
            ref={(r) => {
              itemRefs.current[link.slug] = r;
            }}
          >
            {link.title}
          </Link>
        ));

        return (
          <div className={classes.innerCategory} key={part.category.title}>
            <Text className={classes.innerCategoryTitle}>
              <part.category.icon className={classes.innerCategoryIcon} />
              {part.category.title}
            </Text>
            {links}
          </div>
        );
      });

  return (
    <div className={cx(classes.category, { [classes.categoryCollapsed]: collapsed })}>
      <button className={classes.header} type="button" onClick={() => setCollapsed((c) => !c)}>
        <ChevronDownIcon className={cx(classes.icon, { [classes.iconCollapsed]: collapsed })} />
        <Text className={classes.title} weight={700} size="xs" transform="uppercase">
          {group.group.replace('-', ' ')}
        </Text>
      </button>
      {!collapsed && uncategorized}
      {!collapsed && categorized}
    </div>
  );
}
Example #8
Source File: TableOfContents.tsx    From mantine with MIT License 5 votes vote down vote up
export default function TableOfContents({ headings, withTabs }: TableOfContentsProps) {
  const theme = useMantineTheme();
  const { classes, cx } = useStyles();
  const slugger = new Slugger();
  const [active, setActive] = useState(0);
  const { pathname } = useLocation();

  const slugs = useRef<HTMLDivElement[]>([]);
  const filteredHeadings = headings.filter((heading) => heading.depth > 1);

  useEffect(() => {
    slugger.reset();
    slugs.current = filteredHeadings.map(
      (heading) => document.getElementById(slugger.slug(heading.value)) as HTMLDivElement
    );
  }, [headings]);

  const handleScroll = () => {
    setActive(getActiveElement(slugs.current.map((d) => d.getBoundingClientRect())));
  };

  useEffect(() => {
    setActive(getActiveElement(slugs.current.map((d) => d.getBoundingClientRect())));
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  if (filteredHeadings.length === 0) {
    return null;
  }

  const items = filteredHeadings.map((heading, index) => {
    const slug = slugger.slug(heading.value);
    return (
      <Text<'a'>
        key={slug}
        component="a"
        size="sm"
        className={cx(classes.link, { [classes.linkActive]: active === index })}
        href={`#${slug}`}
        sx={{ paddingLeft: (heading.depth - 1) * theme.spacing.lg }}
        onClick={(event) => {
          event.preventDefault();
          navigate(`${pathname}#${slug}`, { replace: true });
        }}
      >
        {heading.value}
      </Text>
    );
  });

  return (
    <nav className={cx(classes.wrapper, { [classes.withTabs]: withTabs })}>
      <div className={classes.inner}>
        <div>
          <div className={classes.header}>
            <ActivityLogIcon />
            <Text className={classes.title}>Table of contents</Text>
          </div>
          <div className={classes.items}>{items}</div>
        </div>
      </div>
    </nav>
  );
}
Example #9
Source File: SimpleTab.tsx    From website-docs with MIT License 5 votes vote down vote up
export function SimpleTab({
  children,
}: {
  children: ReactElement<{ label: string; href?: string; children: ReactElement[] }>[]
}) {
  const location = useLocation()
  const [activeTab, setActiveTab] = useState(0)
  
  useEffect(() => {
    let active = children.findIndex(
      child => {
        const activeJudge: string = child.props?.href || child.props.label;
        return activeJudge === decodeURIComponent(location.hash.slice(1))
      }
    )
    if (active === -1) {
      active = 0
    }
    setActiveTab(active)
  }, [location.hash, children])

  return (
    <>
      <ul className={tabs}>
        {children.map((child, index) => {
          const id: string = child.props?.href || child.props.label;
          return (
            <li key={id} id={id}>
              <a
                href={`#${id}`}
                className={activeTab === index ? active : normal}>
                {child.props.label}
              </a>
            </li>
          )
        })}
      </ul>
      {children.map((child, index) => {
        const id: string = child.props?.href || child.props.label;
        return (
          <div
            key={id}
            className={clsx(activeTab !== index && hidden)}>
            {child.props.children}
          </div>
        )
      })}
    </>
  )
}
Example #10
Source File: pricing-table.tsx    From admin with MIT License 5 votes vote down vote up
PricingTable = () => {
  const location = useLocation()
  const params = usePriceListFilters(location.search, defaultQueryProps)
  const [columns] = usePriceListTableColumns()

  const { price_lists, isLoading, count = 0 } = useAdminPriceLists(
    params.queryObject,
    {
      keepPreviousData: true,
    }
  )

  useSetSearchParams(params.representationObject)

  const resetFilters = () => {
    params.setQuery("")
    params.reset()
  }

  return (
    <div className="w-full overflow-y-auto flex flex-col justify-between min-h-[300px] h-full ">
      <LoadingContainer isLoading={isLoading}>
        <PriceListTable
          columns={columns}
          count={count}
          priceLists={price_lists || []}
          options={{
            enableSearch: true,
            filter: (
              <PriceListsFilter
                filters={params.filters}
                submitFilters={params.setFilters}
                clearFilters={resetFilters}
                tabs={params.availableTabs}
                onTabClick={params.setTab}
                activeTab={params.activeFilterTab}
                onRemoveTab={params.removeTab}
                onSaveTab={params.saveTab}
              />
            ),
          }}
          {...params}
        />
      </LoadingContainer>
    </div>
  )
}
Example #11
Source File: index.tsx    From website-docs with MIT License 4 votes vote down vote up
export default function Search() {
  const { language } = useI18next()

  const location = useLocation()
  const searchParams = new URLSearchParams(location.search)
  const type = searchParams.get('type') || defaultDocInfo['type']
  const version = searchParams.get('version') || defaultDocInfo['version']
  const query = searchParams.get('q')

  const dispatch = useDispatch()

  const loading = useSelector(state => state.loading)

  const [selectedType, setSelectedType] = useState(type)
  const toAlgoliaVersion = version =>
    version === 'stable'
      ? convertVersionName(replaceStableVersion(selectedType))
      : version !== 'null' ? version : null
  const [selectedVersion, _setSelectedVersion] = useState(
    toAlgoliaVersion(version)
  )
  const setSelectedVersion = version =>
    _setSelectedVersion(toAlgoliaVersion(version))
  const [selectedVersionList, setSelectedVersionList] = useState(
    matchToVersionList(type)
  )
  const [results, setResults] = useState([])
  const [searched, setSearched] = useState(false)
  const [docsTypesByLang, setDocsTypesByLang] = useState([])

  useEffect(() => {
    return () => dispatch(setSearchValue(''))
  }, [dispatch])

  useEffect(() => {
    const types = [
      {
        name: 'TiDB',
        match: 'tidb',
      },
      {
        name: 'TiDB in Kubernetes',
        match: 'tidb-in-kubernetes',
      },
      {
        name: 'TiDB Data Migration (DM)',
        match: 'tidb-data-migration',
      },
    ]

    const getDocsTypesByLang = () => {
      switch (language) {
        case 'zh':
          types.push({
            name: '开发指南',
            match: 'appdev',
          })

          break
        default:
          types.push(
            {
              name: 'Cloud',
              match: 'tidbcloud',
            },
            {
              name: 'App Dev',
              match: 'appdev',
            }
          )

          break
      }

      return types
    }

    setDocsTypesByLang(getDocsTypesByLang())
  }, [language])

  const handleSetVersionList = match => () => {
    const versionList = matchToVersionList(match)

    setSelectedType(match)
    setSelectedVersionList(versionList)
    setSelectedVersion(versionList ? versionList[0] : null)
  }

  function execSearch() {
    dispatch(setLoading(true))

    const index = algoliaClient.initIndex(
      `${language}-${selectedType}${selectedVersion ? '-' + selectedVersion : ''}`
    )

    index
      .search(query, {
        hitsPerPage: 150,
      })
      .then(({ hits }) => {
        setResults(hits)
        setSearched(true)
        dispatch(setLoading(false))
      })
  }

  useEffect(() => {
    if (selectedType && query) {
      execSearch()
    } else {
      setResults([])
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedType, selectedVersion, query])

  return (
    <Layout>
      <Seo title="Search" noindex />
      <div>
        <div>
          <div className={select}>
            <span className={optionLabel}>
              <Trans i18nKey="search.type" />
            </span>

            {docsTypesByLang.map(type => (
              <button
                key={type.name}
                className={clsx(
                  optionItem,
                  selectedType === type.match && isActive
                )}
                onClick={handleSetVersionList(type.match)}>
                {type.name}
              </button>
            ))}
          </div>

          {selectedVersionList && (
            <div className={select}>
              <span className={optionLabel}>
                <Trans i18nKey="search.version" />
              </span>

              {selectedVersionList.map(version => (
                <button
                  key={version}
                  className={clsx(
                    optionItem,
                    selectedVersion === toAlgoliaVersion(version) && isActive
                  )}
                  onClick={() => setSelectedVersion(toAlgoliaVersion(version))}>
                  {toAlgoliaVersion(version)}
                </button>
              ))}
            </div>
          )}
        </div>

        <div style={{ position: 'relative' }}>
          <SearchResult results={results} searched={searched} />
          {loading && (
            <Loading
              stretched
              style={{ alignItems: 'start' }}
              imgProps={{
                style: {
                  marginTop: '2rem',
                },
              }}
            />
          )}
        </div>
      </div>
    </Layout>
  )
}
Example #12
Source File: InviteView.tsx    From Frontend with MIT License 4 votes vote down vote up
InviteView: React.FC<RouteComponentProps> = () => {
  const { connectionMade } = useAnalytics();
  const { uid }: params = useParams();
  const location = useLocation();
  const toast = useToast();
  const intl = useIntl();
  const { profile } = useAuth();
  const [value, loading] = useObjectVal<Profile>(
    firebase.database().ref(`profiles/${uid}`)
  );
  const [
    createKnowsMutation,
    { loading: isLoadingConnection }
  ] = useCreateKnowsMutation({
    onCompleted() {
      connectionMade();
      toast({
        position: 'bottom-right',
        title: intl.formatMessage({ id: 'InviteView.Connected' }),
        description: intl.formatMessage(
          {
            id: 'InviteView.Connected-Description'
          },
          {
            name: value.displayName
          }
        ),
        status: 'success',
        isClosable: true
      });
    }
  });

  if (loading) {
    return <Spinner />;
  }

  const displayName = value && value.displayName ? value.displayName : 'user';
  const photoURL = value && value.photoURL ? value.photoURL : null;
  const shouldShowConnectButton = profile?.uid !== uid;

  return (
    <>
      <PageHeader
        heading={intl.formatMessage({ id: 'InviteView.heading' })}
        lead={intl.formatMessage(
          {
            id: 'InviteView.lead'
          },
          {
            name: value.displayName
          }
        )}
      />

      <AvatarGroup size="xl" max={2} mb={12}>
        <Avatar name={displayName} src={photoURL} />
        <Avatar bg="none" name="Contact Tracing" src={icon} />
      </AvatarGroup>
      {shouldShowConnectButton && (
        <Button
          isLoading={isLoadingConnection}
          width="200px"
          mb={16}
          variantColor="teal"
          onClick={() => {
            if (!profile) {
              navigate(`/me/sign-in?next=${location.pathname}`);
              return;
            }

            createKnowsMutation({
              variables: {
                fromUid: profile?.uid,
                toUid: uid
              }
            });
          }}
        >
          <FormattedMessage id="InviteView.Connect-button" />
        </Button>
      )}
      <Heading as="h3" mb={2} size="lg">
        <FormattedMessage id="InviteView.why-use" />
      </Heading>
      <List styleType="disc">
        <ListItem>
          <FormattedMessage id="InviteView.why-1" />
        </ListItem>
        <ListItem>
          <FormattedMessage id="InviteView.why-2" />
        </ListItem>
        <ListItem>
          <FormattedMessage id="InviteView.why-3" />
        </ListItem>
      </List>
    </>
  );
}
Example #13
Source File: index.tsx    From admin with MIT License 4 votes vote down vote up
ProductIndex = () => {
  const location = useLocation()
  const [view, setView] = useState("products")

  const notification = useNotification()

  const createCollection = useAdminCreateCollection()

  useEffect(() => {
    if (location.search.includes("?view=collections")) {
      setView("collections")
    }
  }, [location])

  useEffect(() => {
    location.search = ""
  }, [view])

  const CurrentView = () => {
    switch (view) {
      case "products":
        return <ProductTable />
      default:
        return <CollectionsTable />
    }
  }

  const CurrentAction = () => {
    switch (view) {
      case "products":
        return [
          {
            label: "New Product",
            onClick: () => navigate("/a/products/new"),
            icon: (
              <span className="text-grey-90">
                <PlusIcon size={20} />
              </span>
            ),
          },
        ]
      default:
        return [
          {
            label: "New Collection",
            onClick: () => setShowNewCollection(!showNewCollection),
            icon: (
              <span className="text-grey-90">
                <PlusIcon size={20} />
              </span>
            ),
          },
        ]
    }
  }

  const [showNewCollection, setShowNewCollection] = useState(false)

  const handleCreateCollection = async (data, colMetadata) => {
    const metadata = colMetadata
      .filter((m) => m.key && m.value) // remove empty metadata
      .reduce((acc, next) => {
        return {
          ...acc,
          [next.key]: next.value,
        }
      }, {})

    await createCollection.mutateAsync(
      { ...data, metadata },
      {
        onSuccess: ({ collection }) => {
          notification("Success", "Successfully created collection", "success")
          navigate(`/a/collections/${collection.id}`)
          setShowNewCollection(false)
        },
        onError: (err) => notification("Error", getErrorMessage(err), "error"),
      }
    )
  }

  return (
    <>
      <div className="flex flex-col grow h-full">
        <div className="w-full flex flex-col grow">
          <BodyCard
            actionables={CurrentAction()}
            customHeader={
              <TableViewHeader
                views={VIEWS}
                setActiveView={setView}
                activeView={view}
              />
            }
          >
            <CurrentView />
          </BodyCard>
        </div>
      </div>
      {showNewCollection && (
        <AddCollectionModal
          onClose={() => setShowNewCollection(!showNewCollection)}
          onSubmit={handleCreateCollection}
        />
      )}
    </>
  )
}
Example #14
Source File: index.tsx    From admin with MIT License 4 votes vote down vote up
ProductTable: React.FC<ProductTableProps> = () => {
  const location = useLocation()

  const {
    removeTab,
    setTab,
    saveTab,
    availableTabs: filterTabs,
    activeFilterTab,
    reset,
    paginate,
    setFilters,
    setLimit,
    filters,
    setQuery: setFreeText,
    queryObject,
    representationObject,
  } = useProductFilters(location.search, defaultQueryProps)

  const offs = parseInt(queryObject.offset) || 0
  const limit = parseInt(queryObject.limit)

  const [query, setQuery] = useState(queryObject.query)
  const [numPages, setNumPages] = useState(0)

  const clearFilters = () => {
    reset()
    setQuery("")
  }

  const { products, isLoading, isRefetching, count } = useAdminProducts({
    ...queryObject,
  })

  useEffect(() => {
    if (typeof count !== "undefined") {
      const controlledPageCount = Math.ceil(count / limit)
      setNumPages(controlledPageCount)
    }
  }, [count])

  const updateUrlFromFilter = (obj = {}) => {
    const stringified = qs.stringify(obj)
    window.history.replaceState(`/a/products`, "", `${`?${stringified}`}`)
  }

  const refreshWithFilters = () => {
    const filterObj = representationObject

    if (isEmpty(filterObj)) {
      updateUrlFromFilter({ offset: 0, limit: DEFAULT_PAGE_SIZE })
    } else {
      updateUrlFromFilter(filterObj)
    }
  }

  useEffect(() => {
    refreshWithFilters()
  }, [representationObject])

  const setTileView = () => {
    setLimit(DEFAULT_PAGE_SIZE_TILE_VIEW)
    setShowList(false)
  }

  const setListView = () => {
    setLimit(DEFAULT_PAGE_SIZE)
    setShowList(true)
  }
  const [showList, setShowList] = React.useState(true)
  const [columns] = useProductTableColumn({
    setTileView,
    setListView,
    showList,
  })

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    gotoPage,
    canPreviousPage,
    canNextPage,
    pageCount,
    nextPage,
    previousPage,
    // Get the state from the instance
    state: { pageIndex, pageSize },
  } = useTable(
    {
      columns,
      data: products || [],
      manualPagination: true,
      initialState: {
        pageIndex: Math.floor(offs / limit),
        pageSize: limit,
      },
      pageCount: numPages,
      autoResetPage: false,
    },
    usePagination
  )

  // Debounced search
  useEffect(() => {
    const delayDebounceFn = setTimeout(() => {
      if (query) {
        setFreeText(query)
        gotoPage(0)
      } else {
        if (typeof query !== "undefined") {
          // if we delete query string, we reset the table view
          reset()
        }
      }
    }, 400)

    return () => clearTimeout(delayDebounceFn)
  }, [query])

  const handleNext = () => {
    if (canNextPage) {
      paginate(1)
      nextPage()
    }
  }

  const handlePrev = () => {
    if (canPreviousPage) {
      paginate(-1)
      previousPage()
    }
  }

  return (
    <div className="w-full h-full overflow-y-auto">
      <>
        <Table
          filteringOptions={
            <ProductsFilter
              filters={filters}
              submitFilters={setFilters}
              clearFilters={clearFilters}
              tabs={filterTabs}
              onTabClick={setTab}
              activeTab={activeFilterTab}
              onRemoveTab={removeTab}
              onSaveTab={saveTab}
            />
          }
          enableSearch
          handleSearch={setQuery}
          {...getTableProps()}
        >
          {showList ? (
            <>
              <Table.Head>
                {headerGroups?.map((headerGroup) => (
                  <Table.HeadRow {...headerGroup.getHeaderGroupProps()}>
                    {headerGroup.headers.map((col) => (
                      <Table.HeadCell
                        className="min-w-[100px]"
                        {...col.getHeaderProps()}
                      >
                        {col.render("Header")}
                      </Table.HeadCell>
                    ))}
                  </Table.HeadRow>
                ))}
              </Table.Head>
              <LoadingContainer
                isLoading={isLoading || isRefetching || !products}
              >
                <Table.Body {...getTableBodyProps()}>
                  {rows.map((row) => {
                    prepareRow(row)
                    return <ProductRow row={row} />
                  })}
                </Table.Body>
              </LoadingContainer>
            </>
          ) : (
            <LoadingContainer
              isLoading={isLoading || isRefetching || !products}
            >
              <ProductOverview
                products={products}
                toggleListView={setListView}
              />
            </LoadingContainer>
          )}
        </Table>
        <TablePagination
          count={count!}
          limit={limit}
          offset={offs}
          pageSize={offs + rows.length}
          title="Products"
          currentPage={pageIndex + 1}
          pageCount={pageCount}
          nextPage={handleNext}
          prevPage={handlePrev}
          hasNext={canNextPage}
          hasPrev={canPreviousPage}
        />
      </>
    </div>
  )
}
Example #15
Source File: index.tsx    From admin with MIT License 4 votes vote down vote up
OrderTable: React.FC<RouteComponentProps> = () => {
  const location = useLocation()

  const {
    removeTab,
    setTab,
    saveTab,
    availableTabs: filterTabs,
    activeFilterTab,
    reset,
    paginate,
    setFilters,
    filters,
    setQuery: setFreeText,
    queryObject,
    representationObject,
  } = useOrderFilters(location.search, defaultQueryProps)
  const filtersOnLoad = queryObject

  const offs = parseInt(filtersOnLoad?.offset) || 0
  const lim = parseInt(filtersOnLoad.limit) || DEFAULT_PAGE_SIZE

  const [query, setQuery] = useState(filtersOnLoad?.query)
  const [numPages, setNumPages] = useState(0)

  const { orders, isLoading, count } = useAdminOrders(queryObject)

  useEffect(() => {
    const controlledPageCount = Math.ceil(count! / queryObject.limit)
    setNumPages(controlledPageCount)
  }, [orders])

  const [columns] = useOrderTableColums()

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    canPreviousPage,
    canNextPage,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    // Get the state from the instance
    state: { pageIndex },
  } = useTable(
    {
      columns,
      data: orders || [],
      manualPagination: true,
      initialState: {
        pageSize: lim,
        pageIndex: offs / lim,
      },
      pageCount: numPages,
      autoResetPage: false,
    },
    usePagination
  )

  // Debounced search
  useEffect(() => {
    const delayDebounceFn = setTimeout(() => {
      if (query) {
        setFreeText(query)
        gotoPage(0)
      } else {
        // if we delete query string, we reset the table view
        reset()
      }
    }, 400)

    return () => clearTimeout(delayDebounceFn)
  }, [query])

  const handleNext = () => {
    if (canNextPage) {
      paginate(1)
      nextPage()
    }
  }

  const handlePrev = () => {
    if (canPreviousPage) {
      paginate(-1)
      previousPage()
    }
  }

  const updateUrlFromFilter = (obj = {}) => {
    const stringified = qs.stringify(obj)
    window.history.replaceState(`/a/orders`, "", `${`?${stringified}`}`)
  }

  const refreshWithFilters = () => {
    const filterObj = representationObject

    if (isEmpty(filterObj)) {
      updateUrlFromFilter({ offset: 0, limit: DEFAULT_PAGE_SIZE })
    } else {
      updateUrlFromFilter(filterObj)
    }
  }

  const clearFilters = () => {
    reset()
    setQuery("")
  }

  useEffect(() => {
    refreshWithFilters()
  }, [representationObject])

  return (
    <div className="w-full overflow-y-auto flex flex-col justify-between min-h-[300px] h-full ">
      <Table
        filteringOptions={
          <OrderFilters
            filters={filters}
            submitFilters={setFilters}
            clearFilters={clearFilters}
            tabs={filterTabs}
            onTabClick={setTab}
            activeTab={activeFilterTab}
            onRemoveTab={removeTab}
            onSaveTab={saveTab}
          />
        }
        enableSearch
        handleSearch={setQuery}
        searchValue={query}
        {...getTableProps()}
        className={clsx({ ["relative"]: isLoading })}
      >
        <Table.Head>
          {headerGroups?.map((headerGroup, index) => (
            <Table.HeadRow {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((col, headerIndex) => (
                <Table.HeadCell {...col.getHeaderProps()}>
                  {col.render("Header")}
                </Table.HeadCell>
              ))}
            </Table.HeadRow>
          ))}
        </Table.Head>
        {isLoading || !orders ? (
          <div className="flex w-full h-full absolute items-center justify-center mt-10">
            <div className="">
              <Spinner size={"large"} variant={"secondary"} />
            </div>
          </div>
        ) : (
          <Table.Body {...getTableBodyProps()}>
            {rows.map((row) => {
              prepareRow(row)
              return (
                <Table.Row
                  color={"inherit"}
                  linkTo={row.original.id}
                  {...row.getRowProps()}
                  className="group"
                >
                  {row.cells.map((cell, index) => {
                    return cell.render("Cell", { index })
                  })}
                </Table.Row>
              )
            })}
          </Table.Body>
        )}
      </Table>
      <TablePagination
        count={count!}
        limit={queryObject.limit}
        offset={queryObject.offset}
        pageSize={queryObject.offset + rows.length}
        title="Orders"
        currentPage={pageIndex + 1}
        pageCount={pageCount}
        nextPage={handleNext}
        prevPage={handlePrev}
        hasNext={canNextPage}
        hasPrev={canPreviousPage}
      />
    </div>
  )
}
Example #16
Source File: index.tsx    From admin with MIT License 4 votes vote down vote up
DraftOrderTable: React.FC<RouteComponentProps> = () => {
  const location = useLocation()

  const {
    reset,
    paginate,
    setQuery: setFreeText,
    queryObject,
  } = useDraftOrderFilters(location.search, {})

  const filtersOnLoad = queryObject

  const offs = parseInt(filtersOnLoad?.offset) || 0
  const lim = parseInt(filtersOnLoad?.limit) || DEFAULT_PAGE_SIZE

  const [query, setQuery] = useState(filtersOnLoad?.query)
  const [numPages, setNumPages] = useState(0)

  const { draft_orders, isLoading, isRefetching, count } = useAdminDraftOrders(
    queryObject
  )

  useEffect(() => {
    const controlledPageCount = Math.ceil(count! / queryObject.limit)
    setNumPages(controlledPageCount)
  }, [count, queryObject])

  const [columns] = useDraftOrderTableColumns()

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    canPreviousPage,
    canNextPage,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    // Get the state from the instance
    state: { pageIndex },
  } = useTable(
    {
      columns,
      data: draft_orders || [],
      manualPagination: true,
      initialState: {
        pageSize: lim,
        pageIndex: offs / lim,
      },
      pageCount: numPages,
      autoResetPage: false,
    },
    usePagination
  )

  // Debounced search
  useEffect(() => {
    const delayDebounceFn = setTimeout(() => {
      if (query) {
        setFreeText(query)
        gotoPage(0)
      } else {
        // if we delete query string, we reset the table view
        reset()
      }
    }, 400)

    return () => clearTimeout(delayDebounceFn)
  }, [query])

  const handleNext = () => {
    if (canNextPage) {
      paginate(1)
      nextPage()
    }
  }

  const handlePrev = () => {
    if (canPreviousPage) {
      paginate(-1)
      previousPage()
    }
  }

  return (
    <div className="w-full h-full overflow-y-auto flex flex-col justify-between">
      {isLoading || isRefetching || !draft_orders ? (
        <div className="w-full pt-2xlarge flex items-center justify-center">
          <Spinner size={"large"} variant={"secondary"} />
        </div>
      ) : (
        <>
          <Table
            filteringOptions={[]}
            enableSearch
            handleSearch={setQuery}
            searchValue={query}
            {...getTableProps()}
          >
            <Table.Head>
              {headerGroups?.map((headerGroup, index) => (
                <Table.HeadRow {...headerGroup.getHeaderGroupProps()}>
                  {headerGroup.headers.map((col, headerIndex) => (
                    <Table.HeadCell
                      className="w-[100px]"
                      {...col.getHeaderProps()}
                    >
                      {col.render("Header")}
                    </Table.HeadCell>
                  ))}
                </Table.HeadRow>
              ))}
            </Table.Head>
            <Table.Body {...getTableBodyProps()}>
              {rows.map((row) => {
                prepareRow(row)
                return (
                  <Table.Row
                    color={"inherit"}
                    linkTo={`/a/draft-orders/${row.original.id}`}
                    {...row.getRowProps()}
                  >
                    {row.cells.map((cell, index) => {
                      return cell.render("Cell", { index })
                    })}
                  </Table.Row>
                )
              })}
            </Table.Body>
          </Table>
          <TablePagination
            count={count!}
            limit={queryObject.limit}
            offset={queryObject.offset}
            pageSize={queryObject.offset + rows.length}
            title="Draft Orders"
            currentPage={pageIndex + 1}
            pageCount={pageCount}
            nextPage={handleNext}
            prevPage={handlePrev}
            hasNext={canNextPage}
            hasPrev={canPreviousPage}
          />
        </>
      )}
    </div>
  )
}
Example #17
Source File: MdxPageTabs.tsx    From mantine with MIT License 4 votes vote down vote up
export function MdxPageTabs({ body, frontmatter, headings, siblings }: MdxPageProps) {
  const [query, setQuery] = useState('');
  const { classes } = useStyles();
  const mobile = useMediaQuery('(max-width: 500px)');
  const location = useLocation();
  const initialTab = getInitialTab(location.search.replace('?t=', '') || 'docs');
  const hasProps = Array.isArray(frontmatter.props);
  const hasStyles = Array.isArray(frontmatter.styles);

  if (!hasProps && !hasStyles) {
    return null;
  }

  const propsTables = hasProps
    ? frontmatter.props.map((component) => (
        <div key={component}>
          <Title order={2} sx={{ fontWeight: 600 }} mb={20}>
            {component} component props
          </Title>
          <PropsTable key={component} component={component} query={query} />
        </div>
      ))
    : null;

  return (
    <MdxPageBase>
      <Tabs
        variant="outline"
        initialTab={initialTab}
        onTabChange={(index) => {
          const q = getTabQuery(index);
          navigate(q ? `${location.pathname}?t=${q}` : location.pathname, {
            replace: true,
          });
        }}
        classNames={{ tabsList: classes.tabsList, tabsListWrapper: classes.tabsWrapper }}
      >
        <Tab label="Documentation" className={classes.tab}>
          <div
            className={classes.tabContent}
            style={{
              display: 'flex',
              position: 'relative',
              justifyContent: 'space-between',
            }}
          >
            <div className={classes.main}>
              <MDXRenderer>{body}</MDXRenderer>
              <MdxSiblings siblings={siblings} />
            </div>

            <div className={classes.tableOfContents}>
              <TableOfContents headings={headings} withTabs />
            </div>
          </div>
        </Tab>

        {hasProps && (
          <Tab label={mobile ? 'Props' : 'Component props'} className={classes.tab}>
            <div
              style={{ maxWidth: 1178, marginLeft: 'auto', marginRight: 'auto', marginTop: 24 }}
              className={classes.tabContent}
            >
              <TextInput
                autoFocus
                icon={<MagnifyingGlassIcon />}
                placeholder="Search props"
                mb={20}
                value={query}
                onChange={(event) => setQuery(event.currentTarget.value)}
              />
              {propsTables}
            </div>
          </Tab>
        )}

        {hasStyles && (
          <Tab label={mobile ? 'Styles' : 'Styles API'} className={classes.tab}>
            <div
              style={{ maxWidth: 1178, marginLeft: 'auto', marginRight: 'auto', marginTop: 24 }}
              className={classes.tabContent}
            >
              <StylesApi components={frontmatter.styles} />
            </div>
          </Tab>
        )}
      </Tabs>
    </MdxPageBase>
  );
}