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] profile context integration with view plants and add details #63

Merged
Merged
167 changes: 81 additions & 86 deletions app/add-details/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,28 @@

import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { UUID } from 'crypto';
import { insertUserPlants } from '@/api/supabase/queries/userPlants';
import PlantDetails from '@/components/PlantDetails';
import { Plant, UserPlant } from '@/types/schema';

const plants: Plant[] = [
{
id: 'cfed129c-1cdf-4089-89d2-83ae2fb2f83d',
plant_name: 'cabbage',
us_state: 'string',
harvest_season: 'SPRING',
water_frequency: 'string',
weeding_frequency: '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',
beginner_friendly: true,
plant_tips: 'string',
img: 'string',
difficulty_level: 'HARD',
sunlight_min_hours: 1,
sunlight_max_hours: 1,
},
{
id: '8f25fca8-6e86-486b-9a2b-79f68efa3658',
plant_name: 'tomato',
us_state: 'string',
harvest_season: 'SPRING',
water_frequency: 'string',
weeding_frequency: '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',
beginner_friendly: true,
plant_tips: 'string',
img: 'string',
difficulty_level: 'HARD',
sunlight_min_hours: 1,
sunlight_max_hours: 1,
},
];
const user_id: UUID = '0802d796-ace8-480d-851b-d16293c74a21';
import COLORS from '@/styles/colors';
import { Flex } from '@/styles/containers';
import { H1, P1 } from '@/styles/text';
import { UserPlant } from '@/types/schema';
import { useAuth } from '@/utils/AuthProvider';
import { useProfile } from '@/utils/ProfileProvider';
import { ButtonDiv, FooterButton, MoveButton } from './styles';

