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

frontend - add clear filter button #5275 #5413

Merged
merged 16 commits into from
Jan 13, 2025

Conversation

graceegal
Copy link
Contributor

@graceegal graceegal commented Dec 30, 2024

closes #5275
part of #5341

Web frontend checklist

  • Formatted my code with yarn format
  • There are no warnings from yarn lint --fix
  • There are no console warnings when running the app
  • Added any new components to storybook
  • Added tests where relevant
  • All tests pass
  • Clicked around my changes running locally and it works
  • Checked Desktop, Mobile and Tablet screen sizes

@graceegal graceegal requested a review from a team December 30, 2024 02:42
@graceegal graceegal self-assigned this Dec 30, 2024
Copy link

vercel bot commented Dec 30, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
couchers ✅ Ready (Inspect) Visit Preview Jan 11, 2025 9:46pm

@nabramow
Copy link
Member

Screenshot 2024-12-29 at 8 15 38 PM

Needs some margin around the right side of the button here. I'd make it the same as the distance between search in this area and this.

@nabramow
Copy link
Member

When I click clear filters, it also clears my selected location. IMO it shouldn't clear location but everything else. But deferring to @jesseallhands what do you think?

Comment on lines 184 to 206
/**
* Checks if filters are applied
*/
useEffect(() => {
const filtersActive =
queryName !== "" ||
lastActiveFilter !== 0 ||
hostingStatusFilter.length !== 0 ||
numberOfGuestFilter !== undefined ||
completeProfileFilter !== false ||
(locationResult?.location.lng !== 0 &&
locationResult?.location.lat !== 0);

setAreFiltersApplied(filtersActive);
}, [
queryName,
lastActiveFilter,
hostingStatusFilter,
numberOfGuestFilter,
completeProfileFilter,
locationResult,
]);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay first of all, this was a great first attempt, and it pretty much works! Well done taking this on as one of your first tickets as honestly the map is confusing even for me!

A few notes on things I'd change due to the approach:

First a caveat - this isn't how I'd ideally do this in i.e. a day job, normally I'd just send an api call to the backend to clear everything and that would return an updated response, which would update the UI.

BUT we cache the result and filter it on the frontend, which is why that doesn't work here.

Given we will refactor the map soon anyway, this is how I'd go about it as a stop gap:

We already have a very similar useEffect to the one you created for wasSearchPerformed in the parent component SearchPage so IMO we want to avoid another one.

Also I'd generally try to keep this functionality in the same place the values are set in useState, which is in SearchPage.

Since you are correctly clearing the values there, we just need a variable to pass down to say "hey the filters changed refilter the user pin results in this component. Your function is already updating the state, which is re-running the api call and regenerating "result", which gets passed down to MapWrapper.

So IMO we just need to tell MapWrapper the search was cleared as the actual functionality is already there.

I'd simplify it a bit like so:

  • In SearchPage create a useState variable areFiltersCleared, setAreFiltersCleared and set it to true as a default value
  • When you run the handleClearFilters function in SearchPage, set this to true
  • In SearchPage, in the useEffect that checks if if (!wasSearchPerformed) create an else to the inner if clause that checks if everything is 0 or undefined, and setAreFiltersCleared false there
  • In MapWrapper, in the useEffect that re-renders users list on map, change wasSearchedPerformed to {wasSearchPerformed || areFilltersCleared)

I thiiiiink that should do it but let me know if not!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thank you so much for the detailed feedback and explanation Nicole! Really appreciate it!

I've made the changes you outlined, however I just want to call out that updating the useEffect that checks if if (!wasSearchPerformed) in SearchPage differed a bit from what you proposed... this was to ensure that the areFiltersCleared state was properly updated all the time, not just upon the first search. LMK if this makes more sense now.

