Skip to content

Commit

Permalink
auth context for login
Browse files Browse the repository at this point in the history
  • Loading branch information
carolynzhuang committed Dec 11, 2024
1 parent a6b5a91 commit f11a4f6
Show file tree
Hide file tree
Showing 8 changed files with 338 additions and 297 deletions.
2 changes: 1 addition & 1 deletion App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { Text } from 'react-native';
import { useFonts } from 'expo-font';
import { DMSans_400Regular, DMSans_700Bold } from '@expo-google-fonts/dm-sans';
import { DefaultTheme } from '@react-navigation/native';
import { AuthContextProvider } from '@/context/AuthContext';
import AppNavigator from '@/navigation/AppNavigator';
import colors from '@/styles/colors';
import {AuthContextProvider} from '@/context/AuthContext';

DefaultTheme.colors.background = colors.white;

Expand Down
508 changes: 265 additions & 243 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@
"@eslint/object-schema": "^2.1.4",
"@ianvs/prettier-plugin-sort-imports": "^4.4.0",
"@types/react": "~18.3.12",
"@typescript-eslint/eslint-plugin": "^8.15.0",
"@typescript-eslint/parser": "^8.15.0",
"@typescript-eslint/eslint-plugin": "^8.18.0",
"@typescript-eslint/parser": "^8.18.0",
"babel-plugin-module-resolver": "^5.0.2",
"eslint": "^8.57.1",
"eslint-config-expo": "~8.0.1",
Expand Down
54 changes: 31 additions & 23 deletions src/components/GoogleSignInButton/GoogleSignInButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import * as Google from 'expo-auth-session/providers/google';
import * as WebBrowser from 'expo-web-browser';
import { CompositeScreenProps } from '@react-navigation/native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { useAuth } from '@/context/AuthContext';
import { LoginStackParamList, RootStackParamList } from '@/types/navigation';
import { styles } from './styles';
import { useAuth } from '@/context/AuthContext';

WebBrowser.maybeCompleteAuthSession();

Expand All @@ -16,39 +16,47 @@ type GoogleSignInButtonProps = CompositeScreenProps<
NativeStackScreenProps<RootStackParamList, 'BottomTabs'>
>;

export default function GoogleSignInButton({ navigation }: GoogleSignInButtonProps) {
const { setAuthenticated } = useAuth();
const [request, response, promptAsync] = Google.useAuthRequest({
export default function GoogleSignInButton({
navigation,
}: GoogleSignInButtonProps) {
const { setAuthenticated } = useAuth();
const [, response, promptAsync] = Google.useAuthRequest({
webClientId: process.env.EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID,
androidClientId: process.env.EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID,
iosClientId: process.env.EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID,
redirectUri: makeRedirectUri({ scheme: 'org.calblueprint.ourcityforest' }),
});

useEffect(() => {
if (response?.type === 'success' && response.authentication?.accessToken) {
handleSignInWithGoogle(response.authentication.accessToken);
}
}, [response]);
const handleSignInWithGoogle = async (token: string) => {
try {
const userResponse = await fetch(
'https://www.googleapis.com/userinfo/v2/me',
{
headers: { Authorization: `Bearer ${token}` },
},
);

const handleSignInWithGoogle = async (token: string) => {
try {
const userResponse = await fetch('https://www.googleapis.com/userinfo/v2/me', {
headers: { Authorization: `Bearer ${token}` },
});

if (userResponse.ok) {
await setAuthenticated(true);
navigation.navigate('BottomTabs', { screen: 'Home', params: { screen: 'TreeSearch' } });
} else {
console.error('Authentication failed');
if (userResponse.ok) {
await setAuthenticated(true);
navigation.navigate('BottomTabs', {
screen: 'Home',
params: { screen: 'TreeSearch' },
});
} else {
console.error('Authentication failed');
await setAuthenticated(false);
}
} catch (error) {
console.error('Failed to sign in with Google:', error);
await setAuthenticated(false);
}
} catch (error) {
console.error('Failed to sign in with Google:', error);
await setAuthenticated(false);
};

if (response?.type === 'success' && response.authentication?.accessToken) {
handleSignInWithGoogle(response.authentication.accessToken);
}
};
}, [response, navigation, setAuthenticated]);

return (
<TouchableOpacity onPress={() => promptAsync()}>
Expand Down
30 changes: 15 additions & 15 deletions src/components/GoogleSignOutButton/GoogleSignOutButton.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
import { TouchableOpacity, Text } from 'react-native';
import { Text, TouchableOpacity } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useAuth } from '@/context/AuthContext';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { CommonActions } from '@react-navigation/native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { useAuth } from '@/context/AuthContext';
import { ContactStackParamList } from '@/types/navigation';
import { styles } from './styles';

type GoogleSignOutButtonProps = NativeStackScreenProps<ContactStackParamList, 'Contact'>;
type GoogleSignOutButtonProps = NativeStackScreenProps<
ContactStackParamList,
'Contact'
>;

export default function GoogleSignOutButton({ navigation }: GoogleSignOutButtonProps) {
const { setAuthenticated } = useAuth();
export default function GoogleSignOutButton({
navigation,
}: GoogleSignOutButtonProps) {
const { setAuthenticated } = useAuth();

const handleSignOut = async () => {
try {
await AsyncStorage.setItem('authenticated', 'false');
await setAuthenticated(false);
await setAuthenticated(false);
navigation.dispatch(
CommonActions.reset({
index: 0,
routes: [{ name: 'LoginStack' }],
})
}),
);
} catch (error) {
console.error('Error signing out:', error);
}
};

return (
<TouchableOpacity
style={styles.button}
onPress={handleSignOut}
>
<Text style={styles.buttonText}>
Sign out
</Text>
<TouchableOpacity style={styles.button} onPress={handleSignOut}>
<Text style={styles.buttonText}>Sign out</Text>
</TouchableOpacity>
);
}
14 changes: 10 additions & 4 deletions src/context/AuthContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import React, {
createContext,
ReactNode,
useContext,
useEffect,
useState,
} from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';

type AuthState = {
Expand All @@ -16,19 +22,19 @@ export const AuthContextProvider = ({ children }: { children: ReactNode }) => {
try {
const storedAuth = await AsyncStorage.getItem('authenticated');
console.log('Auth state from storage:', storedAuth);
setIsAuthenticated(storedAuth === 'true');
setIsAuthenticated(storedAuth === 'true');
} catch (error) {
console.error('Error loading authentication state:', error);
}
};

syncAuthState();
}, []);
}, []);

