-
Notifications
You must be signed in to change notification settings - Fork 2
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
[feat] Create Custom Multi-Select Dropdown and Style Seasonal Planting Guide #62
base: main
Are you sure you want to change the base?
Changes from all commits
89dc29f
490fc33
5bd2a96
4e8f4ff
a75868d
95243f6
605bc82
5b001cb
1ec4cb3
e111a96
5c76ed4
46fa944
25773d3
c90c0cf
ef2f1c6
783e913
a34cd15
a0968ae
8a333f0
6605a47
f5b9569
6f031e1
284883c
9e06512
293eccd
954d7de
f41df1b
7906153
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
'use client'; | ||
|
||
import { useEffect, useMemo, useState } from 'react'; | ||
import { useEffect, useMemo, useRef, useState } from 'react'; | ||
import { useRouter } from 'next/navigation'; | ||
import { | ||
getAllPlants, | ||
|
@@ -11,6 +11,7 @@ import { Button, SmallButton } from '@/components/Buttons'; | |
import FilterDropdownMultiple from '@/components/FilterDropdownMultiple'; | ||
import Icon from '@/components/Icon'; | ||
import PlantCard from '@/components/PlantCard'; | ||
import PlantCardKey from '@/components/PlantCardKey'; | ||
import SearchBar from '@/components/SearchBar'; | ||
import CONFIG from '@/lib/configs'; | ||
import COLORS from '@/styles/colors'; | ||
|
@@ -35,6 +36,7 @@ import { | |
AddButtonContainer, | ||
FilterContainer, | ||
HeaderButton, | ||
InfoButton, | ||
NumberSelectedPlants, | ||
NumberSelectedPlantsContainer, | ||
PlantGridContainer, | ||
|
@@ -84,6 +86,9 @@ export default function Page() { | |
const [searchTerm, setSearchTerm] = useState<string>(''); | ||
const [selectedPlants, setSelectedPlants] = useState<Plant[]>([]); | ||
const [ownedPlants, setOwnedPlants] = useState<OwnedPlant[]>([]); | ||
const [isCardKeyOpen, setIsCardKeyOpen] = useState<boolean>(false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. optimization note: each time
for more on re-rendering / how to prevent it: https://www.developerway.com/posts/react-re-renders-guide however, we've already wrapped PlantCard in a memo, so maybe it's chill? something to consider tho! |
||
const cardKeyRef = useRef<HTMLDivElement>(null); | ||
const infoButtonRef = useRef<HTMLButtonElement>(null); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. honestly i think it's ok if we close the card anytime someone clicks outside of the cardKey, so we can probably remove the infoButtonRef? |
||
const userState = profileData?.us_state ?? null; | ||
|
||
const profileAndAuthReady = profileReady && !authLoading; | ||
|
@@ -378,12 +383,52 @@ export default function Page() { | |
|
||
const plantPluralityString = selectedPlants.length > 1 ? 'Plants' : 'Plant'; | ||
|
||
// close plant card key when clicking outside, even on info button | ||
const handleClickOutside = (event: MouseEvent) => { | ||
if ( | ||
cardKeyRef.current && | ||
!cardKeyRef.current.contains(event.target as Node) && | ||
infoButtonRef.current && | ||
!infoButtonRef.current.contains(event.target as Node) | ||
) { | ||
setIsCardKeyOpen(false); | ||
} | ||
}; | ||
|
||
// handle clicking outside PlantCardKey to close it if open | ||
useEffect(() => { | ||
if (isCardKeyOpen) { | ||
document.addEventListener('mousedown', handleClickOutside); | ||
} else { | ||
document.removeEventListener('mousedown', handleClickOutside); | ||
} | ||
|
||
return () => { | ||
document.removeEventListener('mousedown', handleClickOutside); | ||
}; | ||
}, [isCardKeyOpen]); | ||
|
||
return ( | ||
<div id="plantContent"> | ||
<TopRowContainer> | ||
<H1 $color={COLORS.shrub} $fontWeight={500}> | ||
View Plants | ||
</H1> | ||
<Flex $direction="row" $gap="10px" $align="center"> | ||
<H1 $color={COLORS.shrub} $fontWeight={500}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
View Plants | ||
</H1> | ||
<div style={{ position: 'relative' }}> | ||
<InfoButton | ||
onClick={() => setIsCardKeyOpen(!isCardKeyOpen)} | ||
ref={infoButtonRef} | ||
> | ||
<Icon type="info" /> | ||
</InfoButton> | ||
{isCardKeyOpen && ( | ||
<div ref={cardKeyRef}> | ||
<PlantCardKey /> | ||
</div> | ||
Comment on lines
+426
to
+428
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: instead of wrapping PlantCardKey in other div, it might be cleaner to use forwardRef, which would look smth like this:
HOWEVER, apparently, in React 19 (we're using React 18.3) you can directly pass ref as a prop, so maybe we can hold off on this change. |
||
)} | ||
</div> | ||
</Flex> | ||
<SearchBar searchTerm={searchTerm} setSearchTerm={setSearchTerm} /> | ||
<FilterContainer> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In View Plants, the upper/lower borders of the filters are being cutoff. This issue is already addressed in the Planting Timeline page by adding 1px padding to top and bottom. I think this is another argument for consolidating the filters in View Plants and Planting Timeline into a cobined component:
Then we could refactor filteredPlantList like so
this can be done in a separate PR, but I think consolidating the filters into a single component would be cleaner, since it creates a single source of truth and keep styling consistent |
||
<FilterDropdownMultiple | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ooo this is a great handle!
we can probably do smth similar in the /add-details and /onboarding screens, which currently have their height set to 100vh - 60px (subtracting the height of the header), but i think flex-grow is a more elegant solution