Skip to content

Commit

Permalink
[Issue #3522] refine fix for pagination showing with no results (#3533)
Browse files Browse the repository at this point in the history
  • Loading branch information
doug-s-nava authored Jan 21, 2025
1 parent 155184a commit ef5bbda
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 69 deletions.
43 changes: 32 additions & 11 deletions frontend/src/components/search/SearchPagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { QueryContext } from "src/app/[locale]/search/QueryProvider";
import { useSearchParamUpdater } from "src/hooks/useSearchParamUpdater";

import { useContext } from "react";
import { useContext, useEffect } from "react";
import { Pagination } from "@trussworks/react-uswds";

export enum PaginationPosition {
Expand All @@ -14,40 +14,61 @@ export enum PaginationPosition {
interface SearchPaginationProps {
page: number;
query: string | null | undefined;
total?: number | null;
totalPages?: number | null;
scroll?: boolean;
totalResults?: string;
loading?: boolean;
}

const MAX_SLOTS = 7;

// in addition to handling client side page navigation, this client component handles setting client state for:
// - total pages of search results
// - total number of search results
export default function SearchPagination({
page,
query,
total = null,
totalPages = null,
scroll = false,
totalResults = "",
loading = false,
}: SearchPaginationProps) {
const { updateQueryParams } = useSearchParamUpdater();
const { updateTotalPages, updateTotalResults } = useContext(QueryContext);
const { totalPages } = useContext(QueryContext);
// Shows total pages from the query context before it is re-fetched from the API.
const pages = total || Number(totalPages);
const {
updateTotalPages,
updateTotalResults,
totalPages: totalPagesFromQuery,
} = useContext(QueryContext);

// will re-run on each fetch, as we switch from the Suspended version of the component to the live one
useEffect(() => {
if (!loading) {
updateTotalPages(String(totalPages));
}
}, [updateTotalPages, totalPages, loading]);

useEffect(() => {
if (!loading) {
updateTotalResults(String(totalResults));
}
}, [updateTotalResults, totalResults, loading]);

const updatePage = (page: number) => {
updateTotalPages(String(total));
updateTotalResults(totalResults);
updateQueryParams(String(page), "page", query, scroll);
};

// Shows total pages from the query context before it is re-fetched from the API.
// This is only used for display due to race conditions, otherwise totalPages prop
// is the source of truth
const pageCount = totalPages || Number(totalPagesFromQuery);

return (
<div className={`grants-pagination ${loading ? "disabled" : ""}`}>
{totalResults !== "0" && pages > 0 && (
{totalResults !== "0" && pageCount > 0 && (
<Pagination
aria-disabled={loading}
pathname="/search"
totalPages={pages}
totalPages={pageCount}
currentPage={page}
maxSlots={MAX_SLOTS}
onClickNext={() => updatePage(page + 1)}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/search/SearchPaginationFetch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default async function SearchPaginationFetch({
return (
<>
<SearchPagination
total={totalPages}
totalPages={totalPages}
page={page}
query={query}
scroll={scroll}
Expand Down
8 changes: 2 additions & 6 deletions frontend/src/components/search/SearchResultsHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { QueryContext } from "src/app/[locale]/search/QueryProvider";
import { useTranslations } from "next-intl";
import { useContext } from "react";

import SearchSortyBy from "./SearchSortBy";
import SearchSortBy from "./SearchSortBy";

export default function SearchResultsHeader({
sortby,
Expand Down Expand Up @@ -36,11 +36,7 @@ export default function SearchResultsHeader({
{t("resultsHeader.message", { count: total })}
</h2>
<div className="tablet-lg:grid-col-auto">
<SearchSortyBy
totalResults={total}
sortby={sortby}
queryTerm={queryTerm}
/>
<SearchSortBy sortby={sortby} queryTerm={queryTerm} />
</div>
</div>
);
Expand Down
23 changes: 9 additions & 14 deletions frontend/src/components/search/SearchSortBy.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
"use client";

import { QueryContext } from "src/app/[locale]/search/QueryProvider";
import { useSearchParamUpdater } from "src/hooks/useSearchParamUpdater";
import { SortOption } from "src/types/search/searchRequestTypes";

import { useTranslations } from "next-intl";
import { useContext } from "react";
import { useCallback } from "react";
import { Select } from "@trussworks/react-uswds";

interface SearchSortByProps {
queryTerm: string | null | undefined;
sortby: string | null;
totalResults: string;
}

export default function SearchSortBy({
queryTerm,
sortby,
totalResults,
}: SearchSortByProps) {
export default function SearchSortBy({ queryTerm, sortby }: SearchSortByProps) {
const { updateQueryParams } = useSearchParamUpdater();
const { updateTotalResults } = useContext(QueryContext);
const t = useTranslations("Search");

const SORT_OPTIONS: SortOption[] = [
Expand Down Expand Up @@ -52,11 +45,13 @@ export default function SearchSortBy({
},
];

const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
const newValue = event.target.value;
updateTotalResults(totalResults);
updateQueryParams(newValue, "sortby", queryTerm);
};
const handleChange = useCallback(
(event: React.ChangeEvent<HTMLSelectElement>) => {
const newValue = event.target.value;
updateQueryParams(newValue, "sortby", queryTerm);
},
[queryTerm, updateQueryParams],
);

return (
<div id="search-sort-by">
Expand Down
Loading

0 comments on commit ef5bbda

Please sign in to comment.