* Clicks on 'clear filters' button
*/
const handleClearFiltersOnClick = () => {
handleClearFilters();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as a standard practice, I'd change the prop name from handleClearFilters to onClearFiltersClick`.

Generally the handle functions update the state in that same component. If passing down to a child component, name it the action it does instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated! That makes sense thanks for the info.

@bakeiro
Copy link
Contributor

bakeiro commented Dec 30, 2024

When I click clear filters, it also clears my selected location. IMO it shouldn't clear location but everything else. But deferring to @jesseallhands what do you think?

The thing is, this is not "clear filters" (AFAIK) this is show all the users, and to do that we need to delete everything (including the location) because we can't apply filters/search a location when we display all the users on the map...

@jesseallhands
Copy link
Contributor

When I click clear filters, it also clears my selected location. IMO it shouldn't clear location but everything else. But deferring to @jesseallhands what do you think?

It should clear location as well, but not reset the map position.

If we don't clear location we still have the problem that users cannot see all of the pins on the map which is one of the main problems we are trying to resolve with this button.

@graceegal
Copy link
Contributor Author

graceegal commented Dec 30, 2024

Screenshot 2024-12-29 at 8 15 38 PM

Needs some margin around the right side of the button here. I'd make it the same as the distance between search in this area and this.

@nabramow hmmm that's weird the border radius is rounded for you. On my vercel preview and on my localhost mine looks like this (with the filter buttons intentionally squashed together but no border radius where they're touching)

UPDATE: I re-ran all of my environments locally and now mine is showing like your screenshot... vercel preview still shows as intended though (weird). I will defer to initial design of equal border radius and margin since it is the most simple fix, unless you say otherwise.

Screenshot 2024-12-30 at 13 27 14
Screenshot 2024-12-30 at 13 27 21

@graceegal
Copy link
Contributor Author

When I click clear filters, it also clears my selected location. IMO it shouldn't clear location but everything else. But deferring to @jesseallhands what do you think?

@nabramow @jesseallhands @bakeiro
updated so that it does reset any location that was set, but does not reset the map position (the current bbox stays the same). LMK if this is the correct functionality yall had in mind!

Comment on lines 289 to 302
const onClearFiltersClick = () => {
const currentBbox = map.current?.getBounds().toArray();
if (currentBbox) {
const bbox: [number, number, number, number] = [
currentBbox[0][0],
currentBbox[0][1],
currentBbox[1][0],
currentBbox[1][1],
];
handleClearFilters(bbox);
} else {
handleClearFilters();
}
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry it's the other way. Name the original function "handleClearFiltersClick", but when you pass it as a prop, name it 'onClickFiltersClick'.

That's because the function is "handling" it, but when you pass it you want to see the action it's doing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aha! Okay just updated all of that. Thank you :)

@jesseallhands
Copy link
Contributor

updated so that it does reset any location that was set, but does not reset the map position (the current bbox stays the same). LMK if this is the correct functionality yall had in mind!

Yes, sounds correct!

I tested it on mobile but it doesn't appear to be working. See video below where you can see the "clear filters" button never is clickable despite a location filter (Berlin) being applied. Also, when I click "search here" the button also is not clickable despite the "search here" filter parameter being applied:

Screen_Recording_20250103_110626_Firefox.mp4

