-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #865 from City-of-Helsinki/UHF-9193_maternity_clin…
…ic_search UHF-9193: maternity and child health clinic search
- Loading branch information
Showing
28 changed files
with
642 additions
and
35 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 1 addition & 8 deletions
9
src/js/react/apps/health-station-search/types/HealthStation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultCard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import CardItem from '@/react/common/Card'; | ||
import CardImage from '@/react/common/CardImage'; | ||
import { MaternityAndChildHealthClinic } from '../types/MaternityAndChildHealthClinic'; | ||
|
||
const ResultCard = ({ address, name, name_override, picture_url, provided_languages, media_as_objects, url }: MaternityAndChildHealthClinic) => { | ||
const title = name_override?.[0] || name?.[0]; | ||
const imageOverride = media_as_objects?.[0].picture_url_override; | ||
|
||
if (!title) { | ||
return null; | ||
} | ||
|
||
let cardImage; | ||
|
||
if (imageOverride) { | ||
cardImage = <CardImage | ||
alt={imageOverride.alt} | ||
photographer={imageOverride.photographer} | ||
src={imageOverride.url} | ||
title={imageOverride.title} | ||
/>; | ||
} | ||
else if (picture_url?.[0]) { | ||
cardImage = <CardImage src={picture_url?.[0]} />; | ||
} | ||
|
||
return ( | ||
<CardItem | ||
cardImage={cardImage} | ||
cardModifierClass='' | ||
cardTitle={title} | ||
cardUrl={url?.[0] || ''} | ||
location={address?.[0]} | ||
locationLabel={Drupal.t('Address', {}, {context: 'React search: location label'})} | ||
cardCategoryTag={provided_languages.includes('sv') ? {'tag': Drupal.t('Service in Swedish', {}, {'context': 'React search: Service in Swedish tag'})} : undefined} | ||
/> | ||
); | ||
}; | ||
|
||
export default ResultCard; |
115 changes: 115 additions & 0 deletions
115
src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultsList.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { SyntheticEvent, createRef, useState } from 'react'; | ||
import { useAtomValue } from 'jotai'; | ||
|
||
import Result from '@/types/Result'; | ||
import Pagination from '@/react/common/Pagination'; | ||
import useScrollToResults from '@/react/common/hooks/useScrollToResults'; | ||
import LoadingOverlay from '@/react/common/LoadingOverlay'; | ||
import ResultsError from '@/react/common/ResultsError'; | ||
import ResultsMap from '@/react/common/ResultsMap'; | ||
import AppSettings from '../enum/AppSettings'; | ||
import { MaternityAndChildHealthClinic } from '../types/MaternityAndChildHealthClinic'; | ||
import ResultCard from './ResultCard'; | ||
import { paramsAtom } from '../store'; | ||
|
||
type ResultsListProps = { | ||
data: any; | ||
error: string|Error; | ||
isLoading: boolean; | ||
isValidating: boolean; | ||
page?: number; | ||
updatePage: Function | ||
} | ||
|
||
const ResultsList = ({ data, error, isLoading, isValidating, page, updatePage }: ResultsListProps) => { | ||
const [useMap, setUseMap] = useState<boolean>(false); | ||
const { size } = AppSettings; | ||
const params = useAtomValue(paramsAtom); | ||
const scrollTarget = createRef<HTMLDivElement>(); | ||
const { sv_only, keyword } = params; | ||
const choices = Boolean(Object.keys(params).length); | ||
useScrollToResults(scrollTarget, choices); | ||
|
||
if (isLoading || isValidating) { | ||
return ( | ||
<div className='hdbt__loading-wrapper'> | ||
<LoadingOverlay /> | ||
</div> | ||
); | ||
} | ||
|
||
if (error) { | ||
return ( | ||
<ResultsError | ||
error={error} | ||
ref={scrollTarget} | ||
/> | ||
); | ||
} | ||
|
||
if (!data?.hits?.hits.length) { | ||
return ( | ||
<div ref={scrollTarget}> | ||
{Drupal.t('No results were found for the criteria you entered. Try changing your search criteria.', {}, { context: 'React search: no search results' })} | ||
</div> | ||
); | ||
} | ||
|
||
const results = data.hits.hits; | ||
const total = keyword && sv_only ? data.hits.hits.length : data.hits.total.value; | ||
const pages = Math.floor(total / size); | ||
const addLastPage = total > size && total % size; | ||
const showPagination = !useMap && (pages > 1 || addLastPage); | ||
const sv_id = results?.[0]?._source?.id?.[0]; | ||
const mapIds = keyword && sv_only && sv_id ? data?.aggregations?.ids?.buckets?.filter((item: any) => item.key === sv_id) : data?.aggregations?.ids?.buckets; | ||
|
||
return ( | ||
<div className='react-search__results'> | ||
<div className='hdbt-search--react__result-top-area'> | ||
{!Number.isNaN(total) && | ||
<h3 className='hdbt-search--react__results--title' ref={scrollTarget}> | ||
{ total > 1 ? | ||
Drupal.t('@clinics clinics', { '@clinics': total }, { context: 'React search: Maternity and child health clinic result count'}) | ||
: | ||
Drupal.t('@clinics clinic', { '@clinics': total }, { context: 'React search: Maternity and child health clinic result count'}) | ||
} | ||
</h3> | ||
} | ||
<div className='hdbt-search--react__results--tablist' role='tablist'> | ||
<button type='button' className='tablist-tab' role='tab' aria-selected={!useMap} aria-controls='hdbt-search--react__results--tabpanel' onClick={() => setUseMap(false)}> | ||
{ Drupal.t('View as a list', {}, {context: 'React search: result display'}) } | ||
</button> | ||
<button type='button' className='tablist-tab' role='tab' aria-selected={useMap} aria-controls='hdbt-search--react__results--tabpanel' onClick={() => setUseMap(true)}> | ||
{ Drupal.t('View in a map', {}, {context: 'React search: result display'}) } | ||
</button> | ||
</div> | ||
</div> | ||
<div id='hdbt-search--react__results--tabpanel' role="tabpanel"> | ||
{ | ||
useMap ? | ||
<ResultsMap ids={mapIds} /> | ||
: | ||
<> | ||
{results.map((hit: Result<MaternityAndChildHealthClinic>) => ( | ||
<ResultCard key={hit._id} {...hit._source} /> | ||
))} | ||
</> | ||
} | ||
{ | ||
showPagination && | ||
<Pagination | ||
currentPage={page || 1} | ||
pages={5} | ||
totalPages={addLastPage ? pages + 1 : pages} | ||
updatePage={(e: SyntheticEvent, nextPage: number) => { | ||
e.preventDefault(); | ||
updatePage(nextPage); | ||
}} | ||
/> | ||
} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ResultsList; |
58 changes: 58 additions & 0 deletions
58
src/js/react/apps/maternity-and-child-health-clinic-search/containers/FormContainer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { Button, Checkbox, TextInput } from 'hds-react'; | ||
import { useAtomValue, useSetAtom } from 'jotai'; | ||
|
||
import { paramsAtom, stagedParamsAtom } from '../store'; | ||
import SearchParams from '../types/SearchParams'; | ||
|
||
type SubmitFormType = HTMLFormElement & { | ||
keyword: HTMLInputElement; | ||
}; | ||
|
||
const ProximityFormContainer = () => { | ||
const stagedParams = useAtomValue(stagedParamsAtom); | ||
const setParams = useSetAtom(paramsAtom); | ||
const setStagedParams = useSetAtom(stagedParamsAtom); | ||
|
||
const onSubmit = (event: React.FormEvent<HTMLFormElement>) => { | ||
event.preventDefault(); | ||
const { keyword, sv_only } = event.target as SubmitFormType; | ||
const params: SearchParams = {}; | ||
|
||
if (keyword.value && keyword.value.length) { | ||
params.keyword = keyword.value; | ||
}; | ||
|
||
params.sv_only = sv_only.checked; | ||
|
||
setParams(params); | ||
}; | ||
|
||
return ( | ||
<form className='hdbt-search--react__form-container' onSubmit={onSubmit}> | ||
<TextInput | ||
className='hdbt-search__filter hdbt-search--react__text-field' | ||
helperText={Drupal.t('Enter the street name and house number', {}, { context: 'React search: street input helper'})} | ||
placeholder={Drupal.t('For example, Kotikatu 1', {}, { context: 'React search: street input helper placeholder'})} | ||
id='keyword' | ||
label={Drupal.t('Home address', {}, { context: 'React search: home address'})} | ||
type='search' | ||
/> | ||
<div className='react-search__checkbox-filter-container'> | ||
<fieldset className='hdbt-search--react__fieldset'> | ||
<Checkbox | ||
className='react-search__checkbox' | ||
checked={stagedParams?.sv_only || false} | ||
id='sv_only' | ||
name='sv_only' | ||
value='sv_only' | ||
onClick={() => setStagedParams({...stagedParams, sv_only: !stagedParams?.sv_only})} | ||
label={Drupal.t('Show the nearest service location where service is available in Swedish.', {}, { context: 'React search: checkbox label swedish'})} | ||
/> | ||
</fieldset> | ||
</div> | ||
<Button className='hdbt-search--react__submit-button' type='submit'>{Drupal.t('Search')}</Button> | ||
</form> | ||
); | ||
}; | ||
|
||
export default ProximityFormContainer; |
24 changes: 24 additions & 0 deletions
24
src/js/react/apps/maternity-and-child-health-clinic-search/containers/ResultsContainer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { useAtomValue, useSetAtom } from 'jotai'; | ||
|
||
import { paramsAtom, updateParamsAtom } from '../store'; | ||
import UseProximityQuery from '../hooks/UseProximityQuery'; | ||
import ResultsList from '../components/ResultsList'; | ||
|
||
const ProximityResultsContainer = () => { | ||
const params = useAtomValue(paramsAtom); | ||
const setParams = useSetAtom(updateParamsAtom); | ||
const updatePage = (page: number) => { | ||
setParams({ | ||
...params, | ||
page | ||
}); | ||
}; | ||
const { data, error, isLoading, isValidating } = UseProximityQuery(params); | ||
const { page } = params; | ||
|
||
return ( | ||
<ResultsList {...{ data, error, isLoading, isValidating, page, updatePage }} /> | ||
); | ||
}; | ||
|
||
export default ProximityResultsContainer; |
20 changes: 20 additions & 0 deletions
20
src/js/react/apps/maternity-and-child-health-clinic-search/containers/SearchContainer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Suspense } from 'react'; | ||
|
||
import LoadingOverlay from '@/react/common/LoadingOverlay'; | ||
import FormContainer from './FormContainer'; | ||
import ResultsContainer from './ResultsContainer'; | ||
|
||
const SearchContainer = () => ( | ||
<Suspense fallback={ | ||
<div className='hdbt__loading-wrapper'> | ||
<LoadingOverlay /> | ||
</div> | ||
}> | ||
<div className='hdbt-search--react'> | ||
<FormContainer /> | ||
<ResultsContainer /> | ||
</div> | ||
</Suspense> | ||
); | ||
|
||
export default SearchContainer; |
7 changes: 7 additions & 0 deletions
7
src/js/react/apps/maternity-and-child-health-clinic-search/enum/AppSettings.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
const AppSettings = { | ||
index: 'maternity_and_child_health_clinic', | ||
locationsBaseUrl: 'https://api.hel.fi/servicemap/v2/administrative_division/?municipality=helsinki&type=maternity_clinic_district&unit_include=id', | ||
size: 10 | ||
}; | ||
|
||
export default AppSettings; |
Oops, something went wrong.