Skip to content

Commit 56c9f4f

Browse files
whitneywindWhitney
andauthored
make search details and location sharable (#2492)
Co-authored-by: Whitney <whitney@Whitneys-MBP.fios-router.home>
1 parent 00ca422 commit 56c9f4f

5 files changed

Lines changed: 135 additions & 29 deletions

File tree

client/src/components/FoodSeeker/SearchResults/ResultsFilters/ResultsFilters.jsx

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,19 @@
11
import { Box, Stack, Typography } from "@mui/material";
22
import Grid2 from "@mui/material/Unstable_Grid2";
33
import AddressDropDown from "components/FoodSeeker/AddressDropDown";
4-
import {
5-
FOOD_PANTRY_CATEGORY_ID,
6-
MEAL_PROGRAM_CATEGORY_ID,
7-
} from "constants/stakeholder";
84
import PropTypes from "prop-types";
9-
import { useCallback } from "react";
10-
import * as analytics from "services/analytics";
11-
import CategoryButton from "./CategoryButton";
125
import SwitchViewsButton from "./SwitchViewsButton";
13-
import useFeatureFlag from "hooks/useFeatureFlag";
146
import { TENANT_CONFIG } from "../../../../helpers/Constants";
157
import Geolocate from "./Geolocate";
168
import useBreakpoints from "hooks/useBreakpoints";
179

1810
const ResultsFilters = ({
19-
categoryIds,
20-
toggleCategory,
2111
showList,
2212
toggleShowList,
2313
}) => {
24-
const isMealsSelected = categoryIds.indexOf(MEAL_PROGRAM_CATEGORY_ID) >= 0;
25-
const isPantrySelected = categoryIds.indexOf(FOOD_PANTRY_CATEGORY_ID) >= 0;
2614
const { taglineText } = TENANT_CONFIG;
27-
const hasAdvancedFilterFeatureFlag = useFeatureFlag("advancedFilter");
2815
const { isMobile } = useBreakpoints();
2916

30-
const toggleMeal = useCallback(() => {
31-
toggleCategory(MEAL_PROGRAM_CATEGORY_ID);
32-
analytics.postEvent("toggleMealFilter", {});
33-
}, [toggleCategory]);
34-
35-
const togglePantry = useCallback(() => {
36-
toggleCategory(FOOD_PANTRY_CATEGORY_ID);
37-
analytics.postEvent("togglePantryFilter", {});
38-
}, [toggleCategory]);
39-
4017
return (
4118
<Grid2
4219
container

client/src/components/FoodSeeker/SearchResults/ResultsMap/ResultsMap.jsx

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import {
2929
useSearchCoordinates,
3030
useSelectedOrganization,
3131
useUserCoordinates,
32+
useOrgNameFilter,
33+
useOpenTimeFilter
3234
} from "../../../../appReducer";
3335
import { useMapbox } from "../../../../hooks/useMapbox";
3436
import AdvancedFilters from "../AdvancedFilters/AdvancedFilters";
@@ -47,11 +49,13 @@ import {
4749
} from "constants/stakeholder";
4850
import debounceFn from "debounce-fn";
4951

50-
const ResultsMap = ({ stakeholders, categoryIds, toggleCategory, loading }) => {
52+
const ResultsMap = ({ stakeholders, categoryIds, toggleCategory, loading, initialZoom }) => {
5153
const [markersLoaded, setMarkersLoaded] = useState(false);
5254
const [cursor, setCursor] = useState("auto");
5355
const searchCoordinates = useSearchCoordinates();
5456
const selectedOrganization = useSelectedOrganization();
57+
const orgNameFilter = useOrgNameFilter();
58+
const openTimeFilter = useOpenTimeFilter();
5559
const navigate = useNavigate();
5660
const location = useLocation();
5761
const { isMobile } = useBreakpoints();
@@ -72,7 +76,7 @@ const ResultsMap = ({ stakeholders, categoryIds, toggleCategory, loading }) => {
7276
const [viewport, setViewport] = useState({
7377
latitude,
7478
longitude,
75-
zoom: DEFAULT_VIEWPORT.zoom,
79+
zoom: initialZoom || DEFAULT_VIEWPORT.zoom,
7680
});
7781
const dispatch = useAppDispatch();
7882
const neighborhood = useNeighborhood();
@@ -94,6 +98,7 @@ const ResultsMap = ({ stakeholders, categoryIds, toggleCategory, loading }) => {
9498
...viewport,
9599
latitude: latitude,
96100
longitude,
101+
zoom: initialZoom ? initialZoom : viewport.zoom,
97102
}));
98103
}, [searchCoordinates, longitude, latitude, isMobile]);
99104

@@ -108,6 +113,7 @@ const ResultsMap = ({ stakeholders, categoryIds, toggleCategory, loading }) => {
108113
flyTo({
109114
longitude: startIconCoordinates.longitude,
110115
latitude: startIconCoordinates.latitude,
116+
initialZoom,
111117
});
112118
}, [startIconCoordinates, flyTo, mapRef]);
113119

@@ -318,6 +324,52 @@ const ResultsMap = ({ stakeholders, categoryIds, toggleCategory, loading }) => {
318324
};
319325
}, []);
320326

