Skip to content

Commit 1039f30

Browse files
Merge branch 'main' into sjp/streamline-joins
2 parents 980ee47 + a18caf7 commit 1039f30

File tree

7 files changed

+237
-219
lines changed

7 files changed

+237
-219
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { Button } from "@cmsgov/design-system"
2+
import type { FormEvent, ChangeEvent } from "react"
3+
import { useTranslation } from "react-i18next"
4+
import classNames from "classnames"
5+
import search from "../pages/Search.module.css"
6+
7+
type Props = {
8+
value: string
9+
onChange: (value: string) => void
10+
onSearch: (query: string) => void
11+
labelKey: string
12+
buttonTextKey: string
13+
isLoading?: boolean
14+
isBackgroundLoading?: boolean
15+
className?: string
16+
}
17+
18+
export const SearchBar = ({
19+
value,
20+
onChange,
21+
onSearch,
22+
labelKey,
23+
buttonTextKey,
24+
isLoading = false,
25+
isBackgroundLoading = false,
26+
className,
27+
}: Props) => {
28+
const { t } = useTranslation()
29+
const inputClass = classNames(search.input, className)
30+
31+
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
32+
e.preventDefault()
33+
onSearch(value)
34+
}
35+
36+
const handleInputChange = (e: ChangeEvent<HTMLInputElement>): void => {
37+
onChange(e.target.value)
38+
}
39+
40+
const showLoadingState = isLoading && !isBackgroundLoading
41+
const isDisabled = value.length < 1 || showLoadingState
42+
43+
return (
44+
<div className="ds-l-row">
45+
<div className="ds-l-col--12 ds-u-padding-bottom--4">
46+
<form onSubmit={handleSubmit}>
47+
<div className="ds-u-clearfix">
48+
<label className="ds-c-label" htmlFor="query">
49+
{t(labelKey)}
50+
</label>
51+
<div className={inputClass}>
52+
<input
53+
className="ds-c-field"
54+
type="text"
55+
name="query"
56+
id="query"
57+
value={value}
58+
onChange={handleInputChange}
59+
/>
60+
<Button type="submit" variation="solid" disabled={isDisabled}>
61+
{showLoadingState ? t("search.searching") : t(buttonTextKey)}
62+
</Button>
63+
</div>
64+
</div>
65+
</form>
66+
</div>
67+
</div>
68+
)
69+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { PaginationCaption } from "./PaginationCaption"
2+
import { Dropdown } from "@cmsgov/design-system"
3+
import { useTranslation } from "react-i18next"
4+
import type { DropdownChangeObject } from "@cmsgov/design-system"
5+
6+
type Props = {
7+
pagination: PaginationState
8+
options: {
9+
value: string
10+
label: string
11+
}[]
12+
value: string
13+
onChange: (value: string) => void
14+
inputLabel: string
15+
}
16+
17+
export const SearchResultsHeader = ({
18+
pagination,
19+
options,
20+
value,
21+
onChange,
22+
inputLabel,
23+
}: Props) => {
24+
const { t } = useTranslation()
25+
26+
const handleSort = (change: DropdownChangeObject): void => {
27+
onChange(change.target.value)
28+
}
29+
30+
return (
31+
<div
32+
style={{
33+
display: "flex",
34+
alignItems: "center",
35+
justifyContent: "space-between",
36+
}}
37+
>
38+
<div style={{ display: "flex", gap: "8px" }}>
39+
<PaginationCaption pagination={pagination} />
40+
</div>
41+
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
42+
{t(inputLabel)}
43+
<Dropdown
44+
label=""
45+
name="sort-dropdown-field"
46+
labelClassName="ds-u-display--none"
47+
options={options}
48+
value={value}
49+
onChange={handleSort}
50+
/>
51+
</div>
52+
</div>
53+
)
54+
}

frontend/src/i18n/en/organizations.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323
"search": {
2424
"title": "Organization search",
25-
"inputLabel": "Name or NPI"
25+
"inputLabel": "Name or NPI",
26+
"button": "Search organizations"
2627
},
2728