export default function Home() {
const { profileData, profileReady, plantsToAdd } = useProfile();
const { userId } = useAuth();
const router = useRouter();

if (profileReady && !profileData) {
router.push('/view-plants');
Copy link
Collaborator

Choose a reason for hiding this comment

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

note: we should replace all routes with CONFIG
e.g.

import CONFIG from '@/lib/configs';
<Link href={CONFIG.login}>Login</Link>

}
const [currentIndex, setCurrentIndex] = useState<number>(1);
const [details, setDetails] = useState<Partial<UserPlant>[]>(
plants.map(plant => ({ plant_id: plant.id, user_id: user_id })),
plantsToAdd.map(plant => ({ plant_id: plant.id, user_id: userId! })),
);
const router = useRouter();

const getDefaultDate = () => new Date().toISOString().substring(0, 10);
Copy link
Collaborator

Choose a reason for hiding this comment

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

note: this date is a little funky. it's 1:48am 12/13, but the plant i just added says 12/12.

Perhaps we should look into other date formatting options e.g. toLocaleDateString() and set it to US Eastern Time, since that's where users will be.


Expand All @@ -71,28 +34,24 @@ export default function Home() {
// Set curr date in details to default date if not on submission page
if (
(!currentDetail || !currentDetail.date_added) &&
currentIndex <= plants.length
currentIndex <= plantsToAdd.length
) {
updateInput('date_added', getDefaultDate());
}
// For valid moves, move to next page
if (
steps !== 0 &&
currentIndex + steps > 0 &&
currentIndex + steps <= plants.length + 1
currentIndex + steps <= plantsToAdd.length + 1
) {
setCurrentIndex(prevIndex => prevIndex + steps);
}
}

function disableNext() {
// disable next if planting type is "SELECT" or undefined
return !(
details[currentIndex - 1].planting_type
// requires refactor of details to ensure that planting_type is PlantingTypeEnum
// && details[currentIndex - 1].planting_type !== 'SELECT'
);
}
// disable next if planting type not selected (undefined)
const disableNext =
currentIndex <= plantsToAdd.length &&
!details[currentIndex - 1].planting_type;

function updateInput(field: string, value: string) {
const updatedDetails = [...details];
Expand All @@ -102,38 +61,74 @@ export default function Home() {
};
setDetails(updatedDetails);
}

// const handleSubmit = async () => {
// try {
// await insertUserPlants(userId!, details);
// router.push('/view-plants');
// } catch (error) {
// console.error('Error inserting user plants:', error);
// // Optionally, add user-facing error handling
// }
// };
async function updateDB() {
await insertUserPlants(user_id, details);
await insertUserPlants(userId!, details);
router.push('/view-plants');
}

return (
<div>
{currentIndex !== plants.length + 1 && (
<div>
<PlantDetails
plant={plants[currentIndex - 1]}
date={details[currentIndex - 1].date_added || getDefaultDate()}
plantingType={details[currentIndex - 1].planting_type || 'SELECT'}
onDateChange={date => updateInput('date_added', date)}
onPlantingTypeChange={type => updateInput('planting_type', type)}
/>
<button onClick={() => move(-1)}>Back</button>
<p>
{currentIndex} / {plants.length}
</p>
<button disabled={disableNext()} onClick={() => move(1)}>
Next
</button>
</div>
<>
{currentIndex !== plantsToAdd.length + 1 && (
<Flex $direction="column" $justify="between">
<Flex $direction="column" $justify="start">
<Flex $gap="16px" $direction="column" $textAlign="center">
<H1 $color={COLORS.shrub}>Add Plant Details</H1>
<P1 $color={COLORS.midgray}>
{currentIndex} / {plantsToAdd.length}
</P1>
</Flex>
<PlantDetails
plant={plantsToAdd[currentIndex - 1]}
date={details[currentIndex - 1].date_added || getDefaultDate()}
plantingType={details[currentIndex - 1].planting_type || 'SELECT'}
onDateChange={date => updateInput('date_added', date)}
onPlantingTypeChange={type => updateInput('planting_type', type)}
/>
</Flex>
<FooterButton>
<ButtonDiv>
{currentIndex > 1 && (
<MoveButton
type="button"
onClick={() => move(-1)}
$secondaryColor={COLORS.shrub}
>
Back
</MoveButton>
)}

<MoveButton
type="button"
disabled={disableNext}
onClick={() => move(1)}
$primaryColor={disableNext ? COLORS.midgray : COLORS.shrub}
$secondaryColor="white"
>
Next
</MoveButton>
</ButtonDiv>
</FooterButton>
</Flex>
)}
{currentIndex === plants.length + 1 && (
{currentIndex === plantsToAdd.length + 1 && (
<div>
<button onClick={() => move(-1)}>Back</button>
<button onClick={updateDB}>Submit</button>
<button type="button" onClick={() => move(-1)}>
Back
</button>
<button type="button" onClick={updateDB}>
Submit
</button>
</div>
)}
</div>
</>
);
}
34 changes: 34 additions & 0 deletions app/add-details/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import styled from 'styled-components';
import { SmallRoundedButton } from '@/components/Button';

export const MoveButton = styled(SmallRoundedButton)`
border: 1px solid;
font-family: inherit;
margin-bottom: 10px;
width: 170px;
height: 50px;
font-size: 15px;
font-style: normal;
font-weight: 400;
line-height: normal;
`;
export const FooterButton = styled.div`
display: flex;
flex-direction: row;
justify-content: end;
width: 100%;
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
padding: 24px;
`;

export const ButtonDiv = styled.div`
display: flex;
width: 100%;
justify-content: space-between;
&:has(:only-child) {
justify-content: flex-end;
}
`;
16 changes: 15 additions & 1 deletion app/plant-page/all-plants/[plantId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import PlantCareDescription from '@/components/PlantCareDescription';
import { Flex } from '@/styles/containers';
import { H4 } from '@/styles/text';
import { Plant } from '@/types/schema';
import { useProfile } from '@/utils/ProfileProvider';
import {
BackButton,
ButtonWrapper,
Expand All @@ -29,13 +30,23 @@ export default function GeneralPlantPage() {
const params = useParams();
const plantId: UUID = params.plantId as UUID;
const [currentPlant, setCurrentPlant] = useState<Plant>();
const { profileReady, profileData, setPlantsToAdd } = useProfile();

useEffect(() => {
const getPlant = async () => {
const plant = await getPlantById(plantId);
setCurrentPlant(plant);
};
getPlant();
}, [plantId]);

const handleAdd = () => {
// assume user is onboarded
if (!currentPlant) return;
setPlantsToAdd([currentPlant]);
router.push('/add-details');
};

return currentPlant ? (
<>
<ImgHeader>
Expand All @@ -58,7 +69,10 @@ export default function GeneralPlantPage() {
difficultyLevel={currentPlant.difficulty_level}
/>
</NameWrapper>
<AddPlant>Add +</AddPlant>
{/*Add button only appears if user is logged in and onboarded*/}
{profileReady && profileData && (
<AddPlant onClick={handleAdd}>Add +</AddPlant>
)}
</Flex>
<ComponentWrapper>
<GardeningTips
Expand Down
Loading
Loading