327+
function updateUrlParams(updates = {}) {
328+
const params = new URLSearchParams(window.location.search);
329+
330+
Object.entries(updates).forEach(([key, value]) => {
331+
if (value === null || value === undefined || value === "") {
332+
params.delete(key);
333+
} else {
334+
params.set(key, value);
335+
}
336+
});
337+
338+
const newUrl = `${window.location.pathname}?${params.toString()}`;
339+
window.history.replaceState(null, "", newUrl);
340+
}
341+
342+
useEffect(() => {
343+
updateUrlParams({
344+
name: orgNameFilter || null,
345+
pantry: isPantrySelected ? "1" : "0",
346+
meal: isMealSelected ? "1" : "0",
347+
openRadio:
348+
openTimeFilter.radio !== "Show All" ? openTimeFilter.radio : null,
349+
openDay:
350+
openTimeFilter.radio === "Customized" ? openTimeFilter.day : null,
351+
openTime:
352+
openTimeFilter.radio === "Customized" ? openTimeFilter.time : null,
353+
});
354+
}, [
355+
orgNameFilter,
356+
isPantrySelected,
357+
isMealSelected,
358+
openTimeFilter,
359+
]);
360+
361+
useEffect(() => {
362+
const timeout = setTimeout(() => {
363+
updateUrlParams({
364+
lat: viewport.latitude?.toFixed(7),
365+
lng: viewport.longitude?.toFixed(7),
366+
zoom: viewport.zoom ? (Math.round(viewport.zoom * 10) / 10).toString() : null,
367+
});
368+
}, 100);
369+
370+
return () => clearTimeout(timeout);
371+
}, [viewport]);
372+
321373
return (
322374
<div
323375
style={{ position: "relative", height: "100%", width: "100%" }}

client/src/components/FoodSeeker/SearchResults/SearchResults.jsx

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import useBreakpoints from "hooks/useBreakpoints";
22
import useCategoryIds from "hooks/useCategoryIds";
33
import useNeighborhoodsGeoJSON from "hooks/useNeighborhoodsGeoJSON";
44
import useOrganizationBests from "hooks/useOrganizationBests";
5+
import { useInitializeCategoryFilter } from "hooks/useInitializeCategoryFilter";
56
import { FOOD_PANTRY_CATEGORY_ID, MEAL_PROGRAM_CATEGORY_ID } from "constants/stakeholder";
67
import { useCallback, useEffect, useState } from "react";
78
import { useLocation } from "react-router-dom";
@@ -24,16 +25,58 @@ const SearchResults = () => {
2425
const { isDesktop } = useBreakpoints();
2526
const { selectAll, loading } = useOrganizationBests();
2627
const { categoryIds, toggleCategory } = useCategoryIds([FOOD_PANTRY_CATEGORY_ID, MEAL_PROGRAM_CATEGORY_ID]);
28+
useInitializeCategoryFilter({ categoryIds, toggleCategory });
2729
const { getGeoJSONById } = useNeighborhoodsGeoJSON();
2830
const [showList, setShowList] = useState(true);
2931
const searchCoordinates = useSearchCoordinates();
3032
const dispatch = useAppDispatch();
3133
const location = useLocation();
32-
const neighborhoodId = new URLSearchParams(location.search).get(
33-
"neighborhood_id"
34-
);
34+
const params = new URLSearchParams(location.search);
35+
const organizationId = params.get("id");
36+
const neighborhoodId = params.get("neighborhood_id");
37+
38+
const lat = parseFloat(params.get("lat") || "");
39+
const lng = parseFloat(params.get("lng") || "");
40+
const initialZoom = parseFloat(params.get("zoom")) || 11;
41+
const longitudeOffset = 0.08 * Math.pow(2, 11 - initialZoom);
42+
43+
const orgNameFilter = params.get("name") || "";
44+
const radio = params.get("openRadio");
45+
const day = params.get("openDay") || "";
46+
const time = params.get("openTime") || "";
47+
48+
useEffect(() => {
49+
try {
50+
if (!isNaN(lat) && !isNaN(lng)) {
51+
dispatch({
52+
type: "SEARCH_COORDINATES_UPDATED",
53+
coordinates: { latitude: lat, longitude: lng + longitudeOffset },
54+
});
55+
}
56+
57+
if (orgNameFilter) {
58+
dispatch({
59+
type: "ORG_NAME_FILTER_UPDATED",
60+
orgNameFilter,
61+
});
62+
}
63+
64+
if (radio && radio !== "Show All") {
65+
dispatch({
66+
type: "OPEN_TIME_FILTER_UPDATED",
67+
openTimeFilter: {
68+
radio,
69+
day,
70+
time,
71+
},
72+
});
73+
}
74+
} catch(err) {
75+
console.error(err)
76+
}
77+
}, []);
78+
3579
const stakeholders = useStakeholders();
36-
const organizationId = new URLSearchParams(location.search).get("id");
3780
const positionDraggable = usePosition();
3881

3982
useEffect(() => {
@@ -175,6 +218,7 @@ const SearchResults = () => {
175218
categoryIds={categoryIds}
176219
toggleCategory={toggleCategory}
177220
loading={loading}
221+
initialZoom={initialZoom}
178222
/>
179223
) : (
180224
<Mobile showList={showList} filters={filters} map={map} list={list} />

client/src/components/FoodSeeker/SearchResults/layouts/Desktop.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const DesktopLayout = ({
1616
categoryIds,
1717
toggleCategory,
1818
loading,
19+
initialZoom,
1920
}) => {
2021
const isFilterPanelOpen = useFilterPanel();
2122
const isListPanelOpen = useListPanel();
@@ -116,6 +117,7 @@ const DesktopLayout = ({
116117
categoryIds={categoryIds}
117118
toggleCategory={toggleCategory}
118119
loading={loading}
120+
initialZoom={initialZoom}
119121
/>
120122
</Box>
121123
</Box>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useEffect } from "react";
2+
import { useLocation } from "react-router-dom";
3+
import {
4+
FOOD_PANTRY_CATEGORY_ID,
5+
MEAL_PROGRAM_CATEGORY_ID,
6+
} from "constants/stakeholder";
7+
8+
type Props = {
9+
categoryIds: number[];
10+
toggleCategory: (id: number) => void;
11+
};
12+
13+
export const useInitializeCategoryFilter = ({
14+
categoryIds,
15+
toggleCategory,
16+
}: Props) => {
17+
const location = useLocation();
18+
19+
useEffect(() => {
20+
const params = new URLSearchParams(location.search);
21+
const pantryParam = params.get("pantry");
22+
const mealParam = params.get("meal");
23+
24+
if (pantryParam === "0" && categoryIds.includes(FOOD_PANTRY_CATEGORY_ID)) {
25+
toggleCategory(FOOD_PANTRY_CATEGORY_ID);
26+
}
27+
if (mealParam === "0" && categoryIds.includes(MEAL_PROGRAM_CATEGORY_ID)) {
28+
toggleCategory(MEAL_PROGRAM_CATEGORY_ID);
29+
}
30+
}, []);
31+
};

0 commit comments

Comments
 (0)