Skip to content

Instantly share code, notes, and snippets.

@thorskjold

thorskjold/App.js

Last active Mar 5, 2021
Embed
What would you like to do?
import React from "react";
import firebase from "firebase";
import { createAppContainer, createSwitchNavigator } from "react-navigation";
import Login from "./screens/Login";
import LoadingScreen from "./screens/LoadingScreen";
import SignUpScreen from "./screens/SignUpScreen";
import ForgotPasswordScreen from "./screens/ForgotPasswordScreen";
import Home from "./screens/Home";
import Camera from "./screens/Camera";
import { firebaseConfig } from "./config";
import Settings from "./screens/Settings";
import AddSpotting from "./screens/AddSpotting";
import AppNavigator from "./navigation/AppNavigator";
// Safeguard to always get the same Firebase instance!
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
export default class App extends React.Component {
render() {
return <AppNavigator />;
}
}
// const AppSwitchNavigator = createSwitchNavigator({
// LoadingScreen: LoadingScreen,
// LoginScreen: Login,
// ForgotPasswordScreen: ForgotPasswordScreen,
// SignUpScreen: SignUpScreen,
// Home: Home,
// Camera: Camera,
// SettingsScreen: Settings,
// AddSpotting: AddSpotting,
// });
// const AppNavigator = createAppContainer(AppSwitchNavigator);
import React from "react";
import { createAppContainer, createSwitchNavigator } from "react-navigation";
import AddSpotting from "../screens/AddSpotting";
import Home from "../screens/Home";
import SignUpScreen from '../screens/SignUpScreen'
import ForgotPasswordScreen from '../screens/ForgotPasswordScreen'
import Login from '../screens/Login'
import DrawerNavigator from "./DrawerNavigator";
export default createAppContainer(
createSwitchNavigator({
LoginScreen: Login,
ForgotPasswordScreen: ForgotPasswordScreen,
SignUpScreen: SignUpScreen,
Main: DrawerNavigator,
Home: Home,
AddSpotting: AddSpotting,
})
);
import React from 'react';
import {View,Text} from 'react-native';
import { createDrawerNavigator } from 'react-navigation-drawer';
import Home from '../screens/Home';
import Profile from '../screens/Profile';
import Settings from '../screens/Settings';
import Camera from '../screens/Camera';
import Login from '../screens/Login';
const DrawerNavigator = createDrawerNavigator({
Home: Home,
Profile: Profile,
Settings: Settings,
Camera: Camera,
LogOut: Login,
});
export default DrawerNavigator;
import React from 'react';
import { StyleSheet, Text, View, SafeAreaView } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import AppColors from '../utils/styles';
export default class DummyLoggedIn extends React.Component {
handlePress = () => {
this.props.navigation.navigate('Home');
};
render() {
return (
<View style={styles.container}>
<SafeAreaView>
<Text>Successfully logged in! Welcome to SanITize!</Text>
<TouchableOpacity onPress={this.handlePress}>
<Text style={styles.backButton}>Go back to Home</Text>
</TouchableOpacity>
</SafeAreaView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
backButton: {
marginTop: 50,
color: AppColors.green,
},
});
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Alert } from 'react-native';
import { SafeAreaView } from 'react-navigation';
import InputField from '../components/InputField'
import AppStyles from '../utils/styles'
import * as firebase from 'firebase'
export default class ForgotPasswordScreen extends React.Component {
state = {
email: '',
}
handleEmail = (textInput) => {
this.setState({email: textInput})
}
handleGoBack = () => {
this.props.navigation.navigate('LoginScreen')
}
handleResetPassword = () => {
firebase.auth().sendPasswordResetEmail(this.state.email)
.then(() => {
Alert.alert("Password reset link has been sent.")
this.props.navigation.navigate('LoginScreen')
}, (error) => {
Alert.alert(error.message)
}
)
}
render(){
return (
<View style={styles.wrapper}>
<SafeAreaView style={styles.container}>
<Text style={styles.logo}>Reset Password</Text>
<View style={styles.inputView} >
<InputField
style={styles.inputText}
isPassword={false}
placeholder={"Email"}
value={this.state.email}
autoCapitalize={"none"}
placeholderTextColor={AppStyles.grey}
onChangeText={text => this.handleEmail(text)}/>
</View>
<TouchableOpacity style={styles.loginBtn} onPress={() => this.handleResetPassword()}>
<Text style={styles.loginText}>RESET PASSWORD</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.handleGoBack()}>
<Text style={styles.loginText}>Go back</Text>
</TouchableOpacity>
</SafeAreaView>
</View>
);
}
}
const styles = StyleSheet.create({
wrapper: {
flex: 1,
alignSelf: "stretch",
},
container: {
flex: 1,
backgroundColor: AppStyles.greyDark,
alignItems: 'center',
justifyContent: 'center',
alignContent: 'stretch',
},
logo:{
fontWeight:"bold",
fontSize:50,
color: AppStyles.green,
marginBottom:40
},
inputView:{
width:"80%",
backgroundColor: 'rgba(255,255,255,0.1)',
borderRadius:25,
height:50,
marginBottom:20,
justifyContent:"center",
padding:20
},
inputText:{
height:50,
color:"white"
},
forgot:{
color:"white",
fontSize:11
},
loginBtn:{
width:"80%",
backgroundColor: AppStyles.green,
borderRadius:25,
height:50,
alignItems:"center",
justifyContent:"center",
marginTop:15,
marginBottom:15
},
loginText:{
color:"white"
}
});
import React from "react";
import {
StyleSheet,
SafeAreaView,
Dimensions,
TouchableOpacity,
Text,
Alert,
ActivityIndicator,
Image,
Modal,
View,
Vibration,
} from "react-native";
import AppColors from "../utils/styles";
import MapView, { Marker } from "react-native-maps";
import * as Location from "expo-location";
import * as Permissions from "expo-permissions";
import generatedMapStyle from "../utils/googleMapStyle.json";
import MapDetail from "../components/MapDetail";
import store from "../store";
import { getSpots, getSpot, addSpot, deleteSpot } from "../utils/api";
import FireApi from "../utils/FirebaseApi";
import * as firebase from "firebase";
import { getDistance } from "geolib";
import Header from "../components/Header.js";
const Poop = require("../assets/spot-icons/shit.png");
const Trash = require("../assets/spot-icons/trash.png");
const Glass = require("../assets/spot-icons/glass.png");
const Syringe = require("../assets/spot-icons/syringe.png");
const Other = require("../assets/spot-icons/other.png");
export default class Home extends React.Component {
// I will probably move all location stuff to the map component.
icons = {
Poop,
Trash,
Glass,
Syringe,
Other,
};
alerts = {
Poop: "You're close to poo. Be careful not to step on it.",
Trash: "You're close to some dropped trash. Be careful not to step on it.",
Glass: "Your'e close to some broken glass. Be careful not to step on it.",
Syringe: "Your'e close to a left syringe. Be careful not to step on it.",
Other: "You might be close to somehing not nice to step on.",
};
state = {
location: null,
region: null,
spots: null,
loading: true,
error: null,
selectedSpot: null,
nearbySpot: null,
modalVisible: false,
isMounted: false,
};
getClosestSpot(currentCoords) {
let { spots } = this.state;
spots.forEach((spot) => {
spot.currentDistance = getDistance(currentCoords, spot.location, 1);
});
spots.sort((spot1, spot2) => {
if (spot1.currentDistance < spot2.currentDistance) {
return -1;
}
if (spot1.currentDistance > spot2.currentDistance) {
return 1;
}
return 0;
});
this.setState({
spots,
});
}
async componentDidMount() {
this.setState({ isMounted: true });
const spots = await FireApi.shared.retrieveAllSpotsAsync();
this.setState({ spots, loading: false });
// this.unsubscribe = store.onChange(() => {
// if (this.state.isMounted) {
// this.setState({
// loading: store.getState().isFetchingSpots,
// error: store.getState().error,
// });
// }
// });
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== "granted") {
this.setState({
permission: false,
errorMessage:
"Permission to access location was denied. To use the app, please go to your settings and give permission.",
});
} else {
this.setState({
permission: true,
errorMessage: null,
});
// To get location updates while in background you'll need to use Location.startLocationUpdatesAsync.
this.watchId = await Location.watchPositionAsync(
{
accuray: Location.Accuracy.BestForNavigation,
timeInterval: 1000,
distanceInterval: 1,
mayShowUserSettingsDialog: true,
},
(currentPosition) => {
if (this.state.spots) {
this.getClosestSpot({
latitude: currentPosition.coords.latitude,
longitude: currentPosition.coords.longitude,
});
if (this.state.spots[0]?.currentDistance <= 5) {
this.setState({
nearbySpot: this.state.spots[0],
});
Vibration.vibrate();
this.setModalVisible(true);
}
}
this.setState({
region: {
latitude: currentPosition.coords.latitude,
longitude: currentPosition.coords.longitude,
latitudeDelta: 0.005,
longitudeDelta: 0.005,
},
});
}
);
}
}
componentWillUnmount() {
// this.unsubscribe();
if (this.watchId) this.watchId.remove();
this.state.isMounted = false;
}
selectSpot(selectedSpot) {
this.setState({
selectedSpot,
});
}
unselectSpot = () => {
this.setState({
selectedSpot: null,
});
};
deleteSpot = async (id) => {
await FireApi.shared.deleteSpot(id);
const spots = this.state.spots.filter((spot) => {
return spot.id !== id;
});
this.setState({
spots,
selectedSpot: null,
});
};
setModalVisible(modalVisible) {
this.setState({
modalVisible,
});
}
render() {
const { loading, spots, region, selectedSpot, permission, errorMessage, modalVisible, nearbySpot } = this.state;
return (
<React.Fragment>
<Header />
<SafeAreaView style={styles.container}>
{nearbySpot ? (
<Modal animationType="slide" transparent={true} visible={modalVisible}>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Image source={this.icons[nearbySpot.category]} style={{ height: 50, width: 50 }} />
<Text style={styles.modalHeading}>Watch out!</Text>
<Text style={styles.modalText}>{this.alerts[nearbySpot.category]}</Text>
<TouchableOpacity
style={{ ...styles.button, backgroundColor: "#2196F3" }}
onPress={() => this.setModalVisible(false)}
>
<Text style={styles.textStyle}>Dismiss</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
) : null}
{loading && <ActivityIndicator size="large" />}
{!loading && permission ? (
<MapView
provider={MapView.PROVIDER_GOOGLE}
style={styles.map}
initialRegion={region}
customMapStyle={generatedMapStyle}
showsUserLocation={true}
>
{spots &&
spots.map((spot, index) => (
<Marker
key={index}
coordinate={spot.location}
title={spot.category}
onPress={() => this.selectSpot(spot)}
>
{selectedSpot && spot.id === selectedSpot.id ? (
<Image
source={this.icons[spot.category]}
style={{ height: 50, width: 50 }}
/>
) : (
<Image
source={this.icons[spot.category]}
style={{ height: 30, width: 30 }}
/>
)}
</Marker>
))}
</MapView>
) : (
<Text style={styles.error}>{errorMessage}</Text>
)}
<MapDetail
spot={selectedSpot}
onDeleteSpot={this.deleteSpot}
onUnselect={this.unselectSpot}
navigate={this.props.navigation.navigate}
></MapDetail>
</SafeAreaView>
</React.Fragment>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
},
header: {
flex: 1,
alignItems: "center",
},
backButton: {
marginTop: 10,
marginBottom: 10,
color: AppColors.red,
},
map: {
flex: 10,
width: Dimensions.get("window").width,
alignItems: "center",
},
mapDetail: {
flex: 2,
},
error: {
margin: 20,
textAlign: "center",
},
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
button: {
backgroundColor: "#F194FF",
borderRadius: 20,
padding: 10,
elevation: 2,
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center",
},
modalHeading: {
fontSize: 24,
marginBottom: 10,
},
modalText: {
textAlign: "center",
fontSize: 16,
marginBottom: 15,
},
});
import React from 'react';
import firebase from 'firebase';
import {
StyleSheet,
Text,
View,
ActivityIndicator,
Button,
} from 'react-native';
export default class LoadingScreen extends React.Component {
componentDidMount() {
this.checkIfLoggedIn();
}
checkIfLoggedIn = () => {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// user is logged in, navigate to next app screen
console.log('Loading Screen: User is logged in.');
this.props.navigation.navigate('Home');
} // user is not logged in, go back to login screen
else {
console.log('Loading Screen: User is not logged in.');
this.props.navigation.navigate('LoginScreen');
}
});
};
render() {
return (
<View style={styles.container}>
<ActivityIndicator size="large" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, SafeAreaView, Image, ScrollView } from 'react-native';
import Colors from '../utils/styles';
import CustomButton from '../components/Button.js';
import Tile from '../components/Tile.js';
import Header from '../components/Header.js';
import { getSpots, getSpot, addSpot, deleteSpot } from "../utils/api"
import store from "../store";
import FirebaseApi from '../utils/FirebaseApi'
/*
if(spots.uuid === FirebaseApi.shared.getUid) {
// Load kun spots for denne bruger
}
*/
export default class App extends React.Component {
onPress = () => { // Proof of concept - The button works!
console.log("hello");
}
state = {
spots: store.getState().spots,
spotLength: 1,
profileName: "Ola Nordmann",
profileImage: "https://lh4.googleusercontent.com/-oVnThGuc-os/AAAAAAAAAAI/AAAAAAAAAAA/AMZuuckHvN3K7nDfYC6-lkPKTTJWLubcRg/s96-c/photo.jpg",
};
async componentDidMount() {
const spots = await FirebaseApi.shared.retrieveAllSpotsAsync();
this.useProfileNameFromFirebase();
this.useProfileImageFromFirebase();
console.log(spots);
store.setState({ spots, isFetchingSpots: false });
this.setState({spotLength: spots.length, spots: spots})
}
useProfileNameFromFirebase = () => {
const userDisplayName = FirebaseApi.shared.getUserDisplayName();
this.setState({
profileName: userDisplayName
})
}
useProfileImageFromFirebase = () => {
const userImage = FirebaseApi.shared.getProfileImage();
this.setState({
profileImage: userImage
})
}
render() {
const spots = this.state.spots;
return (
<React.Fragment>
<Header />
<SafeAreaView style={styles.container}>
<View style={styles.profile}>
<Text style={styles.profileText}>{this.state.profileName}</Text>
<View style={styles.profileDetails}>
<Image style={{width: 40, height: 40}} source={{uri: this.state.profileImage}}></Image>
<View style={styles.smallTile}>
<Text style={styles.boldText}>Spottings</Text>
<Text>{this.state.spotLength}</Text>
</View>
<View style={styles.smallTile}>
<Text style={styles.boldText}>Cleanings</Text>
<Text>15</Text>
</View>
</View>
</View>
<View style={styles.tiles}>
<ScrollView>
{spots.map((spot, index) => (
// How do I get spot.timestamp ?
<Tile spot={spot} key={index} imageURI={spot.image}></Tile>
))}
</ScrollView>
</View>
<CustomButton text="Add trash" colorStyle="#007AFF" onPress={this.onPress} style={styles.button}> </CustomButton>
</SafeAreaView>
</React.Fragment>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
}, profile: {
height: '18%',
width: '100%',
//backgroundColor: Colors.blueDark,
}, tiles: {
height: '64%',
marginLeft: '5%'
}, profileText: {
alignSelf: 'center',
fontSize: 25,
fontWeight: 'bold',
marginBottom: 10
}, profileDetails: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center'
}, smallTile: {
display: 'flex',
flexDirection: 'column',
padding: 15,
justifyContent: "center",
alignItems: 'center',
backgroundColor: Colors.grey,
width: '30%',
borderRadius: 15,
margin: 10
}, boldText: {
fontSize: 15,
fontWeight: 'bold'
}
});
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Alert } from 'react-native';
import { SafeAreaView } from 'react-navigation';
import InputField from '../components/InputField'
import AppStyles from '../utils/styles'
import * as firebase from 'firebase'
export default class SignUpScreen extends React.Component {
state = {
email: '',
password: '',
passwordConfirm: '',
}
handleEmail = (textInput) => {
this.setState({email: textInput})
}
handlePassword = (textInput) => {
this.setState({password: textInput})
}
handlePasswordConfirm = (textInput) => {
this.setState({passwordConfirm: textInput})
}
handleGoBack = () => {
this.props.navigation.navigate('LoginScreen')
}
handleCreateUser = () => {
if(this.state.password !== this.state.passwordConfirm) {
Alert.alert("Passwords do not match!")
return
}
firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
.then(() => {
}, (error) => {
Alert.alert(error.message)
})
}
render(){
return (
<View style={styles.wrapper}>
<SafeAreaView style={styles.container}>
<Text style={styles.logo}>Sign up</Text>
<View style={styles.inputView} >
<InputField
style={styles.inputText}
isPassword={false}
placeholder={"Email"}
value={this.state.email}
autoCapitalize={"none"}
placeholderTextColor={AppStyles.grey}
onChangeText={text => this.handleEmail(text)}/>
</View>
<View style={styles.inputView} >
<InputField
style={styles.inputText}
isPassword={true}
placeholder={"Password"}
value={this.state.password}
autoCapitalize={"none"}
placeholderTextColor={AppStyles.grey}
onChangeText={text => this.handlePassword(text)}/>
</View>
<View style={styles.inputView} >
<InputField
style={styles.inputText}
isPassword={true}
placeholder={"Confirm password"}
value={this.state.passwordConfirm}
autoCapitalize={"none"}
placeholderTextColor={AppStyles.grey}
onChangeText={text => this.handlePasswordConfirm(text)}/>
</View>
<TouchableOpacity style={styles.loginBtn} onPress={() => this.handleCreateUser()}>
<Text style={styles.loginText}>CREATE USER</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.handleGoBack()}>
<Text style={styles.loginText}>Go back</Text>
</TouchableOpacity>
</SafeAreaView>
</View>
);
}
}
const styles = StyleSheet.create({
wrapper: {
flex: 1,
alignSelf: "stretch",
},
container: {
flex: 1,
backgroundColor: AppStyles.greyDark,
alignItems: 'center',
justifyContent: 'center',
alignContent: 'stretch',
},
logo:{
fontWeight:"bold",
fontSize:50,
color: AppStyles.green,
marginBottom:40
},
inputView:{
width:"80%",
backgroundColor: 'rgba(255,255,255,0.1)',
borderRadius:25,
height:50,
marginBottom:20,
justifyContent:"center",
padding:20
},
inputText:{
height:50,
color:"white"
},
forgot:{
color:"white",
fontSize:11
},
loginBtn:{
width:"80%",
backgroundColor: AppStyles.green,
borderRadius:25,
height:50,
alignItems:"center",
justifyContent:"center",
marginTop:15,
marginBottom:15
},
loginText:{
color:"white"
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment