Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[front-end] Add ApplyFilters component and integrate into filter Panel #88

Merged
merged 4 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 51 additions & 17 deletions apps/front-end/src/components/map/mapLibre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const openPopup = async (
popupClosedCallback: () => void,
offset?: [number, number],
) => {
if (popup?.isOpen() && popupIx === itemIx) {
console.log(`Popup for item @${itemIx} already open`);
return;
}

console.log(`Open popup for item @${itemIx} ${coordinates}`);

// Shift the popup up a bit so it doesn't cover the marker
Expand Down Expand Up @@ -97,11 +102,11 @@ export const createMap = (
const map = new MapLibreGL.Map({
container: "map-container",
style: `https://api.maptiler.com/maps/streets-v2/style.json?key=${import.meta.env.VITE_MAPTILER_API_KEY}`,
minZoom: 1.1,
minZoom: 1.45,
maxZoom: 18,
bounds: [
[-180, -59.9],
[180, 83],
[-169, -49.3],
[189, 75.6],
],
attributionControl: false,
});
Expand Down Expand Up @@ -172,16 +177,25 @@ export const createMap = (
e: MapLayerMouseEvent,
leafOffset: [number, number],
) => {
const coordinates = feature.geometry.coordinates.slice() as LngLatLike;
const coordinates = feature.geometry.coordinates.slice();
const itemIx = feature.properties?.ix;
openPopup(
map,
itemIx,
coordinates,
popupCreatedCallback,
popupClosedCallback,
leafOffset,
);
map
.easeTo({
center: [
coordinates[0],
getMapCentreLatOffsetted(coordinates[1], map.getZoom()),
],
})
.once("moveend", () => {
openPopup(
map,
itemIx,
coordinates as LngLatLike,
popupCreatedCallback,
popupClosedCallback,
leafOffset,
);
});
},
onLeafHover: (
feature: GeoJSON.Feature<GeoJSON.Point>,
Expand Down Expand Up @@ -218,13 +232,17 @@ export const createMap = (
1,
0,
)) as GeoJSON.Feature<GeoJSON.Point>[];
const zoom = await source.getClusterExpansionZoom(
const clusterExpansionZoom = await source.getClusterExpansionZoom(
clusterFeature.properties?.cluster_id,
);

if (map.getZoom() >= 18 && clusterExpansionZoom > 18) {
// This is a cluster that needs to be spiderfied, so don't need to fly anymore
return;
}
map.flyTo({
center: features[0].geometry.coordinates as LngLatLike,
zoom: zoom ?? undefined,
zoom: clusterExpansionZoom ?? undefined,
speed: 1.5,
});
});
Expand All @@ -237,9 +255,19 @@ export const createMap = (
const coordinates = feature.geometry.coordinates.slice();
const itemIx = feature.properties?.ix;

// fly to a position so that the popup is fully visible
if (popup?.isOpen() && popupIx === itemIx) {
console.log(
`Popup for item @${itemIx} already open so toggle closed`,
);
popup?.remove();
popupIx = undefined;
popup = undefined;
return;
}

// ease to a position so that the popup is fully visible
map
.flyTo({
.easeTo({
center: [
coordinates[0],
getMapCentreLatOffsetted(coordinates[1], map.getZoom()),
Expand Down Expand Up @@ -326,6 +354,8 @@ export const createMap = (
// Remove previous popup - remove listener to prevent looping back and confusing React code
popup?.off("close", popupClosedCallback);
popup?.remove();
popupIx = undefined;
popup = undefined;
flyToThenOpenPopupRecursive();
});

Expand All @@ -337,7 +367,7 @@ export const createMap = (
popup = undefined;
});

map.on("movestart", () => {
map.on("dragstart", () => {
// Close popup when the user moves the map
popup?.remove();
popupIx = undefined;
Expand All @@ -364,6 +394,10 @@ export const createMap = (
}
});

map.on("moveend", () => {
console.log("aaaaa", map.getZoom(), map.getBounds());
});

map.on("zoomstart", () => {
spiderfy.unspiderfyAll();
});
Expand Down
23 changes: 23 additions & 0 deletions apps/front-end/src/components/panel/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import CloseButton from "../common/closeButton/CloseButton";
import AboutPanel from "./aboutPanel/AboutPanel";
import DirectoryPanel from "./directoryPanel/DirectoryPanel";
import SearchPanel from "./searchPanel/SearchPanel";
import ApplyFilters from "./applyFilters/ApplyFilters";
import ResultsPanel from "../panel/resultsPanel/ResultsPanel";
import { useAppDispatch, useAppSelector } from "../../app/hooks";
import {
Expand All @@ -18,7 +19,13 @@ import {
selectPanelOpen,
selectResultsPanelOpen,
openPanel,
openResultsPanel,
} from "./panelSlice";
import {
performSearch,
selectIsFilterActive,
} from "../panel/searchPanel/searchSlice";
import { useTranslation } from "react-i18next";

const StyledPanel = styled(Drawer)(() => ({
display: "flex",
Expand All @@ -36,6 +43,7 @@ const StyledPanel = styled(Drawer)(() => ({
visibility: "visible !important",
overflow: "visible",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.16)",
borderRight: "none",
},
}));

Expand All @@ -52,6 +60,8 @@ const Panel = () => {
const isOpen = useAppSelector(selectPanelOpen);
const selectedTab = useAppSelector(selectSelectedTab);
const resultsOpen = useAppSelector(selectResultsPanelOpen);
const isFilterActive = useAppSelector(selectIsFilterActive);
const { t } = useTranslation();

const isMedium = useMediaQuery("(min-width: 897px)");

Expand Down Expand Up @@ -81,6 +91,12 @@ const Panel = () => {
dispatch(setSelectedTab(0));
};

const onApplyFilters = async () => {
console.log(`Applying filters`);
await dispatch(performSearch());
dispatch(openResultsPanel());
};

return (
<>
{/* Desktop view */}
Expand Down Expand Up @@ -137,6 +153,13 @@ const Panel = () => {
boxShadow: "0 -2px 10px rgba(0, 0, 0, 0.2)",
}}
>
{selectedTab === 2 && (
<ApplyFilters
buttonText={t("apply_filters")}
buttonAction={onApplyFilters}
disabled={!isFilterActive}
/>
)}
<NavBar
onTabChange={handleTabChange}
selectedTab={selectedTab}
Expand Down
38 changes: 38 additions & 0 deletions apps/front-end/src/components/panel/applyFilters/ApplyFilters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Box from "@mui/material/Box";
import { styled } from "@mui/material/styles";
import StandardButton from "../../common/standardButton/StandardButton";

const StyledButtonContainer = styled(Box)(() => ({
width: "100%",
display: "flex",
justifyContent: "center",
position: "sticky",
padding: "var(--spacing-medium)",
backgroundColor: "#fff",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.16)",
margin: 0,
"@media (min-width: 897px)": {
display: "none",
},
}));

interface ApplyFiltersProps {
buttonText: string;
disabled: boolean;
buttonAction: () => void;
}

const ApplyFilters = ({buttonText, buttonAction, disabled}: ApplyFiltersProps) => {
return (
<StyledButtonContainer>
<StandardButton
buttonAction={buttonAction}
disabled={disabled}
>
{buttonText}
</StandardButton>
</StyledButtonContainer>
);
};

export default ApplyFilters;
42 changes: 7 additions & 35 deletions apps/front-end/src/components/panel/searchPanel/SearchPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import Heading from "../heading/Heading";
import ContentPanel from "../contentPanel/ContentPanel";
import SelectBox from "../../common/selectBox/SelectBox";
import SearchBox from "./searchBox/SearchBox";
import StandardButton from "../../common/standardButton/StandardButton";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import { styled } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useAppDispatch, useAppSelector } from "../../../app/hooks";
import {
Expand All @@ -23,20 +20,6 @@ import {
import { selectTotalItemsCount } from "../../map/mapSlice";
import { openResultsPanel } from "../panelSlice";

const StyledButtonContainer = styled(Box)(() => ({
width: "100%",
display: "flex",
justifyContent: "center",
position: "sticky",
padding: "var(--spacing-medium)",
backgroundColor: "rgba(255, 255, 255, 0.25) !important",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.16)",
zIndex: 1,
"@media (min-width: 897px)": {
display: "none",
},
}));

const SearchPanel = () => {
const dispatch = useAppDispatch();
const { t } = useTranslation();
Expand Down Expand Up @@ -65,15 +48,9 @@ const SearchPanel = () => {
if (isMedium) dispatch(openResultsPanel());
};

const onApplyFilters = async () => {
console.log(`Applying filters`);
await dispatch(performSearch());
dispatch(openResultsPanel());
};

const onSubmitSearch = async () => {
console.log(`Searching for '${submittedText}'`);
dispatch(setText(currentText));
console.log(`Searching for '${submittedText}'`);
await dispatch(performSearch());
if (isMedium) dispatch(openResultsPanel());
};
Expand All @@ -87,7 +64,12 @@ const SearchPanel = () => {

return (
<form
style={{ display: "flex", flexDirection: "column", overflow: "hidden" }} // Fix for search filter overflow issue
style={{
display: "flex",
flexDirection: "column",
overflow: "hidden",
paddingBottom: "80px",
}} // Fix for search filter overflow issue
>
<Heading title={t("search")}>
<SearchBox
Expand All @@ -113,16 +95,6 @@ const SearchPanel = () => {
/>
))}
</ContentPanel>
<StyledButtonContainer>
{!isMedium && (
<StandardButton
buttonAction={onApplyFilters}
disabled={!currentText && !isFilterActive}
>
{t("apply_filters")}
</StandardButton>
)}
</StyledButtonContainer>
</form>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ const StyledIconButton = styled(IconButton)(() => ({
interface SearchBoxProps {
value: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
onSubmit: (
e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>,
) => void;
onSubmit: () => void;
clearSearch?: () => void;
}

Expand All @@ -63,8 +61,13 @@ const SearchBox = ({
value={value}
onChange={onChange}
onKeyUp={(event) => {
if (event.key === "Enter") onSubmit(event);
if (event.key === "Enter") {
event.currentTarget.blur();
onSubmit();
}
}}
onBlur={onSubmit}
onSubmit={onSubmit}
autoComplete="off"
placeholder={t("search")}
startAdornment={
Expand Down
Loading