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

[Issue #167] Fix search page string translation #169

Merged
merged 6 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions frontend/src/app/[locale]/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ interface searchParamsTypes {

function Search({ searchParams }: { searchParams: searchParamsTypes }) {
unstable_setRequestLocale("en");
const t = useTranslations("Process");
const t = useTranslations("Search");
const convertedSearchParams = convertSearchParamsToProperTypes(searchParams);
const {
agency,
Expand All @@ -71,7 +71,7 @@ function Search({ searchParams }: { searchParams: searchParamsTypes }) {

return (
<>
<PageSEO title={t("page_title")} description={t("meta_description")} />
<PageSEO title={t("title")} description={t("meta_description")} />
<BetaAlert />
<Breadcrumbs breadcrumbList={SEARCH_CRUMBS} />
<SearchCallToAction />
Expand All @@ -85,25 +85,25 @@ function Search({ searchParams }: { searchParams: searchParamsTypes }) {
<SearchOpportunityStatus query={status} />
<SearchFilterAccordion
filterOptions={fundingOptions}
title="Funding instrument"
title={t("accordion.titles.funding")}
queryParamKey="fundingInstrument"
query={fundingInstrument}
/>
<SearchFilterAccordion
filterOptions={eligibilityOptions}
title="Eligibility"
title={t("accordion.titles.eligibility")}
queryParamKey="eligibility"
query={eligibility}
/>
<SearchFilterAccordion
filterOptions={agencyOptions}
title="Agency"
title={t("accordion.titles.agency")}
queryParamKey="agency"
query={agency}
/>
<SearchFilterAccordion
filterOptions={categoryOptions}
title="Category"
title={t("accordion.titles.category")}
queryParamKey="category"
query={category}
/>
Expand Down
15 changes: 10 additions & 5 deletions frontend/src/components/search/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Icon } from "@trussworks/react-uswds";
import { QueryContext } from "src/app/[locale]/search/QueryProvider";
import { useContext } from "react";
import { useSearchParamUpdater } from "src/hooks/useSearchParamUpdater";
import { useTranslations } from "next-intl";

interface SearchBarProps {
query: string | null | undefined;
Expand All @@ -16,16 +17,20 @@ export default function SearchBar({ query }: SearchBarProps) {
updateQueryParams("", "query", queryTerm, false);
};

const t = useTranslations("Search");

return (
<div className="margin-top-5 margin-bottom-2">
<label
htmlFor="query"
className="font-sans-lg display-block margin-bottom-2"
>
<span className="text-bold">Search terms </span>
<small className="display-inline-block">
Enter keywords, opportunity numbers, or assistance listing numbers
</small>
{t.rich("bar.label", {
strong: (chunks) => <span className="text-bold">{chunks}</span>,
small: (chunks) => (
<small className="display-inline-block">{chunks}</small>
),
})}
</label>
<div className="usa-search usa-search--big" role="search">
<input
Expand All @@ -40,7 +45,7 @@ export default function SearchBar({ query }: SearchBarProps) {
}}
/>
<button className="usa-button" type="submit" onClick={handleSubmit}>
<span className="usa-search__submit-text">Search </span>
<span className="usa-search__submit-text">{t("bar.button")} </span>
<Icon.Search
className="usa-search__submit-icon"
size={4}
Expand Down
11 changes: 7 additions & 4 deletions frontend/src/components/search/SearchCallToAction.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { GridContainer } from "@trussworks/react-uswds";
import React from "react";
import { useTranslations } from "next-intl";

const SearchCallToAction: React.FC = () => {
const t = useTranslations("Search");

return (
<>
{/* <BetaAlert /> */}
<GridContainer>
<h1 className="margin-0 tablet-lg:font-sans-xl desktop-lg:font-sans-2xl">
Search funding opportunities
{t("callToAction.title")}
</h1>
<p className="font-serif-md tablet-lg:font-serif-lg usa-intro margin-top-2">
We’re incrementally improving this experimental search page. How can
we make it easier to discover grants that are right for you? Let us
know at <a href="mailto:simpler@grants.gov">simpler@grants.gov</a>.
{t.rich("callToAction.description", {
mail: (chunks) => <a href="mailto:simpler@grants.gov">{chunks}</a>,
})}
</p>
</GridContainer>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client";
import { useTranslations } from "next-intl";

interface SearchFilterToggleAllProps {
isAllSelected: boolean;
Expand All @@ -13,6 +14,8 @@ const SearchFilterToggleAll: React.FC<SearchFilterToggleAllProps> = ({
isAllSelected,
isNoneSelected,
}) => {
const t = useTranslations("Search");

return (
<div className="grid-row">
<div className="grid-col-fill">
Expand All @@ -24,7 +27,7 @@ const SearchFilterToggleAll: React.FC<SearchFilterToggleAllProps> = ({
}}
disabled={isAllSelected}
>
Select All
{t("filterToggleAll.select")}
</button>
</div>
<div className="grid-col-fill text-right">
Expand All @@ -36,7 +39,7 @@ const SearchFilterToggleAll: React.FC<SearchFilterToggleAllProps> = ({
}}
disabled={isNoneSelected}
>
Clear All
{t("filterToggleAll.clear")}
</button>
</div>
</div>
Expand Down
37 changes: 29 additions & 8 deletions frontend/src/components/search/SearchOpportunityStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Checkbox } from "@trussworks/react-uswds";
import { QueryContext } from "src/app/[locale]/search/QueryProvider";
import { useContext } from "react";
import { useSearchParamUpdater } from "src/hooks/useSearchParamUpdater";
import { useTranslations } from "next-intl";

interface StatusOption {
id: string;
Expand All @@ -14,13 +15,6 @@ interface SearchOpportunityStatusProps {
query: Set<string>;
}

const statusOptions: StatusOption[] = [
{ id: "status-forecasted", label: "Forecasted", value: "forecasted" },
{ id: "status-posted", label: "Posted", value: "posted" },
{ id: "status-closed", label: "Closed", value: "closed" },
{ id: "status-archived", label: "Archived", value: "archived" },
];

export default function SearchOpportunityStatus({
query,
}: SearchOpportunityStatusProps) {
Expand All @@ -33,9 +27,36 @@ export default function SearchOpportunityStatus({
updateQueryParams(updated, "status", queryTerm);
};

const t = useTranslations("Search");

const statusOptions: StatusOption[] = [
{
id: "status-forecasted",
label: t("opportunityStatus.label.forecasted"),
value: "forecasted",
},
{
id: "status-posted",
label: t("opportunityStatus.label.posted"),
value: "posted",
},
{
id: "status-closed",
label: t("opportunityStatus.label.closed"),
value: "closed",
},
{
id: "status-archived",
label: t("opportunityStatus.label.archived"),
value: "archived",
},
];

return (
<>
<h2 className="margin-bottom-1 font-sans-xs">Opportunity status</h2>
<h2 className="margin-bottom-1 font-sans-xs">
{t("opportunityStatus.title")}
</h2>
<div className="grid-row flex-wrap">
{statusOptions.map((option) => {
return (
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/components/search/SearchResultsHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import SearchSortyBy from "./SearchSortBy";
import { QueryContext } from "src/app/[locale]/search/QueryProvider";
import { useContext } from "react";
import { useTranslations } from "next-intl";

export default function SearchResultsHeader({
sortby,
Expand All @@ -23,10 +24,13 @@ export default function SearchResultsHeader({
"tablet-lg:margin-bottom-0",
];
if (loading) gridRowClasses.push("opacity-50");

const t = useTranslations("Search");

return (
<div className="grid-row">
<h2 className={gridRowClasses.join(" ")}>
{total && <>{total} Opportunities</>}
{t("resultsHeader.message", { count: total })}
</h2>
<div className="tablet-lg:grid-col-auto">
<SearchSortyBy
Expand Down
19 changes: 7 additions & 12 deletions frontend/src/components/search/SearchResultsListFetch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import SearchErrorAlert from "src/components/search/error/SearchErrorAlert";
import SearchResultsListItem from "src/components/search/SearchResultsListItem";
import { getSearchFetcher } from "src/services/search/searchfetcher/SearchFetcherUtil";
import { QueryParamData } from "src/services/search/searchfetcher/SearchFetcher";
import { getTranslations } from "next-intl/server";

interface ServerPageProps {
searchParams: QueryParamData;
Expand All @@ -13,6 +14,7 @@ export default async function SearchResultsListFetch({
const searchFetcher = getSearchFetcher();
const searchResults = await searchFetcher.fetchOpportunities(searchParams);
const maxPaginationError = null;
const t = await getTranslations("Search");

if (searchResults.status_code !== 200) {
return <SearchErrorAlert />;
Expand All @@ -21,12 +23,11 @@ export default async function SearchResultsListFetch({
if (searchResults.data.length === 0) {
return (
<div>
<h2>Your search did not return any results.</h2>
<h2>{t("resultsListFetch.title")}</h2>
<ul>
<li>{"Check any terms you've entered for typos"}</li>
<li>Try different keywords</li>
<li>{"Make sure you've selected the right statuses"}</li>
<li>Try resetting filters or selecting fewer options</li>
{t.rich("resultsListFetch.body", {
li: (chunks) => <li>{chunks}</li>,
})}
</ul>
</div>
);
Expand All @@ -35,13 +36,7 @@ export default async function SearchResultsListFetch({
return (
<ul className="usa-list--unstyled">
{/* TODO #1485: show proper USWDS error */}
{maxPaginationError && (
<h4>
{
"You''re trying to access opportunity results that are beyond the last page of data."
}
</h4>
)}
{maxPaginationError && <h4>{t("resultsListFetch.paginationError")}</h4>}
{searchResults.data.map((opportunity) => (
<li key={opportunity?.opportunity_id}>
<SearchResultsListItem opportunity={opportunity} />
Expand Down
21 changes: 12 additions & 9 deletions frontend/src/components/search/SearchResultsListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { AgencyNamyLookup } from "src/utils/search/generateAgencyNameLookup";
import { formatDate } from "src/utils/dateUtil";
import { Opportunity } from "src/types/search/searchResponseTypes";
import { useTranslations } from "next-intl";

interface SearchResultsListItemProps {
opportunity: Opportunity;
Expand All @@ -19,6 +20,8 @@ export default function SearchResultsListItem({
? "https://grants.gov"
: "https://test.grants.gov";

const t = useTranslations("Search");

const metadataBorderClasses = `
display-block
tablet:display-inline-block
Expand Down Expand Up @@ -56,7 +59,7 @@ export default function SearchResultsListItem({
<div className="grid-col tablet:order-1 overflow-hidden font-body-xs">
{opportunity.opportunity_status === "archived" && (
<span className={metadataBorderClasses}>
<strong>Archived:</strong>{" "}
<strong>{t("resultsListItem.status.archived")}</strong>
{opportunity?.summary?.archive_date
? formatDate(opportunity?.summary?.archive_date)
: "--"}
Expand All @@ -66,7 +69,7 @@ export default function SearchResultsListItem({
opportunity?.opportunity_status === "closed") &&
opportunity?.summary?.close_date && (
<span className={metadataBorderClasses}>
<strong>Closed:</strong>{" "}
<strong>{t("resultsListItem.status.closed")}</strong>
{opportunity?.summary?.close_date
? formatDate(opportunity?.summary?.close_date)
: "--"}
Expand All @@ -75,7 +78,7 @@ export default function SearchResultsListItem({
{opportunity?.opportunity_status === "posted" && (
<span className={metadataBorderClasses}>
<span className="usa-tag bg-accent-warm-dark">
<strong>Closing:</strong>{" "}
<strong>{t("resultsListItem.status.posted")}</strong>
<span className="text-no-uppercase">
{opportunity?.summary?.close_date
? formatDate(opportunity?.summary?.close_date)
Expand All @@ -87,20 +90,20 @@ export default function SearchResultsListItem({
{opportunity?.opportunity_status === "forecasted" && (
<span className={metadataBorderClasses}>
<span className="usa-tag">
<strong>Forecasted</strong>
<strong>{t("resultsListItem.status.forecasted")}</strong>
</span>
</span>
)}
<span className={metadataBorderClasses}>
<strong>Posted:</strong>{" "}
<strong>{t("resultsListItem.summary.posted")}</strong>
{opportunity?.summary?.post_date
? formatDate(opportunity?.summary?.post_date)
: "--"}
</span>
</div>
<div className="grid-col tablet:order-3 overflow-hidden font-body-xs">
<span className={metadataBorderClasses}>
<strong>Agency:</strong>{" "}
<strong>{t("resultsListItem.summary.agency")}</strong>
{opportunity?.summary?.agency_name &&
opportunity?.summary?.agency_code &&
agencyNameLookup
Expand All @@ -109,7 +112,7 @@ export default function SearchResultsListItem({
: "--"}
</span>
<span className={metadataBorderClasses}>
<strong>Opportunity Number:</strong>{" "}
<strong>{t("resultsListItem.opportunity_number")}</strong>
{opportunity?.opportunity_number}
</span>
</div>
Expand All @@ -121,15 +124,15 @@ export default function SearchResultsListItem({
<span
className={`${metadataBorderClasses} desktop:display-block text-right desktop:margin-right-0 desktop:padding-right-0`}
>
<strong>Award Ceiling:</strong>{" "}
<strong>{t("resultsListItem.award_ceiling")}</strong>
<span className="desktop:display-block desktop:font-sans-lg text-ls-neg-3 text-right">
${opportunity?.summary?.award_ceiling?.toLocaleString() || "--"}
</span>
</span>
<span
className={`${metadataBorderClasses} desktop:display-block text-right desktop:margin-right-0 desktop:padding-right-0`}
>
<strong>Floor:</strong> $
<strong>{t("resultsListItem.floor")}</strong>
{opportunity?.summary?.award_floor?.toLocaleString() || "--"}
</span>
</div>
Expand Down
Loading
Loading