diff options
Diffstat (limited to 'src/routes')
| -rw-r--r-- | src/routes/NavigationBar.tsx | 75 | ||||
| -rw-r--r-- | src/routes/OnboardingStack.tsx | 57 | ||||
| -rw-r--r-- | src/routes/Routes.tsx | 44 | ||||
| -rw-r--r-- | src/routes/authentication/AuthProvider.tsx | 122 | ||||
| -rw-r--r-- | src/routes/authentication/index.ts | 2 | ||||
| -rw-r--r-- | src/routes/index.ts | 10 | ||||
| -rw-r--r-- | src/routes/onboarding/Onboarding.tsx | 43 | ||||
| -rw-r--r-- | src/routes/onboarding/OnboardingStack.tsx | 13 | ||||
| -rw-r--r-- | src/routes/onboarding/index.ts | 2 | ||||
| -rw-r--r-- | src/routes/tabs/NavigationBar.tsx | 73 | ||||
| -rw-r--r-- | src/routes/tabs/index.ts | 1 |
11 files changed, 268 insertions, 174 deletions
diff --git a/src/routes/NavigationBar.tsx b/src/routes/NavigationBar.tsx deleted file mode 100644 index 84c18e00..00000000 --- a/src/routes/NavigationBar.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react'; -import {ViewProps} from 'react-native'; -import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; -import {Fragment} from 'react'; -import {NavigationIcon} from '../components'; -import {Home, Notifications, Profile, Search, Upload} from '../screens/main'; - -interface NavigationBarProps extends ViewProps { - centered?: boolean; -} - -const Tab = createBottomTabNavigator(); - -const NavigationBar: React.FC<NavigationBarProps> = () => { - return ( - <Fragment> - <Tab.Navigator - screenOptions={({route}) => ({ - tabBarIcon: ({focused}) => { - if (route.name === 'Home') { - return focused ? ( - <NavigationIcon tab="Home" disabled={false} /> - ) : ( - <NavigationIcon tab="Home" disabled={true} /> - ); - } else if (route.name === 'Search') { - return focused ? ( - <NavigationIcon tab="Search" disabled={false} /> - ) : ( - <NavigationIcon tab="Search" disabled={true} /> - ); - } else if (route.name === 'Upload') { - return focused ? ( - <NavigationIcon tab="Upload" disabled={false} /> - ) : ( - <NavigationIcon tab="Upload" disabled={true} /> - ); - } else if (route.name === 'Notifications') { - return focused ? ( - <NavigationIcon tab="Notifications" disabled={false} /> - ) : ( - <NavigationIcon tab="Notifications" disabled={true} /> - ); - } else if (route.name === 'Profile') { - return focused ? ( - <NavigationIcon tab="Profile" disabled={false} /> - ) : ( - <NavigationIcon tab="Profile" disabled={true} /> - ); - } - }, - })} - initialRouteName="Home" - tabBarOptions={{ - showLabel: false, - style: { - backgroundColor: 'transparent', - position: 'absolute', - borderTopWidth: 0, - left: 0, - right: 0, - bottom: 0, - }, - }}> - <Tab.Screen name="Home" component={Home} /> - <Tab.Screen name="Search" component={Search} /> - <Tab.Screen name="Upload" component={Upload} /> - <Tab.Screen name="Notifications" component={Notifications} /> - <Tab.Screen name="Profile" component={Profile} /> - </Tab.Navigator> - </Fragment> - ); -}; - -export default NavigationBar; diff --git a/src/routes/OnboardingStack.tsx b/src/routes/OnboardingStack.tsx deleted file mode 100644 index 5e91fe9f..00000000 --- a/src/routes/OnboardingStack.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react'; -import {createStackNavigator} from '@react-navigation/stack'; -import { - Login, - RegistrationOne, - RegistrationTwo, - Verification, - ProfileOnboarding, -} from '../screens/onboarding'; - -export type RootStackParamList = { - Login: undefined; - RegistrationOne: undefined; - RegistrationTwo: - | {firstName: string; lastName: string; email: string} - | undefined; - Verification: {username: string; email: string; userId: string}; - ProfileOnboarding: {username: string; userId: string}; -}; - -const RootStack = createStackNavigator<RootStackParamList>(); - -interface OnboardingStackProps {} - -const OnboardingStack: React.FC<OnboardingStackProps> = ({}) => { - return ( - <RootStack.Navigator initialRouteName="Login"> - <RootStack.Screen - name="Login" - component={Login} - options={{headerShown: false}} - /> - <RootStack.Screen - name="RegistrationOne" - component={RegistrationOne} - options={{headerShown: false}} - /> - <RootStack.Screen - name="RegistrationTwo" - component={RegistrationTwo} - options={{headerShown: false}} - /> - <RootStack.Screen - name="Verification" - component={Verification} - options={{headerShown: false}} - /> - <RootStack.Screen - name="ProfileOnboarding" - component={ProfileOnboarding} - options={{headerShown: false}} - /> - </RootStack.Navigator> - ); -}; - -export default OnboardingStack; diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx index 43a51b90..92cd3dd2 100644 --- a/src/routes/Routes.tsx +++ b/src/routes/Routes.tsx @@ -1,42 +1,14 @@ import React from 'react'; -import {OnboardingStack, NavigationBar} from './'; -interface RoutesProps {} -interface AuthProviderProps {} +import {AuthContext} from './authentication'; +import NavigationBar from './tabs'; +import Onboarding from './onboarding'; -export const AuthContext = React.createContext<{ - user: boolean; - login: () => void; - logout: () => void; -}>({ - user: false, - login: () => {}, - logout: () => {}, -}); - -export const AuthContextProvider: React.FC<AuthProviderProps> = ({ - children, -}) => { - const [loggedIn, setLoggedIn] = React.useState(false); // renders onboarding stack - return ( - <AuthContext.Provider - value={{ - user: loggedIn, - login: () => { - setLoggedIn(true); - }, - logout: () => { - setLoggedIn(false); - }, - }}> - {children} - </AuthContext.Provider> - ); -}; - -const Routes: React.FC<RoutesProps> = ({}) => { - const {user} = React.useContext(AuthContext); - return user ? <NavigationBar /> : <OnboardingStack />; +const Routes: React.FC = () => { + const { + user: {userId}, + } = React.useContext(AuthContext); + return userId ? <NavigationBar /> : <Onboarding />; }; export default Routes; diff --git a/src/routes/authentication/AuthProvider.tsx b/src/routes/authentication/AuthProvider.tsx new file mode 100644 index 00000000..bd5706f3 --- /dev/null +++ b/src/routes/authentication/AuthProvider.tsx @@ -0,0 +1,122 @@ +import React, {useEffect} from 'react'; +import {createContext, useState} from 'react'; +import RNFetchBlob from 'rn-fetch-blob'; +import {UserType, ProfileType} from '../../types'; +import { + PROFILE_INFO_ENDPOINT, + AVATAR_PHOTO_ENDPOINT, + COVER_PHOTO_ENDPOINT, +} from '../../constants'; + +interface AuthContextProps { + user: UserType; + profile: ProfileType; + login: (userId: string, username: string) => void; + logout: () => void; + avatar: string | null; + cover: string | null; +} +const NO_USER: UserType = { + userId: '', + username: '', +}; +const NO_PROFILE: ProfileType = { + biography: '', + website: '', + name: '', +}; +export const AuthContext = createContext<AuthContextProps>({ + user: NO_USER, + profile: NO_PROFILE, + login: () => {}, + logout: () => {}, + avatar: null, + cover: null, +}); + +/** + * Authentication provider for the application. + */ +const AuthProvider: React.FC = ({children}) => { + const [user, setUser] = useState<UserType>(NO_USER); + const [profile, setProfile] = useState<ProfileType>(NO_PROFILE); + const [avatar, setAvatar] = useState<string | null>(null); + const [cover, setCover] = useState<string | null>(null); + + const {userId} = user; + useEffect(() => { + if (!userId) { + return; + } + const loadProfileInfo = async () => { + try { + const response = await fetch(PROFILE_INFO_ENDPOINT + `${userId}/`, { + method: 'GET', + }); + const status = response.status; + if (status === 200) { + const info = await response.json(); + let {name, biography, website} = info; + setProfile({name, biography, website}); + } + } catch (error) { + console.log(error); + } + }; + const loadAvatar = async () => { + try { + const response = await RNFetchBlob.config({ + fileCache: true, + appendExt: 'jpg', + }).fetch('GET', AVATAR_PHOTO_ENDPOINT + `${userId}/`); + const status = response.info().status; + if (status === 200) { + setAvatar(response.path()); + } else { + setAvatar(''); + } + } catch (error) { + console.log(error); + } + }; + const loadCover = async () => { + try { + let response = await RNFetchBlob.config({ + fileCache: true, + appendExt: 'jpg', + }).fetch('GET', COVER_PHOTO_ENDPOINT + `${userId}/`); + const status = response.info().status; + if (status === 200) { + setCover(response.path()); + } else { + setCover(''); + } + } catch (error) { + console.log(error); + } + }; + loadProfileInfo(); + loadAvatar(); + loadCover(); + }, [userId]); + + return ( + <AuthContext.Provider + value={{ + user, + profile, + avatar, + cover, + login: (id, username) => { + setUser({...user, userId: id, username}); + }, + logout: () => { + setUser(NO_USER); + }, + }}> + {children} + </AuthContext.Provider> + ); +}; + +export default AuthProvider; diff --git a/src/routes/authentication/index.ts b/src/routes/authentication/index.ts new file mode 100644 index 00000000..9968ae93 --- /dev/null +++ b/src/routes/authentication/index.ts @@ -0,0 +1,2 @@ +export * from './AuthProvider'; +export {default} from './AuthProvider'; diff --git a/src/routes/index.ts b/src/routes/index.ts index 054a25c3..69697b20 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1,6 +1,4 @@ -export {default as OnboardingStack} from './OnboardingStack'; -export * from './OnboardingStack'; -export {default as NavigationBar} from './NavigationBar'; -export * from './NavigationBar'; -export {default as Routes} from './Routes'; -export * from './Routes'; +export {default as AuthProvider} from './authentication'; +export * from './authentication'; +export * from './onboarding'; +export {default} from './Routes'; diff --git a/src/routes/onboarding/Onboarding.tsx b/src/routes/onboarding/Onboarding.tsx new file mode 100644 index 00000000..d2bfbfd6 --- /dev/null +++ b/src/routes/onboarding/Onboarding.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import {OnboardingStack} from './OnboardingStack'; +import { + Login, + RegistrationOne, + RegistrationTwo, + Verification, + ProfileOnboarding, +} from '../../screens'; + +const Onboarding: React.FC = () => { + return ( + <OnboardingStack.Navigator initialRouteName="Login"> + <OnboardingStack.Screen + name="Login" + component={Login} + options={{headerShown: false}} + /> + <OnboardingStack.Screen + name="RegistrationOne" + component={RegistrationOne} + options={{headerShown: false}} + /> + <OnboardingStack.Screen + name="RegistrationTwo" + component={RegistrationTwo} + options={{headerShown: false}} + /> + <OnboardingStack.Screen + name="Verification" + component={Verification} + options={{headerShown: false}} + /> + <OnboardingStack.Screen + name="ProfileOnboarding" + component={ProfileOnboarding} + options={{headerShown: false}} + /> + </OnboardingStack.Navigator> + ); +}; + +export default Onboarding; diff --git a/src/routes/onboarding/OnboardingStack.tsx b/src/routes/onboarding/OnboardingStack.tsx new file mode 100644 index 00000000..f9722d46 --- /dev/null +++ b/src/routes/onboarding/OnboardingStack.tsx @@ -0,0 +1,13 @@ +import {createStackNavigator} from '@react-navigation/stack'; + +export type OnboardingStackParams = { + Login: undefined; + RegistrationOne: undefined; + RegistrationTwo: + | {firstName: string; lastName: string; email: string} + | undefined; + Verification: {username: string; email: string; userId: string}; + ProfileOnboarding: {username: string; userId: string}; +}; + +export const OnboardingStack = createStackNavigator<OnboardingStackParams>(); diff --git a/src/routes/onboarding/index.ts b/src/routes/onboarding/index.ts new file mode 100644 index 00000000..66b0f3f4 --- /dev/null +++ b/src/routes/onboarding/index.ts @@ -0,0 +1,2 @@ +export * from './OnboardingStack'; +export {default} from './Onboarding'; diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx new file mode 100644 index 00000000..aca968c2 --- /dev/null +++ b/src/routes/tabs/NavigationBar.tsx @@ -0,0 +1,73 @@ +import React from 'react'; +import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; +import {NavigationIcon} from '../../components'; +import { + ProfileScreen, + Home, + Notifications, + Search, + Upload, +} from '../../screens'; + +const Tabs = createBottomTabNavigator(); + +const NavigationBar: React.FC = () => { + return ( + <Tabs.Navigator + screenOptions={({route}) => ({ + tabBarIcon: ({focused}) => { + if (route.name === 'Home') { + return focused ? ( + <NavigationIcon tab="Home" disabled={false} /> + ) : ( + <NavigationIcon tab="Home" disabled={true} /> + ); + } else if (route.name === 'Search') { + return focused ? ( + <NavigationIcon tab="Search" disabled={false} /> + ) : ( + <NavigationIcon tab="Search" disabled={true} /> + ); + } else if (route.name === 'Upload') { + return focused ? ( + <NavigationIcon tab="Upload" disabled={false} /> + ) : ( + <NavigationIcon tab="Upload" disabled={true} /> + ); + } else if (route.name === 'Notifications') { + return focused ? ( + <NavigationIcon tab="Notifications" disabled={false} /> + ) : ( + <NavigationIcon tab="Notifications" disabled={true} /> + ); + } else if (route.name === 'Profile') { + return focused ? ( + <NavigationIcon tab="Profile" disabled={false} /> + ) : ( + <NavigationIcon tab="Profile" disabled={true} /> + ); + } + }, + })} + initialRouteName="Profile" + tabBarOptions={{ + showLabel: false, + style: { + backgroundColor: 'transparent', + position: 'absolute', + borderTopWidth: 0, + left: 0, + right: 0, + bottom: 0, + }, + }}> + <Tabs.Screen name="Home" component={Home} /> + <Tabs.Screen name="Search" component={Search} /> + <Tabs.Screen name="Upload" component={Upload} /> + <Tabs.Screen name="Notifications" component={Notifications} /> + <Tabs.Screen name="Profile" component={ProfileScreen} /> + </Tabs.Navigator> + ); +}; + +export default NavigationBar; diff --git a/src/routes/tabs/index.ts b/src/routes/tabs/index.ts new file mode 100644 index 00000000..8ea77e8f --- /dev/null +++ b/src/routes/tabs/index.ts @@ -0,0 +1 @@ +export {default} from './NavigationBar'; |
