Skip to content

Commit

Permalink
Refactor components to be screens
Browse files Browse the repository at this point in the history
  • Loading branch information
adityapawar1 committed Oct 14, 2023
1 parent 48ee8d6 commit 1536b6d
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 204 deletions.
1 change: 1 addition & 0 deletions src/app/auth/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ function StackLayout() {
<Stack>
<Stack.Screen name="index" options={{ headerShown: false }} />
<Stack.Screen name="signup" options={{ headerShown: false }} />
<Stack.Screen name="login" options={{ headerShown: false }} />
<Stack.Screen name="onboarding" options={{ headerShown: false }} />
</Stack>
);
Expand Down
34 changes: 14 additions & 20 deletions src/components/Login.tsx → src/app/auth/login.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { useState } from 'react';
import { Redirect } from 'expo-router';
import { Alert, StyleSheet, View } from 'react-native';
import { useSession } from '../../utils/AuthContext';
import { Button, Input } from 'react-native-elements';
import { useSession } from '../utils/AuthContext';
import { Link } from 'expo-router';

const styles = StyleSheet.create({
container: {
Expand All @@ -18,8 +20,13 @@ const styles = StyleSheet.create({
},
});

export default function Login() {
function LoginScreen() {
const sessionHandler = useSession();

if (sessionHandler.session) {
return <Redirect href={'/home'} />;
}

const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [loading, setLoading] = useState(false);
Expand All @@ -32,21 +39,6 @@ export default function Login() {
setLoading(false);
};

const signUpWithEmail = async () => {
setLoading(true);
const { error } = await sessionHandler.signUp(email, password);

if (error) {
Alert.alert(error.message);
console.error(error);
} else {
Alert.alert(
'Please follow the directions in the confirmation email to activate your account.',
);
}
setLoading(false);
};

return (
<View style={styles.container}>
<View style={[styles.verticallySpaced, styles.mt20]}>
Expand All @@ -70,12 +62,14 @@ export default function Login() {
autoCapitalize="none"
/>
</View>

<Link href={'/auth/signup'}>Don't have an account? Sign up</Link>

<View style={[styles.verticallySpaced, styles.mt20]}>
<Button title="Sign in" disabled={loading} onPress={signInWithEmail} />
</View>
<View style={styles.verticallySpaced}>
<Button title="Sign up" disabled={loading} onPress={signUpWithEmail} />
</View>
</View>
);
}

export default LoginScreen;
174 changes: 167 additions & 7 deletions src/app/auth/onboarding.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,175 @@
import { View } from 'react-native';
import Login from '../../components/Login';
import Account from '../../components/Account';
import { useState, useEffect } from 'react';
import { StyleSheet, View, Alert, ScrollView, Platform } from 'react-native';
import { Button, Input } from 'react-native-elements';
import DateTimePicker from '@react-native-community/datetimepicker';
import supabase from '../../utils/supabase';
import UserStringInput from '../../components/UserStringInput';
import { useSession } from '../../utils/AuthContext';
import { Redirect } from 'expo-router';

const styles = StyleSheet.create({
container: {
marginTop: 40,
padding: 12,
},
verticallySpaced: {
paddingTop: 4,
paddingBottom: 4,
alignSelf: 'stretch',
},
mt20: {
marginTop: 20,
},
});

function OnboardingScreen() {
const { session } = useSession();
const { session, signOut } = useSession();

if (!session) {
return <Redirect href={'/auth/login'} />;
}

const [loading, setLoading] = useState(true);
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [birthday, setBirthday] = useState(new Date());
const [gender, setGender] = useState('');
const [raceEthnicity, setRaceEthnicity] = useState('');
const [showDatePicker, setShowDatePicker] = useState(Platform.OS === 'ios');

const getProfile = async () => {
try {
setLoading(true);
if (!session?.user) throw new Error('No user on the session!');

const { data, error, status } = await supabase
.from('profiles')
.select(`first_name, last_name, birthday, gender, race_ethnicity`)
.eq('user_id', session?.user.id)
.single();

if (error && status !== 406) {
throw error;
}

if (data) {
setFirstName(data.first_name || firstName);
setLastName(data.last_name || lastName);
setBirthday(new Date(data.birthday) || birthday);
setGender(data.gender || gender);
setRaceEthnicity(data.race_ethnicity || raceEthnicity);
}
} catch (error) {
if (error instanceof Error) {
Alert.alert(`Get profile error: ${error.message}`);
}
} finally {
setLoading(false);
}
};

useEffect(() => {
if (session) getProfile();
}, [session]);

const updateProfile = async () => {
try {
setLoading(true);
if (!session?.user) throw new Error('No user on the session!');

// Only update values that are not blank
const updates = {
...(firstName && { first_name: firstName }),
...(lastName && { last_name: lastName }),
...(gender && { gender }),
...(raceEthnicity && { race_ethnicity: raceEthnicity }),
...(birthday && { birthday }),
};

// Check if user exists
const { count } = await supabase
.from('profiles')
.select(`*`, { count: 'exact' })
.eq('user_id', session?.user.id);

if (count && count >= 1) {
// Update user if they exist
const { error } = await supabase
.from('profiles')
.update(updates)
.eq('user_id', session?.user.id)
.select('*');

if (error) throw error;
} else {
// Create user if they don't exist
const { error } = await supabase.from('profiles').insert(updates);

if (error) throw error;
}

Alert.alert('Succesfully updated user!');
} catch (error) {
if (error instanceof Error) {
Alert.alert(error.message);
}
} finally {
setLoading(false);
}
};

return (
<View>
{session && session.user ? <Account key={session.user.id} /> : <Login />}
</View>
<ScrollView style={styles.container}>
<View style={[styles.verticallySpaced, styles.mt20]}>
<Input label="Email" value={session?.user?.email} disabled />
</View>
<UserStringInput
label="First Name"
value={firstName}
onChange={setFirstName}
/>
<UserStringInput
label="Last Name"
value={lastName}
onChange={setLastName}
/>
<UserStringInput label="Gender" value={gender} onChange={setGender} />
<UserStringInput
label="Race/Ethnicity"
value={raceEthnicity}
onChange={setRaceEthnicity}
/>

{Platform.OS !== 'ios' && (
<Button
title="Change Birthday"
onPress={() => setShowDatePicker(true)}
/>
)}
{showDatePicker && (
<DateTimePicker
testID="dateTimePicker"
value={birthday}
mode="date"
onChange={date => {
setShowDatePicker(Platform.OS === 'ios');
if (date.nativeEvent.timestamp) {
setBirthday(new Date(date.nativeEvent.timestamp));
}
}}
/>
)}
<View style={[styles.verticallySpaced, styles.mt20]}>
<Button
title={loading ? 'Loading ...' : 'Update'}
onPress={updateProfile}
disabled={loading}
/>
</View>
<View style={styles.verticallySpaced}>
<Button title="Sign Out" onPress={signOut} />
</View>
</ScrollView>
);
}

Expand Down
72 changes: 66 additions & 6 deletions src/app/auth/signup.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,74 @@
import { View } from 'react-native';
import Account from '../../components/Account';
import Login from '../../components/Login';
import React, { useState } from 'react';
import { Redirect, Link } from 'expo-router';
import { Alert, StyleSheet, View } from 'react-native';
import { useSession } from '../../utils/AuthContext';
import { Button, Input } from 'react-native-elements';

const styles = StyleSheet.create({
container: {
marginTop: 40,
padding: 12,
},
verticallySpaced: {
paddingTop: 4,
paddingBottom: 4,
alignSelf: 'stretch',
},
mt20: {
marginTop: 20,
},
});

function SignUpScreen() {
const { session } = useSession();
const sessionHandler = useSession();

if (sessionHandler.session) {
return <Redirect href={'/home'} />;
}

const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [loading, setLoading] = useState(false);

const signUpWithEmail = async () => {
setLoading(true);
const { error } = await sessionHandler.signUp(email, password);

if (error) Alert.alert(error.message);
else
Alert.alert(
'Please follow the instructions in your email to verify your account',
);
setLoading(false);
};

return (
<View>
{session && session.user ? <Account key={session.user.id} /> : <Login />}
<View style={styles.container}>
<View style={[styles.verticallySpaced, styles.mt20]}>
<Input
label="Email"
leftIcon={{ type: 'font-awesome', name: 'envelope' }}
onChangeText={text => setEmail(text)}
value={email}
placeholder="[email protected]"
autoCapitalize="none"
/>
</View>
<View style={styles.verticallySpaced}>
<Input
label="Password"
leftIcon={{ type: 'font-awesome', name: 'lock' }}
onChangeText={text => setPassword(text)}
value={password}
secureTextEntry
placeholder="Password"
autoCapitalize="none"
/>
</View>
<Link href={'/auth/login'}>Already have an account? Log In</Link>
<View style={[styles.verticallySpaced, styles.mt20]}>
<Button title="Sign up" disabled={loading} onPress={signUpWithEmail} />
</View>
</View>
);
}
Expand Down
6 changes: 5 additions & 1 deletion src/app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { Redirect } from 'expo-router';
import { useSession } from '../utils/AuthContext';

function StartPage() {
return <Redirect href="/auth" />;
const { session } = useSession();

if (!session) return <Redirect href="/auth/login" />;
else return <Redirect href={'/home'} />;
}

export default StartPage;
11 changes: 10 additions & 1 deletion src/app/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { Text } from 'react-native';
import { Redirect } from 'expo-router';
import { Text, View } from 'react-native';
import { Button } from 'react-native-elements';
import { SafeAreaView } from 'react-native-safe-area-context';
import globalStyles from '../../globalStyles';
import { useSession } from '../utils/AuthContext';

function SettingsScreen() {
const { session, signOut } = useSession();

if (!session) return <Redirect href={'/auth/login'} />;
return (
<SafeAreaView style={globalStyles.container}>
<Text style={globalStyles.h1}>Settings</Text>
<View>
<Button title="Sign Out" onPress={signOut} />
</View>
</SafeAreaView>
);
}
Expand Down
Loading

0 comments on commit 1536b6d

Please sign in to comment.