From 6d0dd334c83af71fb080c1cf3a54addfcd404e09 Mon Sep 17 00:00:00 2001 From: Brent Bovenzi Date: Wed, 28 Oct 2020 12:40:55 -0600 Subject: [PATCH 1/5] search more with bounds - Search this area uses bound search - fallback on center/distance search - adjust default zoom/radius/center for tenants - remove distance dropdown --- app/services/stakeholder-best-service.js | 22 ++++- .../components/Results/ResultsContainer.js | 81 +++++++------------ .../src/components/Results/ResultsFilters.js | 47 +---------- client/src/components/Results/ResultsMap.js | 14 +++- client/src/helpers/Configuration.js | 6 +- client/src/hooks/useOrganizationBests.js | 16 +++- .../src/services/stakeholder-best-service.js | 4 + 7 files changed, 81 insertions(+), 109 deletions(-) diff --git a/app/services/stakeholder-best-service.js b/app/services/stakeholder-best-service.js index d56fc8ada..995a703d7 100644 --- a/app/services/stakeholder-best-service.js +++ b/app/services/stakeholder-best-service.js @@ -12,6 +12,9 @@ record has been approved, it will be the most recent version (i.e., have If you make changes to the database structure, be sure to update these methods as well as the corresponding methods in the stakeholder-service.js. +You can search by max/min lat, lng bounds or by a center and radius(distance), +with bounds taking precedence. + */ const booleanEitherClause = (columnName, value) => { @@ -27,13 +30,16 @@ const search = async ({ latitude, longitude, distance, + maxLat, + maxLng, + minLat, + minLng, isInactive, verificationStatusId, tenantId, }) => { const locationClause = buildLocationClause(latitude, longitude); const categoryClause = buildCTEClause(categoryIds, ""); - const sql = `${categoryClause} select s.id, s.name, s.address_1, s.address_2, s.city, s.state, s.zip, s.phone, s.latitude, s.longitude, s.website, s.notes, @@ -69,9 +75,11 @@ const search = async ({ ${buildLoginSelectsClause()} from stakeholder_set as s ${buildLoginJoinsClause()} - where s.tenant_id = ${tenantId} + where s.tenant_id = ${tenantId} ${ - Number(distance) && locationClause + maxLat && maxLng && minLat && minLng + ? buildBounds({ maxLat, maxLng, minLat, minLng }) + : Number(distance) && locationClause ? `AND ${locationClause} < ${distance}` : "" } @@ -83,7 +91,6 @@ const search = async ({ } order by distance `; - // console.log(sql); let stakeholders = []; let categoriesResults = []; var stakeholderResult, stakeholder_ids; @@ -349,6 +356,13 @@ const buildLocationClause = (latitude, longitude) => { return locationClause; }; +const buildBounds = ({ maxLat, maxLng, minLat, minLng }) => { + return ` + AND s.latitude BETWEEN ${minLat} AND ${maxLat} + AND s.longitude BETWEEN ${minLng} AND ${maxLng} + `; +}; + const buildLoginJoinsClause = () => { return ` left join login L1 on s.created_login_id = L1.id diff --git a/client/src/components/Results/ResultsContainer.js b/client/src/components/Results/ResultsContainer.js index be68eb32b..fe36beaaf 100644 --- a/client/src/components/Results/ResultsContainer.js +++ b/client/src/components/Results/ResultsContainer.js @@ -40,27 +40,6 @@ export default function ResultsContainer({ const [selectedStakeholder, onSelectStakeholder] = useState(null); const [isMapView, setIsMapView] = useState(true); - const doSelectStakeholder = useCallback((stakeholder) => { - if (stakeholder && !isMobile) { - setViewport({ - ...viewport, - latitude: stakeholder.latitude, - longitude: stakeholder.longitude, - }); - } - onSelectStakeholder(stakeholder); - }); - - const switchResultsView = () => { - doSelectStakeholder(); - setIsMapView(!isMapView); - }; - - const initialCategories = storage.categoryIds - ? JSON.parse(storage.categoryIds) - : []; - const { categoryIds, toggleCategory } = useCategoryIds(initialCategories); - const initialCoords = { locationName: userSearch ? userSearch.locationName @@ -83,34 +62,41 @@ export default function ResultsContainer({ : originCoordinates.lon, }; - const [radius, setRadius] = useState( - storage?.radius ? JSON.parse(storage.radius) : 5 - ); const [origin, setOrigin] = useState(initialCoords); const [isVerifiedSelected, selectVerified] = useState( storage?.verified ? JSON.parse(storage.verified) : false ); - - const viewPortHash = { - 0: 4, - 1: 13.5, - 2: 12.5, - 3: 12, - 5: 11, - 10: 10, - 20: 9, - 50: 8, - 100: 7, - 500: 4.5, - }; - const [viewport, setViewport] = useState({ - zoom: viewPortHash[radius || 0], + zoom: originCoordinates.zoom, latitude: origin.latitude || JSON.parse(storage.origin).latitude, longitude: origin.longitude || JSON.parse(storage.origin).longitude, logoPosition: "top-left", }); + const initialCategories = storage.categoryIds + ? JSON.parse(storage.categoryIds) + : []; + const { categoryIds, toggleCategory } = useCategoryIds(initialCategories); + + const doSelectStakeholder = useCallback( + (stakeholder) => { + if (stakeholder && !isMobile) { + setViewport({ + ...viewport, + latitude: stakeholder.latitude, + longitude: stakeholder.longitude, + }); + } + onSelectStakeholder(stakeholder); + }, + [viewport, setViewport] + ); + + const switchResultsView = () => { + doSelectStakeholder(); + setIsMapView(!isMapView); + }; + // Component effects useEffect(() => { @@ -155,7 +141,7 @@ export default function ResultsContainer({ }, []); const handleSearch = useCallback( - (e, center) => { + (e, center, bounds) => { if (e) e.preventDefault(); search({ latitude: @@ -168,11 +154,13 @@ export default function ResultsContainer({ origin.longitude || userCoordinates.longitude || JSON.parse(storage.origin).longitude, - radius, categoryIds: categoryIds.length ? categoryIds : DEFAULT_CATEGORIES, isInactive: "either", verificationStatusId: 0, + bounds, + radius: originCoordinates.radius, }); + if (origin.locationName && origin.latitude && origin.longitude) storage.origin = JSON.stringify({ locationName: origin.locationName, @@ -181,11 +169,10 @@ export default function ResultsContainer({ }); storage.categoryIds = JSON.stringify(categoryIds); - storage.radius = JSON.stringify(radius); storage.verified = JSON.stringify(isVerifiedSelected); if (!center) setViewport({ - zoom: viewPortHash[radius || 0], + zoom: originCoordinates.zoom, latitude: origin.latitude, longitude: origin.longitude, }); @@ -198,14 +185,11 @@ export default function ResultsContainer({ origin.longitude, userCoordinates.latitude, userCoordinates.longitude, - radius, categoryIds, isVerifiedSelected, setViewport, doSelectStakeholder, - viewPortHash, storage.categoryIds, - storage.radius, storage.verified, storage.origin, ] @@ -214,8 +198,6 @@ export default function ResultsContainer({ return ( <> diff --git a/client/src/components/Results/ResultsFilters.js b/client/src/components/Results/ResultsFilters.js index acaec61ac..8342e4ece 100644 --- a/client/src/components/Results/ResultsFilters.js +++ b/client/src/components/Results/ResultsFilters.js @@ -1,7 +1,7 @@ import React, { useCallback, useEffect } from "react"; import PropTypes from "prop-types"; import { makeStyles } from "@material-ui/core/styles"; -import { Grid, Select, MenuItem, Button, Box } from "@material-ui/core"; +import { Grid, Button, Box } from "@material-ui/core"; import SearchIcon from "@material-ui/icons/Search"; import { @@ -64,22 +64,15 @@ const useStyles = makeStyles((theme) => ({ }, })); -const distanceInfo = [0, 1, 2, 3, 5, 10, 20, 50, 100, 500]; - const ResultsFilters = ({ handleSearch, isWindowWide, - viewport, - setViewport, origin, setOrigin, - radius, - setRadius, isVerifiedSelected, userCoordinates, categoryIds, toggleCategory, - viewPortHash, isMapView, switchResultsView, }) => { @@ -98,15 +91,7 @@ const ResultsFilters = ({ useEffect(() => { handleSearch(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [origin, radius, categoryIds, isVerifiedSelected, toggleCategory]); - - const handleDistanceChange = (distance) => { - setRadius(distance); - setViewport({ - ...viewport, - zoom: viewPortHash[distance], - }); - }; + }, [origin, categoryIds, isVerifiedSelected, toggleCategory]); return ( - - -