2829
"sort": {
@@ -34,5 +35,5 @@
3435
"alert": {
3536
"heading": "Are you looking for an practitioner?",
3637
"body": "Visit the [Practitioner search](/practitioners/search) page."
37-
}
38+
}
3839
}
Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,61 @@
11
{
2-
"npi": "NPI",
3-
4-
"detail": {
5-
"unavailable": "This content is not currently available.",
6-
"update": {
7-
"title": "Are you the practitioner listed?",
8-
"subtitle" : "Learn how to",
9-
"link": "update your information."
10-
},
11-
"about": {
12-
"title": "About",
13-
"name": "Name(s)",
14-
"gender": "Gender",
15-
"deceased": "Deceased",
16-
"status": "Active status"
17-
},
18-
"contact": {
19-
"title": "Contact information",
20-
"address": "Mailing address",
21-
"phone": "Phone",
22-
"fax": "Fax"
23-
},
24-
"identifiers": {
25-
"title": "Identifiers",
26-
"type": "Type",
27-
"number": "Number",
28-
"details": "Details",
29-
"fallback": "No identifiers available"
30-
},
31-
"taxonomy": "Taxonomy",
32-
"organizations": "Organization(s)",
33-
"endpoints": "Endpoint(s)",
34-
"locations": "Locations"
35-
},
2+
"npi": "NPI",
363

37-
"listing": {
38-
"title": "All Practitioners",
39-
"taxonomy": "Primary taxonomy",
40-
"location": "Location"
4+
"detail": {
5+
"unavailable": "This content is not currently available.",
6+
"update": {
7+
"title": "Are you the practitioner listed?",
8+
"subtitle": "Learn how to",
9+
"link": "update your information."
4110
},
42-
43-
"search": {
44-
"title": "Practitioner search",
45-
"inputLabel": "Name or NPI"
11+
"about": {
12+
"title": "About",
13+
"name": "Name(s)",
14+
"gender": "Gender",
15+
"deceased": "Deceased",
16+
"status": "Active status"
4617
},
47-
48-
"sort": {
49-
"by": "Sort by",
50-
"first-asc": "First Name (A-Z)",
51-
"first-desc": "First Name (Z-A)",
52-
"last-asc": "Last Name (A-Z)",
53-
"last-desc": "Last Name (Z-A)"
18+
"contact": {
19+
"title": "Contact information",
20+
"address": "Mailing address",
21+
"phone": "Phone",
22+
"fax": "Fax"
23+
},
24+
"identifiers": {
25+
"title": "Identifiers",
26+
"type": "Type",
27+
"number": "Number",
28+
"details": "Details",
29+
"fallback": "No identifiers available"
5430
},
31+
"taxonomy": "Taxonomy",
32+
"organizations": "Organization(s)",
33+
"endpoints": "Endpoint(s)",
34+
"locations": "Locations"
35+
},
36+
37+
"listing": {
38+
"title": "All Practitioners",
39+
"taxonomy": "Primary taxonomy",
40+
"location": "Location"
41+
},
42+
43+
"search": {
44+
"title": "Practitioner search",
45+
"inputLabel": "Name or NPI",
46+
"button": "Search practitioners"
47+
},
5548

56-
"alert": {
57-
"heading": "Are you looking for an organization?",
58-
"body": "Visit the [Organization search](/organizations/search) page."
59-
}
49+
"sort": {
50+
"by": "Sort by",
51+
"first-asc": "First Name (A-Z)",
52+
"first-desc": "First Name (Z-A)",
53+
"last-asc": "Last Name (A-Z)",
54+
"last-desc": "Last Name (Z-A)"
55+
},
6056

61-
}
57+
"alert": {
58+
"heading": "Are you looking for an organization?",
59+
"body": "Visit the [Organization search](/organizations/search) page."
60+
}
61+
}

frontend/src/i18n/en/search.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"title": "Search the data",
3-
"subtitle": "Search by name or NPI number to see the details of any practitioner or organization in the database.",
4-
"practitioner": "Practitioner search",
5-
"organization": "Organization search"
6-
7-
}
2+
"title": "Search the data",
3+
"subtitle": "Search by name or NPI number to see the details of any practitioner or organization in the database.",
4+
"practitioner": "Practitioner search",
5+
"organization": "Organization search",
6+
"searching": "Searching..."
7+
}

0 commit comments

Comments
 (0)