Skip to content

Commit

Permalink
feat: add auth context
Browse files Browse the repository at this point in the history
  • Loading branch information
geeekgod committed Oct 5, 2022
1 parent 5df1b66 commit 1acb615
Show file tree
Hide file tree
Showing 9 changed files with 8,539 additions and 60 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ web-build/

# macOS
.DS_Store

.env
.envrc
13 changes: 8 additions & 5 deletions App.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { NavigationContainer } from '@react-navigation/native';
import AppLoading from 'expo-app-loading';
import * as SplashScreen from 'expo-splash-screen';
import useFont from "./app/hooks/useFont";
import { AuthContextProvider } from "./app/context/AuthContext";


export default function App() {
Expand All @@ -21,7 +22,7 @@ export default function App() {
await SplashScreen.preventAutoHideAsync();
await useFont();
} catch (e) {
console.warn(e);
console.warn("Errror", e);
} finally {
setAppIsReady(true);
}
Expand Down Expand Up @@ -103,10 +104,12 @@ export default function App() {
return (
<View style={{ flex: 1 }} onLayout={onLayoutRootView}>
<NativeBaseProvider theme={theme}>
<NavigationContainer>
<StatusBar barStyle={"default"} />
<StackNavigator />
</NavigationContainer>
<AuthContextProvider>
<NavigationContainer>
<StatusBar barStyle={"default"} />
<StackNavigator />
</NavigationContainer>
</AuthContextProvider>
</NativeBaseProvider>
</View>
);
Expand Down
7 changes: 7 additions & 0 deletions app/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import axios from 'axios'

const bloodLineApi = axios.create({
baseURL: 'http://192.168.1.7:4561/api',
})

export default bloodLineApi
79 changes: 79 additions & 0 deletions app/context/AuthContext/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { createContext, useEffect, useState } from "react";
import AsyncStorage from "@react-native-async-storage/async-storage";

const AuthContext = createContext();
const storeData = async (key, data) => {
try {
await AsyncStorage.setItem(key, JSON.stringify(data));
} catch (err) {
console.log(err);
}
};

const clearAll = async () => {
try {
await AsyncStorage.clear();
} catch (e) {
console.log("Error while clearing all data", e);
}
};

const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState({});
const [accessToken, setAccessToken] = useState(null);

useEffect(() => {
const firstLoad = async () => {
try {
const user = await AsyncStorage.getItem("@user");
const accessToken = await AsyncStorage.getItem("@accessToken");
setUser(JSON.parse(user));
setAccessToken(JSON.parse(accessToken));
} catch (err) {
console.log(err);
}
};

firstLoad();
}, []);

const headers = {
Authorization: accessToken,
"Content-Type": "application/json",
};

const [isAuth, setIsAuth] = useState(() =>
user !== null && accessToken !== null ? true : false
);

console.log(isAuth, user, accessToken);

const storeCredentials = (resData) => {
storeData("@user", resData.user);
storeData("@accessToken", resData.accessToken);
setUser(resData.user);
setAccessToken(resData.accessToken)
};

const logout = () => {
clearAll().then(() => {
setIsAuth(false);
setUser({});
setAccessToken(null);
});
};

useEffect(() => {
setIsAuth(() => user !== null && accessToken !== null ? true : false)
}, [user, accessToken])

return (
<AuthContext.Provider
value={{ user, accessToken, headers, isAuth, storeCredentials }}
>
{children}
</AuthContext.Provider>
);
};

export { AuthContext, AuthContextProvider };
137 changes: 83 additions & 54 deletions app/screens/Login/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,102 @@ import * as WebBrowser from 'expo-web-browser';
import * as Google from 'expo-auth-session/providers/google';
import { StyleSheet, View } from 'react-native';
import { heightScreen, widthScreen } from '../../utils/layout';
import { Box, Button, Icon, Text } from 'native-base';
import { Box, Button, CloseIcon, HStack, Icon, IconButton, Text, VStack } from 'native-base';
import LoginUnlock from "../../assets/svg/login/LoginUnlock.svg";
import axios from "axios";
import { AntDesign } from '@expo/vector-icons';
import { Alert } from "native-base";
import bloodLineApi from '../../api';
import { AuthContext } from '../../context/AuthContext';


WebBrowser.maybeCompleteAuthSession();

const Login = () => {
const [request, response, promptAsync] = Google.useAuthRequest({
expoClientId: '938415613346-3ecn64agj1971r8l0s520kc41d4s0n6p.apps.googleusercontent.com',
androidClientId: '938415613346-f70dmihvkcjpjo3ljm798e85t5g45s2i.apps.googleusercontent.com',
});

React.useEffect(() => {
if (response?.type === 'success') {
const { authentication } = response;
const [showError, setShowError] = React.useState(false);
const { storeCredentials } = React.useContext(AuthContext)

const [request, response, promptAsync] = Google.useAuthRequest({
expoClientId: '938415613346-3ecn64agj1971r8l0s520kc41d4s0n6p.apps.googleusercontent.com',
androidClientId: '938415613346-f70dmihvkcjpjo3ljm798e85t5g45s2i.apps.googleusercontent.com',
});

React.useEffect(() => {
if (response?.type === 'success') {
const { authentication } = response;

bloodLineApi.post("/auth/googleAuth", {
accessToken: authentication.accessToken
}).then((res) => {
storeCredentials(res.data);
}).catch((err) => {
console.log(err);
setShowError(true)

setTimeout(() => setShowError(false), 5000);
})
}
}, [response]);

return (
<View style={styles.container}>
<Box
h="400"
w="400"
position="absolute"
top={heightScreen > 800 ? "-20" : "-40"}
right={heightScreen > 800 ? "-120" : "-150"}
>
<AntDesign name='heart' size={400} color='#DE2A26' />
</Box>
<LoginUnlock />
<Text fontFamily='body' fontWeight="600" mt='6' fontSize='3xl' textAlign='center'>Continue with us</Text>
<Text fontFamily='body' color='#7A7A7A' mt='3' mb='3' fontWeight="400" fontSize='md' textAlign='center' lineHeight='2xl'>Sign in via</Text>
<Button
leftIcon={<Icon name="google" as={AntDesign} color="white" />}
disabled={!request}
onPress={() => promptAsync()}
size='lg'
fontSize='xl'
rounded='2xl'
>
Login with Google
</Button>

{showError && (<Alert w="100%" status='error' position='absolute' bottom='8'>
<VStack space={2} flexShrink={1} w="100%">
<HStack flexShrink={1} space={2} alignItems='center' justifyContent="space-between">
<HStack space={2} flexShrink={1}>
<Alert.Icon mt="1" />
<Text fontSize="md" color="coolGray.800">
There was some error
</Text>
</HStack>
<IconButton onPress={() => setShowError(false)} variant="unstyled" _focus={{
borderWidth: 0
}} icon={<CloseIcon size="3" />} _icon={{
color: "coolGray.600"
}} />
</HStack>
</VStack>
</Alert>)}

axios.get("https://www.googleapis.com/oauth2/v1/userinfo?alt=json", {
headers: { Authorization: `Bearer ${authentication?.accessToken}` }
}).then((res) => {
console.log(res.data)
}).catch((err) => {
console.log(err);
})
}
}, [response]);

return (
<View style={styles.container}>
<Box
h="400"
w="400"
// bg="#DE2A26"
// rounded="full"
position="absolute"
top={heightScreen > 800 ? "-20" : "-40"}
right={heightScreen > 800 ? "-120" : "-150"}
>
<AntDesign name='heart' size={400} color='#DE2A26' />
</Box>
<LoginUnlock />
<Text fontFamily='body' fontWeight="600" mt='6' fontSize='3xl' textAlign='center'>Continue with us</Text>
<Text fontFamily='body' color='#7A7A7A' mt='3' mb='3' fontWeight="400" fontSize='md' textAlign='center' lineHeight='2xl'>Sign in via</Text>
<Button
leftIcon={<Icon name="google" as={AntDesign} color="white" />}
disabled={!request}
onPress={() => promptAsync()}
size='lg'
fontSize='xl'
rounded='2xl'
>
Login with Google
</Button>
</View>
);
</View>
);
}

export default Login

const styles = StyleSheet.create({
container: {
flex: 1,
width: widthScreen,
backgroundColor: "#fff",
paddingHorizontal: heightScreen > 800 ? 32 : 26,
justifyContent: "center",
alignItems: "center",
position: "relative",
},
container: {
flex: 1,
width: widthScreen,
backgroundColor: "#fff",
paddingHorizontal: heightScreen > 800 ? 32 : 26,
justifyContent: "center",
alignItems: "center",
position: "relative",
},
});
2 changes: 1 addition & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = function(api) {
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"web": "expo start --web"
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.17.10",
"@react-navigation/native": "^6.0.13",
"@react-navigation/stack": "^6.3.1",
"axios": "^0.27.2",
Expand Down
Loading

0 comments on commit 1acb615

Please sign in to comment.