Skip to content

Commit 92190bf

Browse files
Add Google Sign-In login screen
1 parent c8bda77 commit 92190bf

File tree

7 files changed

+114
-3
lines changed

7 files changed

+114
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ CodeBuilder Admin is a mobile application built with React Native and Expo. This
4040

4141
```env
4242
GOOGLE_MAPS_API_KEY=your_google_maps_api_key
43+
GOOGLE_WEB_CLIENT_ID=your_google_web_client_id
4344
FIREBASE_API_KEY=your_firebase_api_key
4445
FIREBASE_AUTH_DOMAIN=your_firebase_auth_domain
4546
FIREBASE_PROJECT_ID=your_firebase_project_id

app.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ module.exports = {
4242
firebaseStorageBucket: process.env.FIREBASE_STORAGE_BUCKET,
4343
firebaseMessagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
4444
firebaseAppId: process.env.FIREBASE_APP_ID,
45+
googleWebClientId: process.env.GOOGLE_WEB_CLIENT_ID,
4546
},
4647
orientation: "portrait",
4748
icon: "./assets/images/icon.png",
@@ -135,6 +136,7 @@ module.exports = {
135136
],
136137
"@react-native-firebase/app",
137138
"@react-native-firebase/messaging",
139+
"@react-native-google-signin/google-signin",
138140
// Add the iOS sound plugin
139141
[withIOSSounds],
140142
[

app/_layout.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect } from "react";
22
import { useNavigationContainerRef } from "@react-navigation/native";
33
import { useReactNavigationDevTools } from "@dev-plugins/react-navigation";
44
import { SplashScreen } from "expo-router";
@@ -18,6 +18,7 @@ import "react-native-reanimated";
1818
import { useColorScheme } from "@/hooks/useColorScheme";
1919
import { registerBackgroundFetch } from "@/utils/tasks.utils";
2020
import ErrorBoundary from "@/components/ErrorBoundary";
21+
import { AuthProvider, useAuth } from "@/hooks/useAuth";
2122

2223
import {
2324
setJSExceptionHandler,
@@ -100,17 +101,26 @@ export default function RootLayout() {
100101
return null;
101102
}
102103

103-
return <RootLayoutNav />;
104+
return (
105+
<AuthProvider>
106+
<RootLayoutNav />
107+
</AuthProvider>
108+
);
104109
}
105110

106111
function RootLayoutNav() {
107112
const colorScheme = useColorScheme();
113+
const { user } = useAuth();
108114

109115
return (
110116
<ErrorBoundary>
111117
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
112118
<Stack>
113-
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
119+
{user ? (
120+
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
121+
) : (
122+
<Stack.Screen name="login" options={{ headerShown: false }} />
123+
)}
114124
<Stack.Screen name="modal" options={{ presentation: "modal" }} />
115125
</Stack>
116126
</ThemeProvider>

app/login.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { useEffect } from 'react';
2+
import { View, StyleSheet } from 'react-native';
3+
import { GoogleSignin, GoogleSigninButton } from '@react-native-google-signin/google-signin';
4+
import Constants from 'expo-constants';
5+
import { useAuth } from '@/hooks/useAuth';
6+
7+
export default function LoginScreen() {
8+
const { setUser } = useAuth();
9+
10+
useEffect(() => {
11+
GoogleSignin.configure({
12+
webClientId: Constants.expoConfig?.extra?.googleWebClientId,
13+
});
14+
}, []);
15+
16+
const signIn = async () => {
17+
try {
18+
await GoogleSignin.hasPlayServices({ showPlayServicesUpdateDialog: true });
19+
const result = await GoogleSignin.signIn();
20+
if (result.type === 'success') {
21+
setUser({ idToken: result.data.idToken ?? '', user: result.data.user });
22+
fetch('https://new.codebuilder.org/api/auth/google', {
23+
method: 'POST',
24+
headers: { 'Content-Type': 'application/json' },
25+
body: JSON.stringify({ idToken: result.data.idToken }),
26+
}).catch((e) => console.error('Auth callback error:', e));
27+
}
28+
} catch (e) {
29+
console.error('Google sign in error:', e);
30+
}
31+
};
32+
33+
return (
34+
<View style={styles.container}>
35+
<GoogleSigninButton
36+
onPress={signIn}
37+
size={GoogleSigninButton.Size.Wide}
38+
color={GoogleSigninButton.Color.Dark}
39+
/>
40+
</View>
41+
);
42+
}
43+
44+
const styles = StyleSheet.create({
45+
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
46+
});

hooks/useAuth.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { createContext, useContext, useState, ReactNode } from 'react';
2+
3+
export interface AuthUser {
4+
idToken: string;
5+
user: {
6+
id: string;
7+
name: string | null;
8+
email: string;
9+
photo: string | null;
10+
familyName: string | null;
11+
givenName: string | null;
12+
};
13+
}
14+
15+
interface AuthContextType {
16+
user: AuthUser | null;
17+
setUser: (user: AuthUser | null) => void;
18+
}
19+
20+
const AuthContext = createContext<AuthContextType>({
21+
user: null,
22+
setUser: () => {},
23+
});
24+
25+
export const AuthProvider = ({ children }: { children: ReactNode }) => {
26+
const [user, setUser] = useState<AuthUser | null>(null);
27+
return (
28+
<AuthContext.Provider value={{ user, setUser }}>
29+
{children}
30+
</AuthContext.Provider>
31+
);
32+
};
33+
34+
export const useAuth = () => useContext(AuthContext);

package-lock.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"@react-native-firebase/app": "^22.2.1",
2525
"@react-native-firebase/auth": "^22.2.1",
2626
"@react-native-firebase/messaging": "^22.2.1",
27+
"@react-native-google-signin/google-signin": "^15.0.0",
2728
"@react-navigation/native": "^7.1.6",
2829
"@react-navigation/native-stack": "^7.3.10",
2930
"babel-preset-expo": "~13.0.0",

0 commit comments

Comments
 (0)