Skip to content

Commit

Permalink
fix(expo-bbq): updated the onboarding, still need to adjust the userc…
Browse files Browse the repository at this point in the history
…ard.
  • Loading branch information
h0lybyte committed Nov 10, 2024
1 parent 6c4d2e9 commit a2043ed
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 38 deletions.
1 change: 1 addition & 0 deletions apps/expo-lcagents/src/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function RootLayoutNav() {
<Stack.Screen name="register" options={{ animation: 'fade' }} />
<Stack.Screen name="login" options={{ animation: 'fade' }} />
<Stack.Screen name="profile" options={{ animation: 'fade' }} />


</Stack>

Expand Down
119 changes: 119 additions & 0 deletions apps/expo-lcagents/src/app/onboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React, { useMemo, useCallback, useEffect, useState, useRef } from 'react';
import { YStack, XStack, SizableText, Separator, ScrollView, Button } from 'tamagui';
import { TamaOnboard, LottieAnimation, TamaSheet, useBBQ } from '@kbve/expo-bbq';
import { useNavigation } from 'expo-router';

const Onboard = () => {

// [C ~~> Nav[]]
const navigation = useNavigation();
const router = useBBQ();
// [Sheet]
const sheetRef = useRef<{
showSheet: () => void;
hideSheet: () => void;
} | null>(null);

// [States]
const [sheetMessage, setSheetMessage] = useState('');
const [isComplete, setIsComplete] = useState(false);
const [hasError, setHasError] = useState(false);

// [Lottie] => (Memo) -> JSON animation for the onboarding screen, since its a static asset.
const lottieOnboardAnimation = useMemo(
() => require('../../assets/json/360-vr.json'),
[],
);

// [Navigation] => (useCallback) <~> (useEffect)
const updateNavigationOptions = useCallback(() => {
navigation.setOptions({
title: 'Onboarding',
headerBackTitle: 'Back',
});

}, [navigation]);

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

// [onSuccess] ?=>
const handleSuccess = () => {
setIsComplete(true);
setHasError(false);
// [i18n] ?? NULL => TamaI18N('[onboard_true']); ($->trigger)
setSheetMessage('Onboarding completed successfully!');
if(sheetRef.current) {
sheetRef.current.showSheet();
}
};

// [onError] ?=>
const handleError = (error: string) => {
setIsComplete(false);
setHasError(true);
// [i18n] ?? NULL => TamaI18N('[onboard_error']); ($->trigger)[error:key]
if(sheetRef.current) {
sheetRef.current.showSheet();
}
};


const renderSheetContent = () => {
return (
<YStack ai="center" jc="center" paddingVertical={10}>
<SizableText>{sheetMessage}</SizableText>
{isComplete && !hasError && (
<Button
onPress={() => {
if (sheetRef.current) {
sheetRef.current.hideSheet();
}
router.go('/profile'); // Navigate to the profile page after successful onboarding
}}
color="green"
size="$4"
marginTop={10}
>
Go to Profile
</Button>
)}
</YStack>
);
};

const MemoizedLottieAnimation = React.memo(LottieAnimation);

return (
<ScrollView contentContainerStyle={{ flexGrow: 1 }}>
<YStack f={1} jc="center" ai="center" padding="$4">
<SizableText size="$4" theme="alt2">Welcome to Onboarding</SizableText>
<MemoizedLottieAnimation
lottieJSON={lottieOnboardAnimation}
style={{
width: 150,
height: 'auto',
aspectRatio: 1,
maxWidth: 800,
}}
/>
<TamaOnboard
supabaseUrl="https://supabase.kbve.com"
supabaseAnonKey="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJyb2xlIjogImFub24iLAogICJpc3MiOiAic3VwYWJhc2UiLAogICJpYXQiOiAxNzI0NTM2ODAwLAogICJleHAiOiAxODgyMzAzMjAwCn0._fmEmblm0afeLoPXxt8wP2mYpa9gzU-ufx3v8oRTFGg"
onSuccess={handleSuccess}
onError={handleError}
/>
</YStack>

<TamaSheet ref={sheetRef} title="Onboarding Status">
{renderSheetContent()}
</TamaSheet>
</ScrollView>
);

};

export default Onboard;
2 changes: 1 addition & 1 deletion packages/expo-bbq/src/components/auth/TamaProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function TamaProfile({

if (profileError || !profileData) {
// If no profile exists for the new user, redirect to onboarding
router.replace('/onboarding');
router.replace('/onboard');
return;
}

Expand Down
126 changes: 89 additions & 37 deletions packages/expo-bbq/src/components/auth/user/TamaOnboard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useCallback, useMemo } from 'react';
import React, { useState, useCallback, useMemo, useEffect } from 'react';
import { YStack, Input, Button, TextArea, Text } from 'tamagui';
import { createSupabaseClient } from '../../wrapper/Supabase';

Expand All @@ -20,6 +20,8 @@ export function TamaOnboard({
const [bio, setBio] = useState('');
const [socials, setSocials] = useState('');
const [style, setStyle] = useState('');
const [loading, setLoading] = useState(true);


// [Supabase]
const supabase = useMemo(
Expand All @@ -28,51 +30,101 @@ export function TamaOnboard({
);

// [User] -> Memoize the user object.
const user = useMemo(async () => {
return (await supabase.auth.getUser())?.data.user;
}, [supabase]);
// const user = useMemo(async () => {
// return (await supabase.auth.getUser())?.data.user;
// }, [supabase]);


// Handler to submit the username
const handleUsernameSubmit = useCallback(async () => {
try {

const userData = await user;
if (!userData) throw new Error('UserData not found');

const { error } = await supabase
.from('user_profiles')
.update({ username })
.eq('id', userData.id);
// Check if username is already set
useEffect(() => {
const checkExistingUsername = async () => {
try {
const user = (await supabase.auth.getUser())?.data.user;
if (!user) throw new Error('User data not found');

if (error) throw error;
const { data, error } = await supabase
.from('user_profiles')
.select('username')
.eq('id', user.id)
.single();

setStep(2); // Move to the next step for bio/socials
} catch (err) {
if (onError) onError('Failed to set username. Please try again.');
console.error(err);
}
}, [username, user, supabase, onError]);
if (error) throw new Error(error.message);

// Handler to submit the user card details
const handleUserCardSubmit = useCallback(async () => {
try {
// If username exists, skip to step 2
if (data?.username) {
setStep(2);
}
} catch (err) {
if (onError) onError('Failed to check username. Please try again.');
console.error(err);
} finally {
setLoading(false);
}
};

const userData = await user;
if (!userData) throw new Error('UserData not found');
checkExistingUsername();
}, [supabase, onError]);

// Handler to submit the username
const handleUsernameSubmit = useCallback(async () => {
try {
const user = (await supabase.auth.getUser())?.data.user;
if (!user) throw new Error('User data not found');

// Lowercase the username for consistency
const lowercasedUsername = username.toLowerCase();


const { error } = await supabase
.from('user_profiles')
.update({ bio, socials, style })
.eq('id', userData.id);
// Call the stored function to handle the new user profile
const { data, error } = await supabase
.rpc('create_user_profile', { _username: lowercasedUsername });

if (error) throw error;

if (error) throw new Error(JSON.stringify(error));

// Check if data was returned to confirm successful update
if (data && data.length > 0) {
setStep(2); // Move to the next step for bio/socials
} else {
throw new Error('Update failed, no data returned');
}
} catch (err) {
if (onError) onError('Failed to set username. Please try again.');
console.error(err);
}
}, [username, supabase, onError]);

// Handler to submit the user card details
const handleUserCardSubmit = useCallback(async () => {
try {
const user = (await supabase.auth.getUser())?.data.user;
if (!user) throw new Error('User data not found');

// Prepare the payload, excluding `socials` and `style` if they're empty
const payload: Record<string, any> = { id: user.id, bio };
if (socials) payload.socials = socials;
if (style) payload.style = style;

// Use upsert to insert or update the row
const { data, error } = await supabase
.from('user_cards')
.upsert(payload, { onConflict: 'id' }) // Handle conflicts based on the user's id
.select();

if (error) throw new Error(JSON.stringify(error));
if (!data || data.length === 0) throw new Error('Failed to save user card details');

if (onSuccess) onSuccess();
} catch (err) {
if (onError) onError('Failed to save user card details. Please try again.');
console.error(err);
}
}, [bio, socials, style, user, supabase, onSuccess, onError]);
} catch (err) {
if (onError) onError('Failed to save user card details. Please try again.');
console.error(err);
}
}, [bio, socials, style, supabase, onSuccess, onError]);


if (loading) {
return <Text>Loading...</Text>;
}

return (
<YStack
Expand Down

0 comments on commit a2043ed

Please sign in to comment.