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] Implement Plant Seasonality Filters #17

Merged
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion api/supabase/queries/plantSeasonality.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export async function getPlantSeasonality(
input_state: string,
): Promise<Plant[]> {
const { data, error } = await supabase
.from('plant_seasonality')
.from('plants')
.select('*')
.eq('state', input_state);
kylezryr marked this conversation as resolved.
Show resolved Hide resolved
if (error)
Expand Down
66 changes: 66 additions & 0 deletions app/seasonal-planting-guide/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use client';

import React, { useState } from 'react';
import FilterDropdown from '@/components/FilterDropdown';
import { PlantList } from '@/components/PlantList';

const SeasonalPlantingGuide = () => {
const growingSeasonOptions = ['Spring', 'Summer', 'Fall', 'Winter'];
const harvestSeasonOptions = ['Spring', 'Summer', 'Fall', 'Winter'];
const plantingTypeOptions = [
'Start Seeds Indoors',
'Start Seeds Outdoors',
'Plant Seedlings/Transplant Outdoors',
];

const [growingSeason, setGrowingSeason] = useState<string>('');
const [harvestSeason, setHarvestSeason] = useState<string>('');
const [plantingType, setPlantingType] = useState<string>('');

const clearFilters = () => {
setGrowingSeason('');
setHarvestSeason('');
setPlantingType('');
};

return (
<div>
<FilterDropdown
name="growingSeason"
id="growingSeason"
value={growingSeason}
setStateAction={setGrowingSeason}
options={growingSeasonOptions}
placeholder="Growing Season"
/>

<FilterDropdown
name="harvestSeason"
id="harvestSeason"
value={harvestSeason}
setStateAction={setHarvestSeason}
options={harvestSeasonOptions}
placeholder="Harvest Season"
/>

<FilterDropdown
name="plantingType"
id="plantingType"
value={plantingType}
setStateAction={setPlantingType}
options={plantingTypeOptions}
placeholder="Planting Type"
/>

<button onClick={clearFilters}>Clear filters</button>

<PlantList
growing_season={growingSeason}
harvest_season={harvestSeason}
planting_type={plantingType}
/>
</div>
);
};

export default SeasonalPlantingGuide;
44 changes: 44 additions & 0 deletions components/FilterDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { useState } from 'react';

interface FilterDropdownProps {
name: string;
id: string;
value: string;
setStateAction: React.Dispatch<React.SetStateAction<string>>;
options: string[];
placeholder: string;
}

export default function FilterDropdown(props: FilterDropdownProps) {
kylezryr marked this conversation as resolved.
Show resolved Hide resolved
const [isOpen, setIsOpen] = useState(false);

const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
props.setStateAction(event.target.value);
setIsOpen(false);
};

const handleToggle = () => {
setIsOpen(!isOpen);
};

return (
<select
name={props.name}
id={props.id}
onChange={handleChange}
onClick={handleToggle}
onBlur={() => setIsOpen(false)}
value={props.value}
>
{/*Default placeholder text*/}
<option value="" disabled hidden>
{props.placeholder}
</option>
{props.options.map((option, index) => (
<option key={index} value={option}>
{option}
</option>
))}
</select>
);
}
64 changes: 61 additions & 3 deletions components/PlantList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,79 @@ import React, { useEffect, useState } from 'react';
import { getPlantSeasonality } from '@/api/supabase/queries/plantSeasonality';
import { Plant } from '@/types/schema';

export const PlantList = () => {
interface PlantListProps {
harvest_season: string;
planting_type: string;
growing_season: string;
kylezryr marked this conversation as resolved.
Show resolved Hide resolved
}

export const PlantList = (props: PlantListProps) => {
kylezryr marked this conversation as resolved.
Show resolved Hide resolved
const [plants, setPlants] = useState<Plant[]>([]);
const growingSeasonToMonth = new Map<string, string[]>([
['Spring', ['MARCH', 'APRIL', 'MAY']],
['Summer', ['JUNE', 'JULY', 'AUGUST']],
['Fall', ['SEPTEMBER', 'OCTOBER', 'NOVEMBER']],
['Winter', ['DECEMBER', 'JANUARY', 'FEBRUARY']],
]);

useEffect(() => {
const fetchPlantSeasonality = async () => {
const plantList = await getPlantSeasonality('Tennessee');
// gets plants in Tennessee by default
const plantList = await getPlantSeasonality('TENNESSEE');
kylezryr marked this conversation as resolved.
Show resolved Hide resolved
setPlants(plantList);
};

fetchPlantSeasonality();
}, []);

const checkGrowingSeason = (plant: Plant) => {
if (!props.growing_season) {
return true;
}

const months = growingSeasonToMonth.get(props.growing_season);

return (
months?.includes(plant.indoors_start) ||
months?.includes(plant.indoors_end) ||
months?.includes(plant.outdoors_start) ||
months?.includes(plant.outdoors_end)
Copy link
Collaborator

Choose a reason for hiding this comment

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

i'm wondering if we need to modify the logic here. what if the growing season is Summer, but the indoor time is April-Sept (i.e. it includes all Summer months, but the start and end times are not in the summer months), and outdoors is August-August? I don't think this example would realistically happen, but we also have to account for LATE_MONTH values which aren't included in the growingSeasonToMonth map.
Perhaps we should try to all seasons that the growing season elapses and check if the inputted growing_season is in the list of elapsed seasons.
Perhaps using actual enums might help here? (The type enums that we're using rn are just types and not actual enums oops)

);
};

const checkHarvestSeason = (plant: Plant) => {
if (!props.harvest_season) {
return true;
}

return plant.harvest_season === props.harvest_season.toLocaleUpperCase();
kylezryr marked this conversation as resolved.
Show resolved Hide resolved
};

const checkPlantingType = (plant: Plant) => {
if (!props.planting_type) {
return true;
}

if (props.planting_type === 'Start Seeds Indoors') {
return plant.indoors_start !== null && plant.indoors_start !== null;
} else if (props.planting_type === 'Start Seeds Outdoors') {
return plant.outdoors_start !== null && plant.outdoors_start !== null;
} else if (props.planting_type === 'Plant Seedlings/Transplant Outdoors') {
return plant.transplant_start !== null && plant.transplant_end !== null;
kylezryr marked this conversation as resolved.
Show resolved Hide resolved
}
};

const filterPlantList = (plant: Plant) => {
return (
checkGrowingSeason(plant) &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

i rlly like this structure! it's super clean; great job!
quick note: in the next sprint we'll add a state filter too

checkHarvestSeason(plant) &&
checkPlantingType(plant)
);
};

return (
<div>
{plants.map((plant, key) => (
{plants.filter(filterPlantList).map((plant, key) => (
<div key={key}>{plant.plant_name}</div>
))}
</div>
Expand Down
12 changes: 6 additions & 6 deletions types/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ export interface Plant {
state: string;
harvest_season: Season;
water_num_times_per_week: number;
plant_seed_indoors_start: string;
plant_seed_indoors_end: string;
plant_seed_outdoors_start: string;
plant_seed_outdoors_end: string;
plant_transplant_start: string;
plant_transplant_end: string;
indoors_start: string;
indoors_end: string;
outdoors_start: string;
outdoors_end: string;
transplant_start: string;
transplant_end: string;
harvest_start: string;
harvest_end: string;
water_inches_per_week: number;
Expand Down