@@ -105,7 +107,9 @@ export default function SearchPage({
>();

const [isFiltersOpen, setIsFiltersOpen] = useState(false);
const [areFiltersCleared, setAreFiltersCleared] = useState(true);
const [areFiltersCleared, setAreFiltersCleared] = useState(
locationResult.name === ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if locationResult is not finished loading? It's risky to make one state variable dependent on another in the same component. Curious why not just set it to true by default?

Copy link
Contributor Author

@graceegal graceegal Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is set to true by default then the clear filters button will be disabled on initial render, even if the map is initially rendered with a location filter (ie: someone searched Berlin from the homepage) which is an issue. I see what you mean about the risk of making one state variable dependent on another though... I am thinking to change it to make it dependent on the locationName prop instead. Does that seem like a good fix?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like locationName and bbox are passed in the props from the parent component to SearchPage. I assume that's coming from the dashboard (please check). If so you could use that instead, something like locationName.length > 0 as the default value.

@@ -160,9 +162,9 @@ export default function SearchPage({
numberOfGuestFilter !== undefined ||
completeProfileFilter !== false ||
queryName !== "" ||
(locationResult.location.lng !== 0 && locationResult.location.lat !== 0);
locationResult.name != "" ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want locationResult.name !== "" here (two equal signs)

setQueryName("");
setLocationResult({
bbox: bbox || [0, 0, 0, 0],
bbox: [390, 82, -173, -66],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these hardcoded numbers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are the hardcoded numbers that set the original map position on initial render, so upon clearing filters I set them back to the same numbers to remain consistent

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh gotcha okay!

@nabramow
Copy link
Member

nabramow commented Jan 8, 2025

@nabramow @jesseallhands Clear filters button functionality should now match what we discussed on the meeting today. LMK if not!

A few other things I noticed while working on this and wanted to address:

  1. SearchResults List Mobile View: On mobile only, SearchResultsList is collapsed down and hidden when no filters are applied (this occurs in 2 situations - when they open the map from dashboard without an initial location search query AND every time that clear filters button is clicked). Is that okay behavior or would you prefer it be shown even when no filters are applied?
  2. LocationAutocomplete Sync Issue: When clearing filters and when a location is searched, there's an inconsistency between two instances of LocationAutocomplete (one in SearchBox and one in FilterDialog). The location input might show different values in each place - for example, SearchBox might still display "London" from an initial Dashboard search while FilterDialog shows empty or a different location. Should this synchronization issue be addressed in this PR or as a separate ticket?

Yeah these are both outstanding issues! David is working on 1 in #5294 and 2 I've come across before. Definitely things we should fix, but they existed before this PR so you don't need to address here.

@@ -81,7 +81,9 @@ export default function SearchPage({
const isMobile = useMediaQuery(theme.breakpoints.down("md"));

// State
const [wasSearchPerformed, setWasSearchPerformed] = useState(false);
const [wasSearchPerformed, setWasSearchPerformed] = useState(
Copy link

@nexagoai nexagoai Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[David here] maybe a boolean it's better than empty string?

Copy link

@nexagoai nexagoai Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like setting the wasSearchPerformed to false can show all the users on the map?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry if I review this late, I've been busy lately 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nexagoai locationName !== "" does return a boolean.

@@ -105,6 +107,9 @@ export default function SearchPage({
>();

const [isFiltersOpen, setIsFiltersOpen] = useState(false);
const [areFiltersCleared, setAreFiltersCleared] = useState(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey David @nexagoai! If it is set to true by default then the clear filters button will be disabled on initial render, even if the map is initially rendered with a location filter (ie: someone searched Berlin from the homepage) which is an issue. That's why it's currently set to a conditional that checks whether it should be true or false

}: mapWrapperProps) {
const { t } = useTranslation([SEARCH]);
const [areClustersLoaded, setAreClustersLoaded] = useState(false);
const [isMapStyleLoaded, setIsMapStyleLoaded] = useState(false);
const [isMapSourceLoaded, setIsMapSourceLoaded] = useState(false);
const previousResult = usePrevious(selectedResult);
const classes = useStyles();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const isMobile = useMediaQuery(theme.breakpoints.down("md"));

Medium here to represent mobile as it doesn't include the size defined. So this would mean "below medium" rather than "medium and below".

@@ -1,5 +1,6 @@
import ReplayIcon from "@mui/icons-material/Replay";
import TuneIcon from "@mui/icons-material/Tune";
import { useMediaQuery, useTheme } from "@mui/material";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than useTheme you can just import our customized theme:

import { theme } from "theme";

@nabramow
Copy link
Member

Okay functionality-wise this is working great for me on both mobile and web. Happy to approve just those two small changes!

@graceegal
Copy link
Contributor Author

graceegal commented Jan 11, 2025

Okay functionality-wise this is working great for me on both mobile and web. Happy to approve just those two small changes!

@nabramow Awesome, thanks! I've made the final 2 updates so should be ready for approval. Note- the vercel deployment failed (for what seemed like no reason just a weird hiccup) so the last 2 commits were just to fix it and have it regenerate the vercel preview (I just moved an import 1 line down and then back again because of linting). All good now though and all checks pass :)

@graceegal graceegal requested a review from nabramow January 11, 2025 22:11
Copy link
Member

@nabramow nabramow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Thanks for your persistence on this one! 🚀

@graceegal graceegal merged commit a670d24 into develop Jan 13, 2025
3 checks passed
@graceegal graceegal deleted the web/feature/map-clear-filter-button branch January 13, 2025 18:19
nabramow added a commit that referenced this pull request Jan 15, 2025
@nabramow nabramow linked an issue Jan 15, 2025 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants