From 82dc058fe80bb785c0a17f7c0dab1035374b4ead Mon Sep 17 00:00:00 2001 From: kevin3656 Date: Sun, 6 Oct 2024 17:08:19 -0700 Subject: [PATCH 1/7] plot status and state pages --- app/onboarding/page.tsx | 0 app/onboarding/plotstatus/page.tsx | 31 ++++++++++++++++++++++++++++ app/onboarding/state/page.tsx | 32 +++++++++++++++++++++++++++++ app/onboarding/styles.ts | 33 ++++++++++++++++++++++++++++++ hooks/useProfile.ts | 31 ++++++++++++++++++++++++++++ styles/colors.ts | 9 ++++++++ types/schema.d.ts | 7 +++++++ 7 files changed, 143 insertions(+) create mode 100644 app/onboarding/page.tsx create mode 100644 app/onboarding/plotstatus/page.tsx create mode 100644 app/onboarding/state/page.tsx create mode 100644 app/onboarding/styles.ts create mode 100644 hooks/useProfile.ts create mode 100644 styles/colors.ts diff --git a/app/onboarding/page.tsx b/app/onboarding/page.tsx new file mode 100644 index 0000000..e69de29 diff --git a/app/onboarding/plotstatus/page.tsx b/app/onboarding/plotstatus/page.tsx new file mode 100644 index 0000000..5cd9a20 --- /dev/null +++ b/app/onboarding/plotstatus/page.tsx @@ -0,0 +1,31 @@ +'use client'; + +import { useProfile } from '@/hooks/useProfile'; +import { + Button, + ButtonContainer, + ContentContainer, + PageContainer, +} from '../styles'; + +export default function Page() { + const { addProfile } = useProfile(); + + const handleButtonClick = (state: string) => { + const newProfile = { state, email: '', phone_num: '', user_type: '' }; + addProfile(newProfile); + console.log('test'); + }; + return ( + + +

Plot Status

+

Do you own a plot to plant in?

+ + + + +
+
+ ); +} diff --git a/app/onboarding/state/page.tsx b/app/onboarding/state/page.tsx new file mode 100644 index 0000000..ae2bb07 --- /dev/null +++ b/app/onboarding/state/page.tsx @@ -0,0 +1,32 @@ +'use client'; + +import { useProfile } from '@/hooks/useProfile'; +import { + Button, + ButtonContainer, + ContentContainer, + PageContainer, +} from '../styles'; + +export default function Page() { + const { addProfile } = useProfile(); + + const handleButtonClick = (state: string) => { + const newProfile = { state, email: '', phone_num: '', user_type: '' }; + addProfile(newProfile); + console.log('test'); + }; + return ( + + +

Choose Your state

+ + + + +
+
+ ); +} diff --git a/app/onboarding/styles.ts b/app/onboarding/styles.ts new file mode 100644 index 0000000..1d985e7 --- /dev/null +++ b/app/onboarding/styles.ts @@ -0,0 +1,33 @@ +import styled from 'styled-components'; +import COLORS from '@/styles/colors'; + +export const PageContainer = styled.div` + width: 100%; + height: 100svh; + background-color: ${COLORS.seed}; +`; +export const ContentContainer = styled.div` + display: flex; /* Enable flexbox */ + flex-direction: column; + align-items: center; + justify-content: center; + + height: 100vh; +`; + +export const ButtonContainer = styled.div` + display: flex; /* Enable flexbox */ + flex-direction: row; + align-items: center; + justify-content: center; + gap: 10px; +`; + +export const Button = styled.button` + width: 9.375rem; + height: 3.125rem; + border-radius: 25rem; + border-width: 0px; + background-color: ${COLORS.sprout}; + color: white; +`; diff --git a/hooks/useProfile.ts b/hooks/useProfile.ts new file mode 100644 index 0000000..3543922 --- /dev/null +++ b/hooks/useProfile.ts @@ -0,0 +1,31 @@ +import { useState } from 'react'; +import { Profile } from '../types/schema'; + +const initialProfiles: Profile[] = []; + +export const useProfile = () => { + const [profiles, setProfiles] = useState(initialProfiles); + + const addProfile = (newProfile: Profile) => { + setProfiles(prev => [...prev, newProfile]); + }; + + const updateProfile = (index: number, updates: Partial) => { + setProfiles(prev => + prev.map((profile, i) => + i === index ? { ...profile, ...updates } : profile, + ), + ); + }; + + const removeProfile = (index: number) => { + setProfiles(prev => prev.filter((_, i) => i !== index)); + }; + + return { + profiles, + addProfile, + updateProfile, + removeProfile, + }; +}; diff --git a/styles/colors.ts b/styles/colors.ts new file mode 100644 index 0000000..86875a4 --- /dev/null +++ b/styles/colors.ts @@ -0,0 +1,9 @@ +const COLORS = { + // background white + seed: '#FFFBF2', + + //greens + shrub: '#1F5A2A', + sprout: '#94B506', +}; +export default COLORS; diff --git a/types/schema.d.ts b/types/schema.d.ts index ba520d3..81bfeb5 100644 --- a/types/schema.d.ts +++ b/types/schema.d.ts @@ -2,6 +2,13 @@ import type { UUID } from 'crypto'; export type Season = 'SPRING' | 'SUMMER' | 'FALL' | 'WINTER'; +export interface Profile { + state: string; + email: string; + phone_num: string; + user_type: string; +} + export interface Plant { id: UUID; plant_name: string; From 2b7378bfec085197bdce9b79caed8157bfd59cb7 Mon Sep 17 00:00:00 2001 From: kevin3656 Date: Sun, 13 Oct 2024 15:37:33 -0700 Subject: [PATCH 2/7] added page on onboarding, profile.ts for supabase queries --- api/supabase/queries/profiles.ts | 13 +++ app/onboarding/page.tsx | 179 +++++++++++++++++++++++++++++++ types/schema.d.ts | 2 + 3 files changed, 194 insertions(+) create mode 100644 api/supabase/queries/profiles.ts diff --git a/api/supabase/queries/profiles.ts b/api/supabase/queries/profiles.ts new file mode 100644 index 0000000..628bf66 --- /dev/null +++ b/api/supabase/queries/profiles.ts @@ -0,0 +1,13 @@ +import { Profile } from '@/types/schema'; +import supabase from '../createClient'; + +export async function upsertProfile(profile: Profile) { + const { data, error } = await supabase + .from('profiles') + .upsert(profile) + .select(); + + if (error) throw new Error(`Error upserting profile data: ${error.message}`); + + return data[0]; +} diff --git a/app/onboarding/page.tsx b/app/onboarding/page.tsx index e69de29..2a93dd0 100644 --- a/app/onboarding/page.tsx +++ b/app/onboarding/page.tsx @@ -0,0 +1,179 @@ +'use client'; + +import React, { useState } from 'react'; +import { upsertProfile } from '@/api/supabase/queries/profiles'; +import { Profile } from '@/types/schema'; + +type UUID = `${string}-${string}-${string}-${string}-${string}`; +const generateUUID = (): UUID => { + return crypto.randomUUID() as UUID; +}; +const id = generateUUID(); + +// Define the possible options for each question +const states = ['Tennessee', 'Missouri']; +const gardenTypes = ['Individual', 'Community', 'School']; +const plotOptions = [ + { label: 'yes', value: true }, + { label: 'no', value: false }, +]; +//Interfaces and props to avoid typ errors on Lint +interface StateSelectionProps { + selectedState: string; + setSelectedState: React.Dispatch>; +} + +interface GardenTypeSelectionProps { + selectedGardenType: string; + setSelectedGardenType: React.Dispatch>; +} + +interface PlotSelectionProps { + selectedPlot: boolean | null; + setSelectedPlot: React.Dispatch>; +} + +// Select State +const StateSelection: React.FC = ({ + selectedState, + setSelectedState, +}) => { + return ( +
+

Which state do you live in?

+ +
+ ); +}; + +// Step 2: Select garden type + +const GardenTypeSelection: React.FC = ({ + selectedGardenType, + setSelectedGardenType, +}) => { + return ( +
+

