From aaf22c568df8c2df92055a625cd0b2d3b3d5462e Mon Sep 17 00:00:00 2001 From: mitjapotocin Date: Thu, 13 Jan 2022 20:24:51 +0100 Subject: [PATCH] #34: Search, zoom, position in url params --- src/components/DoctorCard/Info/index.js | 12 ++++++++++- src/components/Doctors/index.js | 27 ++++++++++++++++++++++--- src/components/Filters/Search.js | 18 ++++++++++++----- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/components/DoctorCard/Info/index.js b/src/components/DoctorCard/Info/index.js index fe6aa841..144256c1 100644 --- a/src/components/DoctorCard/Info/index.js +++ b/src/components/DoctorCard/Info/index.js @@ -1,5 +1,6 @@ -import { useNavigate, useParams } from 'react-router-dom'; +import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { CardContent, Stack, Typography } from '@mui/material'; +import { useEffect } from 'react'; import { useLeafletContext } from 'context/leafletContext'; @@ -13,6 +14,7 @@ const Info = function Info({ doctor, handleZoom = () => {}, isMarker = false }) const { lng } = useParams(); const { map } = useLeafletContext(); const [type, ageGroup] = doctor.type.split('-'); + const [searchParams, setSearchParams] = useSearchParams(); const navigate = useNavigate(); @@ -22,6 +24,14 @@ const Info = function Info({ doctor, handleZoom = () => {}, isMarker = false }) const path = `/${lng}/${drPath}/${slug}/${instId}`; + useEffect(() => { + setSearchParams({ + query: searchParams.get('query') || '', + zoom: map?.getZoom() || '', + center: map?.getCenter() || '', + }); + }, [setSearchParams, map, searchParams]); + const handleDoctorCard = (event, isReportError) => { event.preventDefault(); diff --git a/src/components/Doctors/index.js b/src/components/Doctors/index.js index 571a4b8d..da8d77ee 100644 --- a/src/components/Doctors/index.js +++ b/src/components/Doctors/index.js @@ -1,5 +1,5 @@ import { useEffect, useMemo, useState } from 'react'; -import { useLocation } from 'react-router-dom'; +import { useLocation, useSearchParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import L from 'leaflet'; @@ -22,6 +22,23 @@ import MapOnlySnackbar from './MapOnlySnackbar'; import * as Styled from './styles'; import { withErrorBoundary } from '../Shared/ErrorBoundary'; +const getCenterFromSearchParams = params => { + if (!params) { + return undefined; + } + + const center = params + .replace(/[A-Za-z()]/g, '') + .split(', ') + .map(n => parseFloat(n, 10)); + + if (center.length === 2 && center.every(n => typeof n === 'number')) { + return center; + } + + return undefined; +}; + const { GEO_LOCATION, BOUNDS } = MAP; const corner1 = L.latLng(...Object.values(BOUNDS.southWest)); @@ -61,8 +78,12 @@ const Doctors = function Doctors({ itemsPerPage = 10, useShow }) { map.flyTo([lat, lon], MAP.MAX_ZOOM); }; - const zoom = state?.zoom ?? MAP.ZOOM; - const center = state?.center ?? MAP.GEO_LOCATION.SL_CENTER; + const [searchParams] = useSearchParams(); + + const searchParamsZoom = !!searchParams.get('zoom') && parseInt(searchParams.get('zoom'), 10); + const searchParamsCenter = getCenterFromSearchParams(searchParams.get('center')); + const zoom = searchParamsZoom || state?.zoom || MAP.ZOOM; + const center = searchParamsCenter || state?.center || MAP.GEO_LOCATION.SL_CENTER; const areDoctors = Array.isArray(doctors) && doctors.length !== 0; const dataLoading = !Array.isArray(doctors); diff --git a/src/components/Filters/Search.js b/src/components/Filters/Search.js index d9c4183f..89e2ceb3 100644 --- a/src/components/Filters/Search.js +++ b/src/components/Filters/Search.js @@ -1,21 +1,29 @@ -import { useLocation } from 'react-router-dom'; - +import { useSearchParams, useLocation } from 'react-router-dom'; import * as Icons from 'components/Shared/Icons'; import { useFilter } from 'context/filterContext'; -import { useState, useRef } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { useDebounce } from 'hooks'; import { t } from 'i18next'; import * as Styled from './styles'; const Search = function Search() { const { state } = useLocation(); - const { setSearchValue } = useFilter(); + const { setSearchValue } = useFilter(); + const [searchParams, setSearchParams] = useSearchParams(); const defaultValue = state?.searchValue ?? ''; - const [value, setValue] = useState(defaultValue); + const [value, setValue] = useState(searchParams.get('query') || defaultValue); const inputRef = useRef(null); + useEffect(() => { + setSearchParams({ + query: value || '', + zoom: searchParams.get('zoom') || '', + center: searchParams.get('center') || '', + }); + }, [setSearchParams, value, searchParams]); + const clearValue = () => { setValue(''); inputRef.current.focus();