const setAuthenticated = async (value: boolean) => {
try {
await AsyncStorage.setItem('authenticated', value ? 'true' : 'false');
setIsAuthenticated(value);
setIsAuthenticated(value);
} catch (error) {
console.error('Failed to update authentication state:', error);
}
Expand Down
4 changes: 2 additions & 2 deletions src/navigation/AppNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import QRCodeScanner from '@/components/QRCodeScanner/QRCodeScanner';
import { useAuth } from '@/context/AuthContext';
import ContactScreen from '@/screens/Contact/Contact';
import DirectoryScreen from '@/screens/Directory/Directory';
import LoginScreen from '@/screens/Login/Login';
Expand All @@ -15,7 +16,6 @@ import {
LoginStackParamList,
RootStackParamList,
} from '@/types/navigation';
import { useAuth } from '@/context/AuthContext';

// Stack and Tab Navigators
const LoginStack = createStackNavigator<LoginStackParamList>();
Expand Down Expand Up @@ -79,7 +79,7 @@ function BottomTabNavigator() {

// Root Navigator
export default function AppNavigator() {
const { isAuthenticated } = useAuth();
const { isAuthenticated } = useAuth();

return (
<NavigationContainer>
Expand Down
19 changes: 12 additions & 7 deletions src/screens/Contact/Contact.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import React from 'react';
import { Image, ScrollView, Text, View } from 'react-native';
import { styles } from './styles';
import GoogleSignOutButton from '@/components/GoogleSignOutButton/GoogleSignOutButton';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import GoogleSignOutButton from '@/components/GoogleSignOutButton/GoogleSignOutButton';
import { ContactStackParamList } from '@/types/navigation';
import { styles } from './styles';

type ContactScreenProps = NativeStackScreenProps<ContactStackParamList, "Contact">;
type ContactScreenProps = NativeStackScreenProps<
ContactStackParamList,
'Contact'
>;

export default function ContactScreen({ navigation, route }: ContactScreenProps) {
export default function ContactScreen({
navigation,
route,
}: ContactScreenProps) {
return (
<ScrollView style={styles.backgroundContainer}>
<View style={styles.imageContainer}>
Expand All @@ -22,10 +28,9 @@ export default function ContactScreen({ navigation, route }: ContactScreenProps)
</View>

<View style={styles.contactInfo}>

{/* temporary button */}
<GoogleSignOutButton navigation={navigation} route={route}/>
<GoogleSignOutButton navigation={navigation} route={route} />

<View>
<Text style={styles.contactHeader}>Contact Us</Text>
</View>
Expand Down

0 comments on commit f11a4f6

Please sign in to comment.