Skip to content

Commit

Permalink
Added authentication workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
swapnilkamat23 committed Jun 3, 2023
1 parent 6018e57 commit b56f381
Show file tree
Hide file tree
Showing 25 changed files with 4,591 additions and 1,691 deletions.
64 changes: 61 additions & 3 deletions App.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,76 @@
import React, { useState } from "react";
import React, { useState, useEffect, useCallback } from "react";
import { NavigationContainer } from "@react-navigation/native";
import * as SplashScreen from "expo-splash-screen";

import AuthContext from "./app/auth/context";
import navigationTheme from "./app/navigation/navigationTheme";
import AuthNavigator from "./app/navigation/AuthNavigator";
import AppNavigator from "./app/navigation/AppNavigator";
import asyncStorage from "./app/store/asyncStorage";
import { USER_OBJECT_KEY } from "./app/store/constants";
import ErrorScreen from "./app/views/screens/ErrorScreen";
import { AsyncStatus } from "./app/constants/enums";

// Keep the splash screen visible while we fetch resources
SplashScreen.preventAutoHideAsync();

export default function App() {
const [user, setUser] = useState();
const [appStatus, setAppStatus] = useState(AsyncStatus.Idle);

const restoreUserSession = async () => {
const userObj = await asyncStorage.getDataObject(USER_OBJECT_KEY);
if (!userObj) return;
setUser(userObj);
};

useEffect(() => {
async function prepare() {
try {
setAppStatus(AsyncStatus.Loading);
await restoreUserSession();
setAppStatus(AsyncStatus.Succeeded);
} catch (error) {
console.log("Error loading app", error);
setAppStatus(AsyncStatus.Failed);
}
}

prepare();
}, []);

const onNavigationContainerReady = useCallback(async () => {
if (
appStatus === AsyncStatus.Succeeded ||
appStatus === AsyncStatus.Failed
) {
await SplashScreen.hideAsync();
}
}, [appStatus]);

// Avoids rendering of AppNavigator/AuthNavigator.
// Important to keep SplashScreen visible until loading is done. (per official documentation of SpashScreen)
if (appStatus === AsyncStatus.Idle || appStatus === AsyncStatus.Loading) {
return null;
}

// Render respective experience based on success/failure to load App component
function renderSwitch() {
switch (appStatus) {
case AsyncStatus.Succeeded:
return <>{user ? <AppNavigator /> : <AuthNavigator />}</>;
case AsyncStatus.Failed:
return <ErrorScreen />;
}
}

return (
<AuthContext.Provider value={{ user, setUser }}>
<NavigationContainer theme={navigationTheme}>
{user ? <AppNavigator /> : <AuthNavigator />}
<NavigationContainer
theme={navigationTheme}
onReady={onNavigationContainerReady}
>
{renderSwitch()}
</NavigationContainer>
</AuthContext.Provider>
);
Expand Down
8 changes: 4 additions & 4 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"icon": "./app/assets/icon.png",
"userInterfaceStyle": "light",
"splash": {
"image": "./app/assets/splash.png",
"image": "./app/assets/splash_2.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
"backgroundColor": "#E3E1E1"
},
"assetBundlePatterns": [
"**/*"
Expand All @@ -20,12 +20,12 @@
"android": {
"package": "com.sb.ma",
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"foregroundImage": "./app/assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"web": {
"favicon": "./assets/favicon.png"
"favicon": "./app/assets/favicon.png"
},
"extra": {
"eas": {
Expand Down
1 change: 0 additions & 1 deletion app/api/Sample.js

This file was deleted.

8 changes: 8 additions & 0 deletions app/api/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { create } from "apisauce";
import settings from "../config/settings";

const apiClient = create({
baseURL: settings.baseURL,
});

export default apiClient;
24 changes: 24 additions & 0 deletions app/api/hooks/useApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useState } from "react";

import { AsyncStatus } from "../../constants/enums";

export default useApi = (apiFunc) => {
const [data, setData] = useState([]);
const [apiStatus, setApiStatus] = useState(AsyncStatus.Idle);

const request = async (...args) => {
setApiStatus(AsyncStatus.Loading);
const response = await apiFunc(...args);

setApiStatus(response.ok ? AsyncStatus.Succeeded : AsyncStatus.Failed);
setData(response.data);
return response;
};

return {
request,
data,
error: apiStatus === AsyncStatus.Failed,
loading: apiStatus === AsyncStatus.Loading,
};
};
8 changes: 8 additions & 0 deletions app/api/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import client from "./client";

const login = (username, password) =>
client.post("/login", { username, password });

export default {
login,
};
1 change: 1 addition & 0 deletions app/assets/animation/loader.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"nm":"Comp 1","ddd":0,"h":200,"w":200,"meta":{"g":"@lottiefiles/toolkit-js 0.26.1"},"layers":[{"ty":4,"nm":"Capa de formas 5","sr":1,"st":0,"op":60,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[-1,-182.375,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[25,25,100],"t":0},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[25,47,100],"t":12},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[35,21.67,100],"t":13},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[52.13,16,100],"t":14},{"s":[106,9,100],"t":15}],"ix":6},"sk":{"a":0,"k":0},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[99.5,-7,0],"t":0},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[99.5,78,0],"t":12},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[99.5,82.03,0],"t":13},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[99.5,83.06,0],"t":14},{"s":[99.5,84.19,0],"t":15}],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[100],"t":15},{"s":[0],"t":16}],"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Forma 1","ix":1,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Trazado 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[0.938,0],[0,-5.25],[-4.563,0.125],[0.108,4.624]],"o":[[-0.813,0.125],[0,4.813],[4.563,-0.125],[-0.125,-5.375]],"v":[[-1.344,-193.078],[-8.75,-180.5],[-1.063,-172.313],[6.938,-180.188]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Relleno 1","c":{"a":0,"k":[1,0.7412,0.0784],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":1},{"ty":4,"nm":"Capa de formas 3","sr":1,"st":0,"op":60,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[-32,-31,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-2,0.5,100],"t":47},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[0.75,2,100],"t":48},{"s":[1,1.5,100],"t":53}],"ix":6},"sk":{"a":0,"k":0},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[99.99,84.13,0],"t":47},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[99.99,79.02,0],"t":48},{"s":[99.99,-5,0],"t":53}],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[0],"t":46},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[100],"t":47},{"s":[100],"t":48}],"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Elipse 1","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Trazado elíptico 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[308,308],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Relleno 1","c":{"a":0,"k":[1,0.7412,0.0784],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-31,-31],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":2},{"ty":4,"nm":"Capa de formas 4","sr":1,"st":0,"op":60,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[-32,-31,0],"ix":1},"s":{"a":0,"k":[27.5,27.5,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[99.5,126.5,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Elipse 1","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Trazado elíptico 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[308,308],"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Trazo 1","lc":1,"lj":1,"ml":4,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"c":{"a":0,"k":[1,0.7412,0.0784],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-31,-31],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"tm","bm":0,"hd":false,"mn":"ADBE Vector Filter - Trim","nm":"Recortar trazados 1","ix":2,"e":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[50],"t":12},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[0],"t":24},{"s":[50],"t":48}],"ix":2},"o":{"a":0,"k":180,"ix":3},"s":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[50],"t":12},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[100],"t":24},{"s":[50],"t":48}],"ix":1},"m":1}],"ind":3},{"ty":4,"nm":"Capa de formas 1","sr":1,"st":0,"op":60,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"td":1,"ao":0,"ks":{"a":{"a":0,"k":[-32,-31,0],"ix":1},"s":{"a":0,"k":[25,25,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[99.5,126.5,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Elipse 1","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Trazado elíptico 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[308,308],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Relleno 1","c":{"a":0,"k":[1,0.7412,0.0784],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-31,-31],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":4},{"ty":0,"nm":"Precomp. 1","sr":1,"st":0,"op":144,"ip":0,"hd":false,"ddd":0,"bm":0,"tt":1,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[200,200,0],"ix":1},"s":{"a":0,"k":[50,50,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[100,100,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"w":400,"h":400,"refId":"comp_0","ind":5}],"v":"4.10.1","fr":24,"op":72,"ip":0,"assets":[{"nm":"","id":"comp_0","layers":[{"ty":4,"nm":"Capa de formas 12","sr":1,"st":0,"op":144,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[43,43,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[81.5,370.25,0],"t":24,"ti":[-60.6666679382324,28.5,0],"to":[60.6666679382324,-28.5,0]},{"s":[445.5,199.25,0],"t":48}],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Forma 1","ix":1,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Trazado 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[28,0],[34.935,-19.483],[31.619,18.821],[33,-14],[57,29],[0,0],[0,0],[0,0]],"o":[[-28,0],[-52,29],[-42,-25],[-28.892,12.257],[-57,-29],[0,0],[0,0],[0,0]],"v":[[367.75,-97],[277,-75],[155,-82],[35,-82],[-94,-82.326],[-200,-74],[-352.07,320.209],[499.162,354.093]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Relleno 1","c":{"a":0,"k":[1,0.7412,0.0784],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":1},{"ty":4,"nm":"Capa de formas 2","sr":1,"st":0,"op":144,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[43,43,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-133,374,0],"t":24,"ti":[-60.6666679382324,28.5,0],"to":[60.6666679382324,-28.5,0]},{"s":[231,203,0],"t":48}],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Forma 1","ix":1,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Trazado 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[28,0],[34.935,-19.483],[31.619,18.821],[33,-14],[57,29],[0,0],[0,0],[0,0]],"o":[[-28,0],[-52,29],[-42,-25],[-28.892,12.257],[-57,-29],[0,0],[0,0],[0,0]],"v":[[367.75,-97],[277,-75],[155,-82],[35,-82],[-94,-82.326],[-200,-74],[-352.07,320.209],[499.162,354.093]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Relleno 1","c":{"a":0,"k":[1,0.8,0.2941],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":2}]}]}
File renamed without changes
Binary file added app/assets/splash_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion app/config/Sample.js

This file was deleted.

20 changes: 20 additions & 0 deletions app/config/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* This file returns a set of configurations for the respective environment that the app is running in.
*/

const settings = {
dev: {
baseURL: "https://ill-gold-parrot-sock.cyclic.app",
},
prod: {
// update this URL once we deploy to prod env
baseURL: "https://some-url-in-prod.com",
},
};

const getCurrentSettings = () => {
if (__DEV__) return settings.dev;
return settings.prod;
};

export default getCurrentSettings();
6 changes: 6 additions & 0 deletions app/constants/enums.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const AsyncStatus = {
Idle: "Idle",
Loading: "Loading",
Succeeded: "Succeeded",
Failed: "Failed",
};
2 changes: 1 addition & 1 deletion app/navigation/AppNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const AppNavigator = () => (
}}
/>
<Tab.Screen
name="Account"
name="Profile"
component={AccountScreen}
options={{
tabBarIcon: ({ color, size }) => (
Expand Down
1 change: 0 additions & 1 deletion app/store/Sample.js

This file was deleted.

65 changes: 65 additions & 0 deletions app/store/asyncStorage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* This file contains helper functions to store and retrieve key-values from async storage.
*/

import AsyncStorage from "@react-native-async-storage/async-storage";

const storeData = async (key, value) => {
try {
await AsyncStorage.setItem(key, value);
} catch (e) {
console.log(
`Error occured while saving to async storage - key=${key}, value=${value}. Message stack - ${e}`
);
}
};

const storeDataObject = async (key, value) => {
try {
const jsonValue = JSON.stringify(value);
await AsyncStorage.setItem(key, jsonValue);
} catch (e) {
console.log(
`Error occured while saving object to async storage - key=${key}, value=${value}. Message stack - ${e}`
);
}
};

const getData = async (key) => {
try {
return await AsyncStorage.getItem(key);
} catch (e) {
console.log(
`Error occured while fetching from async storage - key=${key}. Message stack - ${e}`
);
}
};

const getDataObject = async (key) => {
try {
const jsonValue = await AsyncStorage.getItem(key);
return jsonValue != null ? JSON.parse(jsonValue) : null;
} catch (e) {
console.log(
`Error occured while fetching object from async storage - key=${key}. Message stack - ${e}`
);
}
};

const removeData = async (key) => {
try {
return await AsyncStorage.removeItem(key);
} catch (e) {
console.log(
`Error occured while deleting from async storage - key=${key}. Message stack - ${e}`
);
}
};

export default {
storeData,
storeDataObject,
getData,
getDataObject,
removeData,
};
7 changes: 7 additions & 0 deletions app/store/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
*
* Maintains list of keys used for storing data/objects in async storage.
*
*/

export const USER_OBJECT_KEY = "user";
33 changes: 33 additions & 0 deletions app/views/components/ActivityIndicator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import LottieView from "lottie-react-native";
import { View, StyleSheet } from "react-native";

import colors from "../styles/colors";

function ActivityIndicator({ visible = false }) {
if (!visible) return null;

return (
<View style={styles.overlay}>
<LottieView
source={require("../../assets/animation/loader.json")}
autoPlay
loop
/>
</View>
);
}

const styles = StyleSheet.create({
overlay: {
flex: 1,
position: "absolute",
backgroundColor: colors.sb_bright,
height: "100%",
opacity: 0.8,
width: "100%",
zIndex: 1,
},
});

export default ActivityIndicator;
14 changes: 12 additions & 2 deletions app/views/components/Screen.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import React from "react";
import Constants from "expo-constants";
import { SafeAreaView, StyleSheet, View } from "react-native";
import {
SafeAreaView,
StatusBar,
StyleSheet,
View,
Keyboard,
TouchableWithoutFeedback,
} from "react-native";

/*
* Wrapper component for the screens which adds a padding to the top based on the
Expand All @@ -11,7 +18,10 @@ import { SafeAreaView, StyleSheet, View } from "react-native";
function Screen({ children, style }) {
return (
<SafeAreaView style={[styles.screen, style]}>
<View style={style}>{children}</View>
<StatusBar barStyle={"dark-content"} />
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
<View style={style}>{children}</View>
</TouchableWithoutFeedback>
</SafeAreaView>
);
}
Expand Down
46 changes: 46 additions & 0 deletions app/views/components/TextInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { StyleSheet } from "react-native";
import React from "react";
import { TextInput } from "react-native-paper";

import { colors } from "../styles";

function AppTextInput(props) {
const {
label,
value,
onChangeText = () => {},
multiline = false,
numberOfLines = 1,
disabled = false,
secureTextEntry = false,
textContentType = "none",
} = props;

return (
<TextInput
autoCapitalize="none"
autoCorrect={false}
style={styles.inputTextBox}
mode="outlined"
outlineColor={colors.sb_gray_100}
activeOutlineColor={colors.sb_blue_100}
multiline={multiline}
numberOfLines={numberOfLines}
label={label}
value={value}
onChangeText={onChangeText}
disabled={disabled}
secureTextEntry={secureTextEntry}
textContentType={textContentType}
/>
);
}

const styles = StyleSheet.create({
inputTextBox: {
backgroundColor: colors.sb_bright,
outline: "none",
},
});

export default AppTextInput;
Loading

0 comments on commit b56f381

Please sign in to comment.