Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MobileApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"preset": "jest-expo"
},
"dependencies": {
"base64-arraybuffer": "^0.1.5",
"expo": "^27.0.1",
"firebase": "^5.0.4",
"lodash": "^4.17.10",
Expand Down
52 changes: 29 additions & 23 deletions MobileApp/src/components/app-navigator.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
import {createStackNavigator, createBottomTabNavigator} from 'react-navigation'
import {
createStackNavigator,
createBottomTabNavigator
} from 'react-navigation'
import AuthScreen from './screens/auth'
import EventList from './screens/event-list'
import PeopleList from './screens/people-list'
import EventScreen from './screens/event'
import EventMapScreen from './screens/event-map'
import PersonAvatar from './screens/person-avatar'

const ListsNavigator = createBottomTabNavigator({
events: {
screen: EventList
},
people: {
screen: PeopleList
}
events: {
screen: EventList
},
people: {
screen: PeopleList
}
})


export default createStackNavigator({
auth: {
screen: AuthScreen,
navigationOptions: {
title: 'Auth'
}
},
lists: {
screen: ListsNavigator,
navigationOptions: {
title: 'Lists'
}
},
event: {
screen: EventMapScreen
auth: {
screen: AuthScreen,
navigationOptions: {
title: 'Auth'
}
})
},
lists: {
screen: ListsNavigator,
navigationOptions: {
title: 'Lists'
}
},
event: {
screen: EventMapScreen
},
personAvatar: {
screen: PersonAvatar
}
})
72 changes: 72 additions & 0 deletions MobileApp/src/components/people/person-avatar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { Component } from 'react'
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'
import { Camera, Permissions } from 'expo'
import { observable, action } from 'mobx'
import { observer, inject } from 'mobx-react'

@inject('people')
@inject('navigation')
@observer
class PersonAvatar extends Component {
@observable permissionAsked = false
@observable permissionGranted = false

async componentDidMount() {
this.setPermissionAsked(true)
const { status } = await Permissions.askAsync(Permissions.CAMERA)
this.setPermissionGranted(status === 'granted')
}

@action setPermissionAsked = (asked) => (this.permissionAsked = asked)
@action setPermissionGranted = (granted) => (this.permissionGranted = granted)

render() {
if (!this.permissionAsked) return <Text>Not Asked</Text>
if (!this.permissionGranted) return <Text>Not Granted</Text>

return (
<View style={styles.container}>
<Camera style={styles.camera} ref={this.setRef}>
<View>
<TouchableOpacity style={styles.button} onPress={this.takeAvatar} />
</View>
</Camera>
</View>
)
}

setRef = (ref) => {
this.camera = ref
}

takeAvatar = async () => {
const { uid, people, navigation } = this.props

if (this.camera) {
const avatar = await this.camera.takePictureAsync({ base64: true })
people.saveAvatar(uid, avatar)
}

navigation.navigate('people')
}
}

const styles = StyleSheet.create({
container: {
flex: 1
},
camera: {
flex: 1,
justifyContent: 'flex-end'
},
button: {
marginBottom: 20,
width: 60,
height: 60,
backgroundColor: 'white',
borderRadius: 30,
alignSelf: 'center'
}
})

export default PersonAvatar
68 changes: 35 additions & 33 deletions MobileApp/src/components/people/person-card.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
import React, { Component } from 'react'
import {View, Text, Image, StyleSheet} from 'react-native'
import { View, Text, Image, StyleSheet } from 'react-native'
import Card from '../common/card'

class PersonCard extends Component {
static propTypes = {
static propTypes = {}

};

render() {
const { email, firstName, lastName } = this.props.person
return (
<Card style = {styles.container}>
<Image source={{uri: 'http://lorempixel.com/200/100/people/'}} style = {styles.avatar}/>
<View style = {styles.content}>
<Text style = {styles.email}>{email}</Text>
<Text>{firstName} {lastName}</Text>
</View>
</Card>
)
}
render() {
const { email, firstName, lastName, avatar } = this.props.person
return (
<Card style={styles.container}>
{avatar ? (
<Image source={{ uri: avatar }} style={styles.avatar} />
) : null}
<View style={styles.content}>
<Text style={styles.email}>{email}</Text>
<Text>
{firstName} {lastName}
</Text>
</View>
</Card>
)
}
}

