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

[feat] Create the plantcalendarrow component #46

Merged
merged 19 commits into from
Dec 2, 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
183 changes: 101 additions & 82 deletions app/seasonal-planting-guide/page.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,60 @@
'use client';

import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import FilterDropdownMultiple from '@/components/FilterDropdownMultiple';
import FilterDropdownSingle from '@/components/FilterDropdownSingle';
import { PlantList } from '@/components/PlantList';
import { PlantCalendarList } from '@/components/PlantCalendarList';
import SearchBar from '@/components/SearchBar';
import { DropdownOption } from '@/types/schema';
import COLORS from '@/styles/colors';
import { Box } from '@/styles/containers';
import { H1, H3 } from '@/styles/text';
import { DropdownOption, PlantingTypeEnum, SeasonEnum } from '@/types/schema';
import { useProfile } from '@/utils/ProfileProvider';
import {
FilterContainer,
HeaderContainer,
PageContainer,
PageTitle,
StateOptionsContainer,
} from './styles';

kylezryr marked this conversation as resolved.
Show resolved Hide resolved
export default function SeasonalPlantingGuide() {
const growingSeasonOptions: DropdownOption[] = [
{ label: 'Spring', value: 'SPRING' },
{ label: 'Summer', value: 'SUMMER' },
{ label: 'Fall', value: 'FALL' },
{ label: 'Winter', value: 'WINTER' },
];
const harvestSeasonOptions: DropdownOption[] = [
{ label: 'Spring', value: 'SPRING' },
{ label: 'Summer', value: 'SUMMER' },
{ label: 'Fall', value: 'FALL' },
{ label: 'Winter', value: 'WINTER' },
];
const plantingTypeOptions: DropdownOption[] = [
{ label: 'Start Seeds Indoors', value: 'Start Seeds Indoors' },
{ label: 'Start Seeds Outdoors', value: 'Start Seeds Outdoors' },
{
label: 'Plant Seedlings/Transplant Outdoors',
value: 'Plant Seedlings/Transplant Outdoors',
},
];
const usStateOptions: DropdownOption[] = [
{ label: 'Tennessee', value: 'TENNESSEE' },
{ label: 'Missouri', value: 'MISSOURI' },
];
// Declaring (static) filter options outside so they're not re-rendered
// TODO: Maybe export shared filter options from a centralized file
const growingSeasonOptions: DropdownOption<SeasonEnum>[] = [
{ label: 'Spring', value: 'SPRING' },
{ label: 'Summer', value: 'SUMMER' },
{ label: 'Fall', value: 'FALL' },
{ label: 'Winter', value: 'WINTER' },
];
const harvestSeasonOptions: DropdownOption<SeasonEnum>[] = [
{ label: 'Spring', value: 'SPRING' },
{ label: 'Summer', value: 'SUMMER' },
{ label: 'Fall', value: 'FALL' },
{ label: 'Winter', value: 'WINTER' },
];
const plantingTypeOptions: DropdownOption<PlantingTypeEnum>[] = [
{ label: 'Start Seeds Indoors', value: 'INDOORS' },
{ label: 'Start Seeds Outdoors', value: 'OUTDOORS' },
{
label: 'Plant Seedlings/Transplant Outdoors',
value: 'TRANSPLANT',
},
];
const usStateOptions: DropdownOption[] = [
{ label: 'Tennessee', value: 'TENNESSEE' },
{ label: 'Missouri', value: 'MISSOURI' },
];

export default function SeasonalPlantingGuide() {
const { profileData, profileReady } = useProfile();
const [selectedGrowingSeason, setSelectedGrowingSeason] = useState<
DropdownOption[]
DropdownOption<SeasonEnum>[]
>([]);
const [selectedHarvestSeason, setSelectedHarvestSeason] = useState<
DropdownOption[]
DropdownOption<SeasonEnum>[]
>([]);
const [selectedPlantingType, setSelectedPlantingType] = useState<
DropdownOption[]
DropdownOption<PlantingTypeEnum>[]
>([]);
const [selectedUsState, setSelectedUsState] = useState<string>('');
const [searchTerm, setSearchTerm] = useState<string>('');
Expand All @@ -57,69 +65,80 @@ export default function SeasonalPlantingGuide() {
setSelectedPlantingType([]);
};

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

return (
<PageContainer>
{!selectedUsState ? (
<>
<p>Please select a US state to view planting information.</p>
<StateOptionsContainer>
<FilterDropdownSingle
name="usState"
id="usState"
value={selectedUsState}
setStateAction={setSelectedUsState}
placeholder="US State"
options={usStateOptions}
/>
</StateOptionsContainer>
</>
) : (
<>
<HeaderContainer>
<SearchBar searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
<FilterContainer>
<FilterDropdownSingle
name="usState"
id="usState"
value={selectedUsState}
setStateAction={setSelectedUsState}
placeholder="US State"
options={usStateOptions}
/>

<FilterDropdownMultiple
value={selectedGrowingSeason}
setStateAction={setSelectedGrowingSeason}
options={growingSeasonOptions}
placeholder="Growing Season"
/>
<HeaderContainer>
Copy link
Collaborator

Choose a reason for hiding this comment

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

note: in the future, we can consider refactoring by making the header (including the search bar and filters) into a separate component that takes in a list of filters as props??
it's great as it is now, but this refactor might make it slightly more reusable in /view-plants??? just an idea

<PageTitle>
<H1 $color={COLORS.shrub} $align="left">
Planting Timeline
</H1>
</PageTitle>
<SearchBar searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
<FilterContainer>
<FilterDropdownSingle
id="usState"
value={selectedUsState}
setStateAction={setSelectedUsState}
placeholder="State"
options={usStateOptions}
disabled={!selectedUsState}
/>

<FilterDropdownMultiple
value={selectedHarvestSeason}
setStateAction={setSelectedHarvestSeason}
options={harvestSeasonOptions}
placeholder="Harvest Season"
/>
<FilterDropdownMultiple
value={selectedGrowingSeason}
setStateAction={setSelectedGrowingSeason}
options={growingSeasonOptions}
placeholder="Growing Season"
disabled={!selectedUsState}
/>

<FilterDropdownMultiple
value={selectedPlantingType}
setStateAction={setSelectedPlantingType}
options={plantingTypeOptions}
placeholder="Planting Type"
/>
<FilterDropdownMultiple
value={selectedHarvestSeason}
setStateAction={setSelectedHarvestSeason}
options={harvestSeasonOptions}
placeholder="Harvest Season"
disabled={!selectedUsState}
/>

<button onClick={clearFilters}>Clear filters</button>
</FilterContainer>
</HeaderContainer>
<FilterDropdownMultiple
value={selectedPlantingType}
setStateAction={setSelectedPlantingType}
options={plantingTypeOptions}
placeholder="Planting Type"
disabled={!selectedUsState}
/>

<PlantList
<button onClick={clearFilters}>Clear filters</button>
</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">
<PlantCalendarList
growingSeasonFilterValue={selectedGrowingSeason}
harvestSeasonFilterValue={selectedHarvestSeason}
plantingTypeFilterValue={selectedPlantingType}
usStateFilterValue={selectedUsState}
searchTerm={searchTerm}
/>
</>
</Box>
)}
</PageContainer>
);
Expand Down
23 changes: 20 additions & 3 deletions app/seasonal-planting-guide/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,40 @@ import styled from 'styled-components';
export const PageContainer = styled.div`
display: flex;
flex-direction: column;
gap: 1rem;
min-height: 100vh;
/* width: max-content; */
`;

export const HeaderContainer = styled.div`
display: flex;
flex-direction: column;
gap: 12px;
padding: 2px 24px 20px 24px;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
background-color: #fff;
position: relative;
z-index: 1;
`;

export const FilterContainer = styled.div`
display: flex;
flex-direction: row;
gap: 0.5rem;
margin-top: 12px;
position: relative;
`;

export const StateOptionsContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
`;

export const PageTitle = styled.div`
display: flex;
flex-direction: row;
gap: 2rem;
margin-bottom: 8px;
gap: 12px;
align-items: center;
`;
66 changes: 40 additions & 26 deletions app/view-plants/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ import SearchBar from '@/components/SearchBar';
import COLORS from '@/styles/colors';
import { Box, Flex } from '@/styles/containers';
import { H1 } from '@/styles/text';
import { DropdownOption, OwnedPlant, Plant } from '@/types/schema';
import {
DropdownOption,
OwnedPlant,
Plant,
SeasonEnum,
SunlightEnum,
} from '@/types/schema';
import {
checkDifficulty,
checkGrowingSeason,
Expand All @@ -33,6 +39,26 @@ import {
ViewSelection,
} from './styles';

// Declaring (static) filter options outside so they're not re-rendered
// TODO: Maybe export shared filter options from a centralized file
const sunlightOptions: DropdownOption<SunlightEnum>[] = [
{ label: 'Less than 2 hours', value: 'SHADE' },
{ label: '2-4 hours', value: 'PARTIAL_SHADE' },
{ label: '4-6 hours', value: 'PARTIAL_SUN' },
{ label: '6+ hours', value: 'FULL' },
];
const difficultyOptions: DropdownOption[] = [
{ label: 'Easy', value: 'EASY' },
{ label: 'Moderate', value: 'MODERATE' },
{ label: 'Hard', value: 'HARD' },
];
const growingSeasonOptions: DropdownOption<SeasonEnum>[] = [
{ label: 'Spring', value: 'SPRING' },
{ label: 'Summer', value: 'SUMMER' },
{ label: 'Fall', value: 'FALL' },
{ label: 'Winter', value: 'WINTER' },
];

export default function Page() {
const router = useRouter();
const [viewingOption, setViewingOption] = useState<'myPlants' | 'all'>(
Expand All @@ -43,41 +69,29 @@ export default function Page() {
const [selectedDifficulty, setSelectedDifficulty] = useState<
DropdownOption[]
>([]);
const [selectedSunlight, setSelectedSunlight] = useState<DropdownOption[]>(
[],
);
const [selectedSunlight, setSelectedSunlight] = useState<
DropdownOption<SunlightEnum>[]
>([]);
const [selectedGrowingSeason, setSelectedGrowingSeason] = useState<
DropdownOption[]
DropdownOption<SeasonEnum>[]
>([]);
const [searchTerm, setSearchTerm] = useState<string>('');
const user_id: UUID = '0802d796-ace8-480d-851b-d16293c74a21';
const [selectedPlants, setSelectedPlants] = useState<Plant[]>([]);
const [ownedPlants, setOwnedPlants] = useState<OwnedPlant[]>([]);

// TODO: replace this with state from ProfileContext
const userState = 'TENNESSEE';
const sunlightOptions: DropdownOption[] = [
{ label: 'Less than 2 hours', value: 'SHADE' },
{ label: '2-4 hours', value: 'PARTIAL_SHADE' },
{ label: '4-6 hours', value: 'PARTIAL_SUN' },
{ label: '6+ hours', value: 'FULL' },
];
const difficultyOptions: DropdownOption[] = [
{ label: 'Easy', value: 'EASY' },
{ label: 'Moderate', value: 'MODERATE' },
{ label: 'Hard', value: 'HARD' },
];
const growingSeasonOptions: DropdownOption[] = [
{ label: 'Spring', value: 'SPRING' },
{ label: 'Summer', value: 'SUMMER' },
{ label: 'Fall', value: 'FALL' },
{ label: 'Winter', value: 'WINTER' },
];

// Fetch All Plants
useEffect(() => {
(async () => {
const plantList = await getAllPlants();
const result = plantList.filter(plant => plant.us_state === userState);
// Filter by user's state, since they can only access when onboarded
// TODO: add userState to dependency array?
// Sort alphabetically first
const result = plantList
.filter(plant => plant.us_state === userState)
.sort((a, b) => a.plant_name.localeCompare(b.plant_name));
setPlants(result);
})();
}, []);
Expand Down Expand Up @@ -268,9 +282,9 @@ export default function Page() {
{viewingOption === 'all' && (
<>
<PlantGridContainer>
{filteredPlantList.map((plant, key) => (
{filteredPlantList.map(plant => (
<PlantCard
key={key}
key={plant.id}
plant={plant}
canSelect={inAddMode}
isSelected={selectedPlants.includes(plant)}
Expand Down
Loading