Skip to content
This repository has been archived by the owner on Sep 18, 2024. It is now read-only.

Commit

Permalink
Add search result header into suspense
Browse files Browse the repository at this point in the history
  • Loading branch information
acouch committed Jul 5, 2024
1 parent 9117b1b commit bbfa4eb
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 129 deletions.
40 changes: 32 additions & 8 deletions frontend/src/app/[locale]/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import BetaAlert from "src/components/BetaAlert";
import Breadcrumbs from "src/components/Breadcrumbs";
import Loading from "src/app/[locale]/search/loading";
import PageSEO from "src/components/PageSEO";
import SearchResultsList from "src/components/search/SearchResultList";
import SearchResultsListFetch from "src/components/search/SearchResultsListFetch";
import QueryProvider from "./QueryProvider";
import SearchBar from "src/components/search/SearchBar";
import SearchCallToAction from "src/components/search/SearchCallToAction";
import SearchFilterAccordion from "src/components/search/SearchFilterAccordion/SearchFilterAccordion";
import SearchOpportunityStatus from "src/components/search/SearchOpportunityStatus";
import SearchPagination from "src/components/search/SearchPagination";
import SearchPaginationLoader from "src/components/search/SearchPaginationLoader";
import SearchPaginationFetch from "src/components/search/SearchPaginationFetch";
import SearchResultsHeaderFetch from "src/components/search/SearchResultsHeaderFetch";
import SearchResultsHeader from "src/components/search/SearchResultsHeader";
import withFeatureFlag from "src/hoc/search/withFeatureFlag";
import {
Expand Down Expand Up @@ -108,25 +109,48 @@ function Search({ searchParams }: { searchParams: searchParamsTypes }) {
/>
</div>
<div className="tablet:grid-col-8">
<SearchResultsHeader sortby={sortby} />
<Suspense
key={key}
fallback={
<SearchResultsHeader sortby={sortby} loading={false} />
}
>
<SearchResultsHeaderFetch
sortby={sortby}
queryTerm={query}
searchParams={convertedSearchParams}
/>
</Suspense>
<div className="usa-prose">
<Suspense
key={pager1key}
fallback={<SearchPaginationLoader page={page} />}
fallback={
<SearchPagination
loading={true}
page={page}
query={query}
/>
}
>
<SearchPagination
<SearchPaginationFetch
searchParams={convertedSearchParams}
scroll={false}
/>
</Suspense>
<Suspense key={key} fallback={<Loading />}>
<SearchResultsList searchParams={convertedSearchParams} />
<SearchResultsListFetch searchParams={convertedSearchParams} />
</Suspense>
<Suspense
key={pager2key}
fallback={<SearchPaginationLoader page={page} />}
fallback={
<SearchPagination
loading={true}
page={page}
query={query}
/>
}
>
<SearchPagination
<SearchPaginationFetch
searchParams={convertedSearchParams}
scroll={true}
/>
Expand Down
74 changes: 53 additions & 21 deletions frontend/src/components/search/SearchPagination.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,63 @@
"use server";
import { getSearchFetcher } from "src/services/search/searchfetcher/SearchFetcherUtil";
import { QueryParamData } from "src/services/search/searchfetcher/SearchFetcher";
import SearchPaginationItem from "./SearchPaginationItem";
"use client";
import { Pagination } from "@trussworks/react-uswds";
import { QueryContext } from "src/app/[locale]/search/QueryProvider";
import { useSearchParamUpdater } from "src/hooks/useSearchParamUpdater";
import { useContext } from "react";

export enum PaginationPosition {
Top = "topPagination",
Bottom = "bottomPagination",
}

interface SearchPaginationProps {
searchParams: QueryParamData;
scroll: boolean;
page: number;
query: string | null | undefined;
total?: number | null;
scroll?: boolean;
totalResults?: string;
loading?: boolean;
}

export default async function SearchPagination({
searchParams,
scroll,
const MAX_SLOTS = 7;

export default function SearchPagination({
page,
query,
total = null,
scroll = false,
totalResults = "",
loading = false,
}: SearchPaginationProps) {
const searchFetcher = getSearchFetcher();
const searchResults = await searchFetcher.fetchOpportunities(searchParams);
const totalPages = searchResults.pagination_info?.total_pages;
const totalResults = searchResults.pagination_info?.total_records;
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 updatePage = (page: number) => {
updateTotalPages(String(total));
updateTotalResults(totalResults);
updateQueryParams(String(page), "page", query, scroll);
};

return (
<>
<SearchPaginationItem
total={totalPages}
page={searchParams.page}
query={searchParams.query}
scroll={scroll}
totalResults={String(totalResults)}
<div
style={{
pointerEvents: loading ? "none" : "fill",
opacity: loading ? 0.5 : 1,
}}
>
<Pagination
pathname="/search"
totalPages={pages}
currentPage={page}
maxSlots={MAX_SLOTS}
onClickNext={() => updatePage(page + 1)}
onClickPrevious={() => updatePage(page > 1 ? page - 1 : 0)}
onClickPageNumber={(event: React.MouseEvent, page: number) =>
updatePage(page)
}
/>
</>
</div>
);
}
33 changes: 33 additions & 0 deletions frontend/src/components/search/SearchPaginationFetch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use server";
import { getSearchFetcher } from "src/services/search/searchfetcher/SearchFetcherUtil";
import { QueryParamData } from "src/services/search/searchfetcher/SearchFetcher";
import SearchPagination from "./SearchPagination";

interface SearchPaginationProps {
searchParams: QueryParamData;
// Determines whether clicking on pager items causes a scroll to the top of the search
// results. Created so the bottom pager can scroll.
scroll: boolean;
}

export default async function SearchPaginationFetch({
searchParams,
scroll,
}: SearchPaginationProps) {
const searchFetcher = getSearchFetcher();
const searchResults = await searchFetcher.fetchOpportunities(searchParams);
const totalPages = searchResults.pagination_info?.total_pages;
const totalResults = searchResults.pagination_info?.total_records;

return (
<>
<SearchPagination
total={totalPages}
page={searchParams.page}
query={searchParams.query}
scroll={scroll}
totalResults={String(totalResults)}
/>
</>
);
}
61 changes: 0 additions & 61 deletions frontend/src/components/search/SearchPaginationItem.tsx

This file was deleted.

29 changes: 0 additions & 29 deletions frontend/src/components/search/SearchPaginationLoader.tsx

This file was deleted.

23 changes: 18 additions & 5 deletions frontend/src/components/search/SearchResultsHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,31 @@ import { useContext } from "react";

export default function SearchResultsHeader({
sortby,
totalFetchedResults,
queryTerm,
loading = false,
}: {
sortby: string | null;
totalFetchedResults?: string;
queryTerm?: string | null | undefined;
loading?: boolean;
}) {
const { totalResults, queryTerm } = useContext(QueryContext);

const { totalResults } = useContext(QueryContext);
const total = totalFetchedResults || totalResults;
return (
<div className="grid-row">
<h2 className="tablet-lg:grid-col-fill margin-top-5 tablet-lg:margin-top-2 tablet-lg:margin-bottom-0">
{totalResults.length > 0 && <>{totalResults} Opportunities</>}
<h2
className="tablet-lg:grid-col-fill margin-top-5 tablet-lg:margin-top-2 tablet-lg:margin-bottom-0"
style={{ opacity: loading ? 0.5 : 1 }}
>
{total && <>{total} Opportunities</>}
</h2>
<div className="tablet-lg:grid-col-auto">
<SearchSortyBy sortby={sortby} queryTerm={queryTerm} />
<SearchSortyBy
totalResults={total}
sortby={sortby}
queryTerm={queryTerm}
/>
</div>
</div>
);
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/components/search/SearchResultsHeaderFetch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"use server";
import { getSearchFetcher } from "src/services/search/searchfetcher/SearchFetcherUtil";
import { QueryParamData } from "src/services/search/searchfetcher/SearchFetcher";
import SearchResultsHeader from "./SearchResultsHeader";

export default async function SearchResultsHeaderFetch({
searchParams,
sortby,
queryTerm,
}: {
searchParams: QueryParamData;
sortby: string | null;
queryTerm: string | null | undefined;
}) {
const searchFetcher = getSearchFetcher();
const searchResults = await searchFetcher.fetchOpportunities(searchParams);
const totalResults = searchResults.pagination_info?.total_records;

return (
<SearchResultsHeader
queryTerm={queryTerm}
sortby={sortby}
totalFetchedResults={String(totalResults)}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface ServerPageProps {
searchParams: QueryParamData;
}

export default async function SearchResultsList({
export default async function SearchResultsListFetch({
searchParams,
}: ServerPageProps) {
const searchFetcher = getSearchFetcher();
Expand Down
12 changes: 11 additions & 1 deletion frontend/src/components/search/SearchSortBy.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"use client";
import { Select } from "@trussworks/react-uswds";
import { useSearchParamUpdater } from "src/hooks/useSearchParamUpdater";
import { QueryContext } from "src/app/[locale]/search/QueryProvider";
import { useContext } from "react";

type SortOption = {
label: string;
Expand All @@ -22,13 +25,20 @@ const SORT_OPTIONS: SortOption[] = [
interface SearchSortByProps {
queryTerm: string | null | undefined;
sortby: string | null;
totalResults: string;
}

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

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

Expand Down
Loading

0 comments on commit bbfa4eb

Please sign in to comment.