Skip to content

Commit

Permalink
[feat] ProfileProvider implementation, lint + prettier fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin3656 committed Oct 26, 2024
1 parent c1a6aa0 commit 96d938f
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 59 deletions.
5 changes: 4 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import StyledComponentsRegistry from '@/lib/registry';
import { ProfileProvider } from '@/utils/ProfileProvider';

// font definitions
const sans = Inter({
Expand All @@ -22,7 +23,9 @@ export default function RootLayout({
return (
<html lang="en">
<body className={sans.className}>
<StyledComponentsRegistry>{children}</StyledComponentsRegistry>
<ProfileProvider>
<StyledComponentsRegistry>{children}</StyledComponentsRegistry>
</ProfileProvider>
</body>
</html>
);
Expand Down
95 changes: 43 additions & 52 deletions app/onboarding/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
'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();
import { ProfileProvider, useProfile } from '@/utils/ProfileProvider';

// Define the possible options for each question
const states = ['Tennessee', 'Missouri'];
Expand Down Expand Up @@ -121,59 +114,57 @@ const OnboardingFlow = () => {
const handleBack = () => {
setStep(step - 1);
};

const { setProfile } = useProfile();
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 {
await setProfile({
state: selectedState,
user_type: selectedGardenType,
has_plot: selectedPlot,
});
console.log('Profile updated successfully');
} catch (error) {
console.error('Error submitting profile:', error);
}
console.log('Submitted data: ', profile);
// Handle form submission, e.g., send to a server or display a confirmation
};
// Handle form submission, e.g., send to a server or display a confirmation

return (
<div>
{step === 1 && (
<StateSelection
selectedState={selectedState}
setSelectedState={setSelectedState}
/>
)}
{step === 2 && (
<GardenTypeSelection
selectedGardenType={selectedGardenType}
setSelectedGardenType={setSelectedGardenType}
/>
)}
{step === 3 && (
<PlotSelection
selectedPlot={selectedPlot}
setSelectedPlot={setSelectedPlot}
/>
)}

<ProfileProvider>
<div>
{step > 1 && <button onClick={handleBack}>Back</button>}
{step < 3 && (
<button onClick={handleNext} disabled={!selectedState && step === 1}>
Next
</button>
{step === 1 && (
<StateSelection
selectedState={selectedState}
setSelectedState={setSelectedState}
/>
)}
{step === 3 && <button onClick={handleSubmit}>Submit</button>}
{step === 2 && (
<GardenTypeSelection
selectedGardenType={selectedGardenType}
setSelectedGardenType={setSelectedGardenType}
/>
)}
{step === 3 && (
<PlotSelection
selectedPlot={selectedPlot}
setSelectedPlot={setSelectedPlot}
/>
)}

<div>
{step > 1 && <button onClick={handleBack}>Back</button>}
{step < 3 && (
<button
onClick={handleNext}
disabled={!selectedState && step === 1}
>
Next
</button>
)}
{step === 3 && <button onClick={handleSubmit}>Submit</button>}
</div>
</div>
</div>
</ProfileProvider>
);
};

export default OnboardingFlow;
10 changes: 6 additions & 4 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import BPLogo from '@/assets/images/bp-logo.png';
import { Container, Image } from './page.style';
import { ProfileProvider } from '@/utils/ProfileProvider';
import OnboardingFlow from './onboarding/page';
import { Container } from './page.style';

export default function Home() {
return (
<Container>
<Image src={BPLogo} alt="Blueprint Logo" />
<p>Open up app/page.tsx to get started!</p>
<ProfileProvider>
<OnboardingFlow />
</ProfileProvider>
</Container>
);
}
2 changes: 0 additions & 2 deletions types/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ export type DifficultyLevelEnum = 'EASY' | 'MODERATE' | 'HARD';
export interface Profile {
user_id: UUID;
state: string;
email: string;
phone_num: string;
user_type: string;
has_plot: boolean;
}
Expand Down
99 changes: 99 additions & 0 deletions utils/ProfileProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
'use client';

import React, {
createContext,
ReactNode,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from 'react';
import { upsertProfile } from '@/api/supabase/queries/profiles';
import { Profile } from '@/types/schema';

// Define a placeholder user ID for development purposes
const placeholderUserId = '2abd7296-374a-42d1-bb4f-b813da1615ae';

interface ProfileContextType {
profileData: Profile | null;
profileReady: boolean;
setProfile: (newProfileData: Partial<Profile>) => Promise<void>;
loadProfile: () => Promise<void>;
}

const ProfileContext = createContext<ProfileContextType | undefined>(undefined);

export const useProfile = () => {
const context = useContext(ProfileContext);
if (!context) {
throw new Error('useProfile must be used within a ProfileProvider');
}
return context;
};

export const ProfileProvider: React.FC<{ children: ReactNode }> = ({
children,
}) => {
const [profileData, setProfileData] = useState<Profile | null>(null);
const [profileReady, setProfileReady] = useState<boolean>(false);

const loadProfile = useCallback(async () => {
setProfileReady(false);

try {
const profile: Profile = {
user_id: placeholderUserId,
state: '',
user_type: '',
has_plot: false,
};
// Fetch or upsert the profile for the placeholder user ID
const fetchedProfile = await upsertProfile(profile);
setProfileData(fetchedProfile);
} catch (error) {
console.error('Error loading profile:', error);
} finally {
setProfileReady(true);
}
}, []);

const setProfile = useCallback(
async (newProfileData: Partial<Profile>) => {
const profileToUpdate: Profile = {
...profileData!,
...newProfileData,
user_id: placeholderUserId, // Using placeholder user ID for now
};

try {
const updatedProfile = await upsertProfile(profileToUpdate);
setProfileData(updatedProfile);
} catch (error) {
console.error('Error updating profile:', error);
throw new Error('Error updating profile');
}
},
[profileData],
);

useEffect(() => {
loadProfile();
}, [loadProfile]);

const providerValue = useMemo(
() => ({
profileData,
profileReady,
setProfile,
loadProfile,
}),
[profileData, profileReady, setProfile, loadProfile],
);

return (
<ProfileContext.Provider value={providerValue}>
{children}
</ProfileContext.Provider>
);
};

0 comments on commit 96d938f

Please sign in to comment.