const styles = StyleSheet.create({
container: {
flexDirection: 'row'
},
avatar: {
width: 200,
height: 100,
margin: 5
},
content: {
flexDirection: 'column',
justifyContent: 'space-around',
alignItems: 'center'
},
email: {
fontWeight: 'bold'
}
container: {
flexDirection: 'row'
},
avatar: {
width: 200,
height: 100,
margin: 5
},
content: {
flexDirection: 'column',
justifyContent: 'space-around',
alignItems: 'center'
},
email: {
fontWeight: 'bold'
}
})

export default PersonCard
export default PersonCard
59 changes: 32 additions & 27 deletions MobileApp/src/components/screens/people-list.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
import React, { Component } from 'react'
import {observer, inject} from 'mobx-react'
import {View, StyleSheet, ActivityIndicator} from 'react-native'
import { observer, inject } from 'mobx-react'
import { View, StyleSheet, ActivityIndicator } from 'react-native'
import PeopleList from '../people/people-list'

@inject('people')
@observer
class PeopleListScreen extends Component {
static propTypes = {

};

static navigationOptions = {
title: 'People List'
}

componentDidMount() {
const {people} = this.props
if (!people.loaded && !people.loading) people.loadAll()
}

render() {
const {people} = this.props
if (people.loading) return this.getLoader()
return <PeopleList />
}

getLoader() {
return <View><ActivityIndicator size='large'/></View>
}
static propTypes = {}

static navigationOptions = {
title: 'People List'
}

componentDidMount() {
const { people } = this.props
if (!people.loaded && !people.loading) people.loadAll()
}

render() {
const { people } = this.props
if (people.loading) return this.getLoader()
return <PeopleList onPersonPress={this.handlePersonPress} />
}

getLoader() {
return (
<View>
<ActivityIndicator size="large" />
</View>
)
}

handlePersonPress = (uid) => {
this.props.navigation.navigate('personAvatar', { uid })
}
}

const styles = StyleSheet.create({
})
const styles = StyleSheet.create({})

export default PeopleListScreen
export default PeopleListScreen
10 changes: 10 additions & 0 deletions MobileApp/src/components/screens/person-avatar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React, { Component } from 'react'
import PersonAvatar from '../people/person-avatar'

class PersonAvatarScreen extends Component {
render() {
return <PersonAvatar uid={this.props.navigation.state.params.uid} />
}
}

export default PersonAvatarScreen
72 changes: 51 additions & 21 deletions MobileApp/src/stores/entities-store.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,64 @@
import {observable, computed, action} from 'mobx'
import { observable, computed, action } from 'mobx'
import BasicStore from './basic-store'
import firebase from 'firebase/app'
import {entitiesFromFB} from './utils'
import { entitiesFromFB } from './utils'

class EntitiesStore extends BasicStore {
@observable loading = false
@observable loaded = false
@observable loading = false
@observable loaded = false

@observable entities = {}
@observable entities = {}

@computed get list() {
return Object.values(this.entities)
}
@computed
get list() {
return Object.values(this.entities)
}

@computed get size() {
return Object.keys(this.entities).length
}
@computed
get size() {
return Object.keys(this.entities).length
}
}

export function loadAllHelper(refName) {
return action(function () {
this.loading = true

firebase.database().ref(refName)
.once('value', action(data => {
this.entities = entitiesFromFB(data.val())
this.loading = false
this.loaded = true
}))
return action(function() {
this.loading = true

firebase
.database()
.ref(refName)
.once(
'value',
action((data) => {
this.entities = entitiesFromFB(data.val())
this.loading = false
this.loaded = true
})
)
})
}

export function subscribeHelper(refName) {
return action(function() {
this.loading = true

const callback = action((data) => {
this.entities = entitiesFromFB(data.val())
this.loading = false
this.loaded = true
})

firebase
.database()
.ref(refName)
.on('value', callback)

return () =>
firebase
.database()
.ref(refName)
.off('value', callback)
})
}

export default EntitiesStore
export default EntitiesStore
Loading