Skip to content

Commit

Permalink
[feat] Create Custom Multi-Select Dropdown and Style Seasonal Plantin…
Browse files Browse the repository at this point in the history
…g Guide (#62)

Co-authored-by: Catherine Tan <[email protected]>
  • Loading branch information
kylezryr and ccatherinetan authored Jan 15, 2025
1 parent 0d08e61 commit 3fb2764
Show file tree
Hide file tree
Showing 26 changed files with 943 additions and 252 deletions.
1 change: 0 additions & 1 deletion app/plant-page/my-garden/[userPlantId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ export default function UserPlantPage() {

<Flex $direction="column" $gap="8px">
<H4>Planting Timeline</H4>
{/*add SeasonalColorKey here */}
<PlantCalendarRow
harvestStart={currentPlant.harvest_start}
harvestEnd={currentPlant.harvest_end}
Expand Down
25 changes: 17 additions & 8 deletions app/seasonal-planting-guide/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import React, { useEffect, useState } from 'react';
import { SmallButton } from '@/components/Buttons';
import FilterDropdownMultiple from '@/components/FilterDropdownMultiple';
import FilterDropdownSingle from '@/components/FilterDropdownSingle';
import { PlantCalendarList } from '@/components/PlantCalendarList';
Expand All @@ -15,13 +16,15 @@ import {
seasonOptions,
usStateOptions,
} from '@/utils/dropdownOptions';
import { toTitleCase } from '@/utils/helpers';
import { useProfile } from '@/utils/ProfileProvider';
import {
FilterContainer,
HeaderContainer,
PageContainer,
PageTitle,
StateOptionsContainer,
VerticalSeparator,
} from './styles';

// (static) filter options imported from utils/dropdownOptions
Expand All @@ -39,7 +42,8 @@ export default function SeasonalPlantingGuide() {
const [selectedPlantingType, setSelectedPlantingType] = useState<
DropdownOption<PlantingTypeEnum>[]
>([]);
const [selectedUsState, setSelectedUsState] = useState<string>('');
const [selectedUsState, setSelectedUsState] =
useState<DropdownOption<string> | null>(null);
const [searchTerm, setSearchTerm] = useState<string>('');

const clearFilters = () => {
Expand All @@ -50,7 +54,10 @@ export default function SeasonalPlantingGuide() {

useEffect(() => {
if (profileReady && profileData) {
setSelectedUsState(profileData.us_state);
setSelectedUsState({
label: toTitleCase(profileData.us_state),
value: profileData.us_state,
});
}
}, [profileData, profileReady]);

Expand All @@ -65,14 +72,17 @@ export default function SeasonalPlantingGuide() {
<SearchBar searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
<FilterContainer>
<FilterDropdownSingle
id="usState"
value={selectedUsState}
setStateAction={setSelectedUsState}
placeholder="State"
options={usStateOptions}
disabled={!selectedUsState}
small={true}
/>

{/* vertical bar to separate state and other filters */}
<VerticalSeparator />

<FilterDropdownMultiple
value={selectedGrowingSeason}
setStateAction={setSelectedGrowingSeason}
Expand All @@ -96,24 +106,23 @@ export default function SeasonalPlantingGuide() {
placeholder="Planting Type"
disabled={!selectedUsState}
/>

<button onClick={clearFilters}>Clear filters</button>
<SmallButton $secondaryColor={COLORS.shrub} onClick={clearFilters}>
Clear Filters
</SmallButton>
</FilterContainer>
</HeaderContainer>
{!selectedUsState ? (
<StateOptionsContainer>
<H3 $color={COLORS.shrub}>Choose Your State</H3>
<FilterDropdownSingle
name="usState"
id="usState"
value={selectedUsState}
setStateAction={setSelectedUsState}
placeholder="State"
options={usStateOptions}
/>
</StateOptionsContainer>
) : (
<Box $pl="16px" $pt="12px">
<Box $p="20px">
<SeasonColorKey />
<PlantCalendarList
growingSeasonFilterValue={selectedGrowingSeason}
Expand Down
20 changes: 17 additions & 3 deletions app/seasonal-planting-guide/styles.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import styled from 'styled-components';
import COLORS from '@/styles/colors';

export const PageContainer = styled.div`
display: flex;
Expand All @@ -10,27 +11,33 @@ export const PageContainer = styled.div`
export const HeaderContainer = styled.div`
display: flex;
flex-direction: column;
padding: 2px 24px 20px 24px;
padding: 2px 24px 0 24px;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
background-color: #fff;
position: relative;
z-index: 2;
`;

//TODO: consolidate styling for Filters in view plants and seasonal planting guide
export const FilterContainer = styled.div`
display: flex;
flex-direction: row;
gap: 0.5rem;
gap: 8px;
margin-top: 12px;
margin-bottom: 20px;
position: relative;
overflow-x: auto;
align-items: center;
`;

export const StateOptionsContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
gap: 16px;
flex-grow: 1;
background-color: ${COLORS.glimpse};
`;

export const PageTitle = styled.div`
Expand All @@ -40,3 +47,10 @@ export const PageTitle = styled.div`
gap: 12px;
align-items: center;
`;

export const VerticalSeparator = styled.div`
height: 30px;
width: 1px;
background-color: ${COLORS.lightgray};
flex-shrink: 0;
`;
55 changes: 50 additions & 5 deletions app/view-plants/page.tsx
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,
Expand All @@ -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';
Expand All @@ -35,6 +36,7 @@ import {
AddButtonContainer,
FilterContainer,
HeaderButton,
InfoButton,
NumberSelectedPlants,
NumberSelectedPlantsContainer,
PlantGridContainer,
Expand Down Expand Up @@ -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);
const cardKeyRef = useRef<HTMLDivElement>(null);
const infoButtonRef = useRef<HTMLButtonElement>(null);
const userState = profileData?.us_state ?? null;

const profileAndAuthReady = profileReady && !authLoading;
Expand Down Expand Up @@ -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">
<div style={{ minHeight: '100vh', backgroundColor: 'white' }}>
<TopRowContainer>
<H1 $color={COLORS.shrub} $fontWeight={500}>
View Plants
</H1>
<Flex $direction="row" $gap="10px" $align="center">
<H1 $color={COLORS.shrub} $fontWeight={500}>
View Plants
</H1>
<div style={{ position: 'relative' }}>
<InfoButton
onClick={() => setIsCardKeyOpen(!isCardKeyOpen)}
ref={infoButtonRef}
>
<Icon type="info" />
</InfoButton>
{isCardKeyOpen && (
<div ref={cardKeyRef}>
<PlantCardKey />
</div>
)}
</div>
</Flex>
<SearchBar searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
<FilterContainer>
<FilterDropdownMultiple
Expand Down
10 changes: 10 additions & 0 deletions app/view-plants/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const FilterContainer = styled.div`
gap: 8px;
margin-bottom: 20px;
align-items: center;
overflow-x: auto;
`;

export const TopRowContainer = styled.div`
Expand Down Expand Up @@ -74,3 +75,12 @@ export const NumberSelectedPlants = styled.p`
line-height: 16px;
color: #fff;
`;

export const InfoButton = styled.button`
display: flex;
align-items: center;
justify-content: center;
background: none;
border: none;
cursor: pointer;
`;
46 changes: 0 additions & 46 deletions components/Button.tsx

This file was deleted.

5 changes: 3 additions & 2 deletions components/Buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ export const SmallButton = styled(P3).attrs({ as: 'button' })<ButtonProps>`
${ButtonStyles}
// Unique to Small Button
border-radius: 20px;
min-width: 60px;
height: 24px;
padding: 4px 10px;
min-width: 60px;
flex-shrink: 0; // to prevent Clear Filters from collapsing on overflow
padding: 4px 8px;
`;
Loading

0 comments on commit 3fb2764

Please sign in to comment.