In last article we implemented age filter( http://calsob.in/how-to-build-a-dating-app-using-react-native-and-firebase-part-1/ ). So, we were able to filter user by there age. In this article we will add height filter and then we will be able to filter users by there age and height, both.
For age filter we user two sliders to input of users age range. For height filter we will do something similar, but, its a bit more complicated, because we will have to use four slider components. Age range will be in feet and inches and thats why we will need four sliders for height range. Now enough talk, lets start coding.
First we will add some code to our Profile component. Here is the new code of Profile component :
import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, View, Button } from 'react-native'; import firebase from 'firebase' export default class Profile extends Component { constructor(props) { super(props) this.state = { user: this.props.screenProps } } componentWillUnmount() { const { uid } = this.state.user this.firebaseRef.child(uid).child('dp').off('value') } componentDidMount(){ //console.warn("Profile"); const { uid } = this.state.user this.firebaseRef = firebase.database().ref('users') this.firebaseRef.child(uid).on('value', snap => { const user = snap.val() this.setState({ user: user, SwitchGender: user.filterGender }) }) } toggleGender(value){ let user = this.state.user const userData = { filterGender: value } firebase.database().ref('users').child(user.uid).update({ ...userData}) this.setState({SwitchGender: value}) } render() { return ( <View style={styles.container}> <Button onPress={() => this.props.navigation.navigate('Age', { user: this.state.user })} title={ "Age("+this.state.user.ageRange[0]+"yrs "+"to"+this.state.user.ageRange[1]+"yrs)" } /> <Button onPress={() => this.props.navigation.navigate('Height', { user: this.state.user })} title={"Height("+this.state.user.heightRange[0]+"'"+this.state.user.heightRange[1]+'"'+"to"+this.state.user.heightRange[2]+"'"+this.state.user.heightRange[3]+'"'+")"} /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, });
We have added one more button, Height button, below the Age button. On pressing the height button the user will be navigated to Height component, with his login info as parameter.
Now, lets add code for Height component :
import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, View, Slider } from 'react-native'; import firebase from 'firebase' export default class Height extends Component { constructor(props) { super(props) this.state = { user: this.props.navigation.state.params.user, heightfromft: 4, heightfromin: 5, heighttoft:7, heighttoin: 0 } } componentDidMount(){ const { heightRange } = this.state.user this.setState({ heightfromft: heightRange[0],heightfromin: heightRange[1],heighttoft: heightRange[2],heighttoin: heightRange[3] }) this.heightfromft = heightRange[0] this.heightfromin = heightRange[1] this.heighttoft = heightRange[2] this.heighttoin = heightRange[3] } toinches(ft,inch){ totalInch = ft*12+inch return totalInch } setheightftfrom(val){ const valtoin = this.toinches(val,this.heightfromin) const totalheightto = this.toinches(this.heighttoft,this.heighttoin) if(valtoin<totalheightto) this.setState({ heightfromft: val }) } getheightftfrom(val){ const valtoin = this.toinches(val,this.heightfromin) const totalheightto = this.toinches(this.heighttoft,this.heighttoin) if(valtoin<totalheightto){ const { uid } = this.state.user const userData = { heightRange: [val, this.heightfromin, this.heighttoft, this.heighttoin ] } this.heightfromft = val firebase.database().ref('users').child(uid).update({ ...userData}) }else{ this.setState({ heightfromft: this.heightfromft }) } } setheightftto(val){ const valtoin = this.toinches(val,this.heighttoin) const totalheightfrom = this.toinches(this.heightfromft,this.heightfromin) if(valtoin>totalheightfrom) this.setState({ heighttoft: val }) } getheightftto(val){ const valtoin = this.toinches(val,this.heighttoin) const totalheightfrom = this.toinches(this.heightfromft,this.heightfromin) if(valtoin>totalheightfrom){ const { uid } = this.state.user const userData = { heightRange: [this.heightfromft, this.heightfromin, val, this.heighttoin ] } this.heighttoft = val firebase.database().ref('users').child(uid).update({ ...userData}) }else{ this.setState({ heighttoft: this.heighttoft }) } } setheightinfrom(val){ const valtoin = this.toinches(this.heightfromft,val) const totalheightto = this.toinches(this.heighttoft,this.heighttoin) if(valtoin<totalheightto) this.setState({ heightfromin: val }) } getheightinfrom(val){ const valtoin = this.toinches(this.heightfromft,val) const totalheightto = this.toinches(this.heighttoft,this.heighttoin) if(valtoin<totalheightto){ const { uid } = this.state.user const userData = { heightRange: [this.heightfromft, val, this.heighttoft, this.heighttoin ] } this.heightfromin = val firebase.database().ref('users').child(uid).update({ ...userData}) }else{ this.setState({ heightfromin: this.heightfromin }) } } setheightinto(val){ const valtoin = this.toinches(this.heighttoft,val) const totalheightto = this.toinches(this.heightfromft,this.heightfromin) if(valtoin>totalheightto) this.setState({ heighttoin: val }) } getheightinto(val){ const valtoin = this.toinches(this.heighttoft,val) const totalheightto = this.toinches(this.heightfromft,this.heightfromin) if(valtoin>totalheightto){ const { uid } = this.state.user const userData = { heightRange: [this.heightfromft, this.heightfromin, this.heighttoft, val ] } this.heighttoin = val firebase.database().ref('users').child(uid).update({ ...userData}) }else{ this.setState({ heighttoin: this.heighttoin }) } } render() { return ( <View style={styles.container}> <Text style={styles.instructions}> height from : </Text> <Slider style={{ width: 150 }} step={1} minimumValue={4} maximumValue={7} value={this.state.heightfromft} onValueChange={ val => this.setheightftfrom(val) } onSlidingComplete={ val => this.getheightftfrom(val) } /> <Slider style={{ width: 300 }} step={1} minimumValue={0} maximumValue={11} value={this.state.heightfromin} onValueChange={ val => this.setheightinfrom(val) } onSlidingComplete={ val => this.getheightinfrom(val) } /> <Text style={styles.welcome}> {this.state.heightfromft+' ft '+this.state.heightfromin+' in'} </Text> <Text style={styles.instructions}> height to : </Text> <Slider style={{ width: 150 }} step={1} minimumValue={4} maximumValue={7} value={this.state.heighttoft} onValueChange={ val => this.setheightftto(val) } onSlidingComplete={ val => this.getheightftto(val) } /> <Slider style={{ width: 300 }} step={1} minimumValue={0} maximumValue={11} value={this.state.heighttoin} onValueChange={ val => this.setheightinto(val) } onSlidingComplete={ val => this.getheightinto(val) } /> <Text style={styles.welcome}> {this.state.heighttoft+' ft '+this.state.heighttoin+' in'} </Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, });
In the above code we have used four slider component. The first slider take input of height in feet and the second slider takes input of height in inches. The first two slider takes input of lower part of the height range. Similarly, the the third and fourth slider takers input of higher part of height range. In the above code, we are also validating that the lower part never exceeds the higher part. In ‘onSlidingComplete’ event of slider we are updating the height range in the database.
Now, Lets update code in Match Component so that the members list updates when user changes height range. Here is the code for Match component :
import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, View, ListView, Image } from 'react-native'; import _ from 'lodash' import moment from 'moment' import firebase from 'firebase' export default class Match extends Component { constructor(props) { super(props) const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); this.state = { user: this.props.screenProps, dataSource: ds.cloneWithRows([]), } } componentDidMount(){ const { uid } = this.state.user this.firebaseRef = firebase.database().ref('users') this.firebaseRef.on('value', snap => { let users = snap.val(); const rejectMe = _.reject(users, user => user.uid === uid) const filterMe = _.filter(users, user => user.uid === uid) const user = filterMe[0]; /* Age filter start */ const userBday = moment(user.birthday, 'MM/DD/YYYY') const userAge = moment().diff(userBday, 'years') const filterByAge = _.filter(rejectMe, profile => { const profileBday = moment(profile.birthday, 'MM/DD/YYYY') const profileAge = moment().diff(profileBday, 'years') const inRangeUser = _.inRange(profileAge, user.ageRange[0], user.ageRange[1] + 1) const inRangeProfile = _.inRange(userAge, profile.ageRange[0], profile.ageRange[1] + 1) return inRangeUser && inRangeProfile }) /* Age filter end */ /* Height filter start */ const userheightin = user.height[0]*12+user.height[1] const userheightrangefrom = user.heightRange[0]*12+user.heightRange[1] const userheightrangeto = user.heightRange[2]*12+user.heightRange[3] const filterByHeight = _.filter(filterByAge, profile => { const profileheightin = profile.height[0]*12+profile.height[1] const profileheightrangefrom = profile.heightRange[0]*12+profile.heightRange[1] const profileheightrangeto = profile.heightRange[2]*12+profile.heightRange[3] const inRangeUserHeight = _.inRange(profileheightin, userheightrangefrom, userheightrangeto + 1) const inRangeProfileHeight = _.inRange(userheightin, profileheightrangefrom, profileheightrangeto + 1) return inRangeUserHeight && inRangeProfileHeight }) /* Height filter end */ const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); this.setState({ dataSource: ds.cloneWithRows(filterByHeight) }) }) } renderRow(rowData, sectionID, rowID) { return ( <View style={styles.rowContainer}> <Image source={{ uri: rowData.dp }} style={styles.photo} /> <Text style={styles.text}> {`${rowData.first_name} ${rowData.last_name}`} </Text> </View> ) } render() { return ( <ListView enableEmptySections={true} removeClippedSubviews={false} style={styles.container} dataSource={this.state.dataSource} renderRow={this.renderRow.bind(this)} /> ); } } const styles = StyleSheet.create({ container: { flex: 1, marginTop: 20, }, rowContainer: { flex: 1, padding: 12, flexDirection: 'row', alignItems: 'center', }, text: { marginLeft: 12, fontSize: 16, }, photo: { height: 40, width: 40, borderRadius: 20, }, });
In the above code, we are taking the result of age filter i.e. ‘filterByAge’ and passing it through the height filter. Next, we are taking the result of height filter i.e. ‘filterByHeight’ and passing it as data source to ListView component.