What type of garden do you want to create?

+ {gardenTypes.map(type => ( + + ))} +
+ ); +}; + +// Step 3: Do you have a plot? +const PlotSelection: React.FC = ({ + selectedPlot, + setSelectedPlot, +}) => { + return ( +
+

Do you already have a plot?

+ {plotOptions.map(option => ( + + ))} +
+ ); +}; + +// Main Onboarding Component +const OnboardingFlow = () => { + const [step, setStep] = useState(1); + const [selectedState, setSelectedState] = useState(''); + const [selectedGardenType, setSelectedGardenType] = useState(''); + const [selectedPlot, setSelectedPlot] = useState(false); + + const handleNext = () => { + setStep(step + 1); + }; + + const handleBack = () => { + setStep(step - 1); + }; + + const handleSubmit = async () => { + const profile: Profile = { + user_id: id, + state: selectedState, + email: '', + phone_num: '', + user_type: selectedGardenType, + has_plot: selectedPlot, + }; + try { + const updatedProfile = await upsertProfile(profile); + console.log('Profile successfully upserted:', updatedProfile); + } catch (err) { + console.error('Error upserting profile:', err); + } finally { + } + console.log('Submitted data: ', profile); + // Handle form submission, e.g., send to a server or display a confirmation + }; + + return ( +
+ {step === 1 && ( + + )} + {step === 2 && ( + + )} + {step === 3 && ( + + )} + +
+ {step > 1 && } + {step < 3 && ( + + )} + {step === 3 && } +
+
+ ); +}; + +export default OnboardingFlow; diff --git a/types/schema.d.ts b/types/schema.d.ts index 81bfeb5..6b7e3f5 100644 --- a/types/schema.d.ts +++ b/types/schema.d.ts @@ -3,10 +3,12 @@ import type { UUID } from 'crypto'; export type Season = 'SPRING' | 'SUMMER' | 'FALL' | 'WINTER'; export interface Profile { + user_id: UUID; state: string; email: string; phone_num: string; user_type: string; + has_plot: boolean; } export interface Plant { From bb446e6a85cd73b840c8533796cdb93bc13b5132 Mon Sep 17 00:00:00 2001 From: kevin3656 Date: Sun, 13 Oct 2024 15:47:03 -0700 Subject: [PATCH 3/7] removed profile functions from plot status and state page for lint --- app/onboarding/plotstatus/page.tsx | 2 -- app/onboarding/state/page.tsx | 2 -- 2 files changed, 4 deletions(-) diff --git a/app/onboarding/plotstatus/page.tsx b/app/onboarding/plotstatus/page.tsx index 5cd9a20..bf01d8e 100644 --- a/app/onboarding/plotstatus/page.tsx +++ b/app/onboarding/plotstatus/page.tsx @@ -12,8 +12,6 @@ export default function Page() { const { addProfile } = useProfile(); const handleButtonClick = (state: string) => { - const newProfile = { state, email: '', phone_num: '', user_type: '' }; - addProfile(newProfile); console.log('test'); }; return ( diff --git a/app/onboarding/state/page.tsx b/app/onboarding/state/page.tsx index ae2bb07..2ad74f0 100644 --- a/app/onboarding/state/page.tsx +++ b/app/onboarding/state/page.tsx @@ -12,8 +12,6 @@ export default function Page() { const { addProfile } = useProfile(); const handleButtonClick = (state: string) => { - const newProfile = { state, email: '', phone_num: '', user_type: '' }; - addProfile(newProfile); console.log('test'); }; return ( From adf0c22f9214cb417a8e9bc3e99716aeb36b8adb Mon Sep 17 00:00:00 2001 From: kevin3656 Date: Sun, 13 Oct 2024 15:53:28 -0700 Subject: [PATCH 4/7] removed folders for individual pages, primarily for lint --- app/onboarding/plotstatus/page.tsx | 29 ----------------------------- app/onboarding/state/page.tsx | 30 ------------------------------ 2 files changed, 59 deletions(-) delete mode 100644 app/onboarding/plotstatus/page.tsx delete mode 100644 app/onboarding/state/page.tsx diff --git a/app/onboarding/plotstatus/page.tsx b/app/onboarding/plotstatus/page.tsx deleted file mode 100644 index bf01d8e..0000000 --- a/app/onboarding/plotstatus/page.tsx +++ /dev/null @@ -1,29 +0,0 @@ -'use client'; - -import { useProfile } from '@/hooks/useProfile'; -import { - Button, - ButtonContainer, - ContentContainer, - PageContainer, -} from '../styles'; - -export default function Page() { - const { addProfile } = useProfile(); - - const handleButtonClick = (state: string) => { - console.log('test'); - }; - return ( - - -

Plot Status

-

Do you own a plot to plant in?

- - - - -
-
- ); -} diff --git a/app/onboarding/state/page.tsx b/app/onboarding/state/page.tsx deleted file mode 100644 index 2ad74f0..0000000 --- a/app/onboarding/state/page.tsx +++ /dev/null @@ -1,30 +0,0 @@ -'use client'; - -import { useProfile } from '@/hooks/useProfile'; -import { - Button, - ButtonContainer, - ContentContainer, - PageContainer, -} from '../styles'; - -export default function Page() { - const { addProfile } = useProfile(); - - const handleButtonClick = (state: string) => { - console.log('test'); - }; - return ( - - -

Choose Your state

- - - - -
-
- ); -} From 9e892c6793d338ee46888d388126678782f6af54 Mon Sep 17 00:00:00 2001 From: kevin3656 Date: Tue, 22 Oct 2024 17:33:54 -0700 Subject: [PATCH 5/7] Updated Profile Schema, removed some console.log --- app/onboarding/page.tsx | 19 ++++++------------- types/schema.d.ts | 2 -- utils/ProfileProvider.tsx | 3 +++ 3 files changed, 9 insertions(+), 15 deletions(-) create mode 100644 utils/ProfileProvider.tsx diff --git a/app/onboarding/page.tsx b/app/onboarding/page.tsx index 2a93dd0..502bdf6 100644 --- a/app/onboarding/page.tsx +++ b/app/onboarding/page.tsx @@ -4,12 +4,6 @@ import React, { useState } from 'react'; import { upsertProfile } from '@/api/supabase/queries/profiles'; import { Profile } from '@/types/schema'; -type UUID = `${string}-${string}-${string}-${string}-${string}`; -const generateUUID = (): UUID => { - return crypto.randomUUID() as UUID; -}; -const id = generateUUID(); - // Define the possible options for each question const states = ['Tennessee', 'Missouri']; const gardenTypes = ['Individual', 'Community', 'School']; @@ -124,20 +118,19 @@ const OnboardingFlow = () => { const handleSubmit = async () => { const profile: Profile = { - user_id: id, + user_id: '2abd7296-374a-42d1-bb4f-b813da1615ae', state: selectedState, - email: '', - phone_num: '', user_type: selectedGardenType, has_plot: selectedPlot, }; try { - const updatedProfile = await upsertProfile(profile); - console.log('Profile successfully upserted:', updatedProfile); - } catch (err) { - console.error('Error upserting profile:', err); + upsertProfile(profile); + } catch (error) { + console.error('Error upserting profile:', error); + throw new Error('Error upserting profile'); } finally { } + //TODO: Remove console log. console.log('Submitted data: ', profile); // Handle form submission, e.g., send to a server or display a confirmation }; diff --git a/types/schema.d.ts b/types/schema.d.ts index 6b7e3f5..b6c22a5 100644 --- a/types/schema.d.ts +++ b/types/schema.d.ts @@ -5,8 +5,6 @@ export type Season = 'SPRING' | 'SUMMER' | 'FALL' | 'WINTER'; export interface Profile { user_id: UUID; state: string; - email: string; - phone_num: string; user_type: string; has_plot: boolean; } diff --git a/utils/ProfileProvider.tsx b/utils/ProfileProvider.tsx new file mode 100644 index 0000000..e5339ad --- /dev/null +++ b/utils/ProfileProvider.tsx @@ -0,0 +1,3 @@ +'use client'; + +import { createContext } from 'react'; From e3bbaa5c3e69b8d3ae86a5330a7aa1a261d11f5d Mon Sep 17 00:00:00 2001 From: kevin3656 Date: Tue, 22 Oct 2024 21:45:29 -0700 Subject: [PATCH 6/7] [refactor}Deleted unused ProfileProvider --- utils/ProfileProvider.tsx | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 utils/ProfileProvider.tsx diff --git a/utils/ProfileProvider.tsx b/utils/ProfileProvider.tsx deleted file mode 100644 index e5339ad..0000000 --- a/utils/ProfileProvider.tsx +++ /dev/null @@ -1,3 +0,0 @@ -'use client'; - -import { createContext } from 'react'; From 0748c1baedd42585eb7fa5c2798310e1cfffab9b Mon Sep 17 00:00:00 2001 From: Catherine Tan Date: Tue, 29 Oct 2024 15:52:39 -0700 Subject: [PATCH 7/7] remove old useProfile --- api/supabase/queries/profiles.ts | 5 +++-- app/onboarding/page.tsx | 4 ++-- hooks/useProfile.ts | 31 ------------------------------- 3 files changed, 5 insertions(+), 35 deletions(-) delete mode 100644 hooks/useProfile.ts diff --git a/api/supabase/queries/profiles.ts b/api/supabase/queries/profiles.ts index 628bf66..3b54de8 100644 --- a/api/supabase/queries/profiles.ts +++ b/api/supabase/queries/profiles.ts @@ -5,9 +5,10 @@ export async function upsertProfile(profile: Profile) { const { data, error } = await supabase .from('profiles') .upsert(profile) - .select(); + .select() + .single(); if (error) throw new Error(`Error upserting profile data: ${error.message}`); - return data[0]; + return data; } diff --git a/app/onboarding/page.tsx b/app/onboarding/page.tsx index 502bdf6..c75cf7d 100644 --- a/app/onboarding/page.tsx +++ b/app/onboarding/page.tsx @@ -129,9 +129,9 @@ const OnboardingFlow = () => { console.error('Error upserting profile:', error); throw new Error('Error upserting profile'); } finally { + //TODO: Remove console log. + console.log('Submitted data: ', profile); } - //TODO: Remove console log. - console.log('Submitted data: ', profile); // Handle form submission, e.g., send to a server or display a confirmation }; diff --git a/hooks/useProfile.ts b/hooks/useProfile.ts deleted file mode 100644 index 3543922..0000000 --- a/hooks/useProfile.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useState } from 'react'; -import { Profile } from '../types/schema'; - -const initialProfiles: Profile[] = []; - -export const useProfile = () => { - const [profiles, setProfiles] = useState(initialProfiles); - - const addProfile = (newProfile: Profile) => { - setProfiles(prev => [...prev, newProfile]); - }; - - const updateProfile = (index: number, updates: Partial) => { - setProfiles(prev => - prev.map((profile, i) => - i === index ? { ...profile, ...updates } : profile, - ), - ); - }; - - const removeProfile = (index: number) => { - setProfiles(prev => prev.filter((_, i) => i !== index)); - }; - - return { - profiles, - addProfile, - updateProfile, - removeProfile, - }; -};