mirror of
https://bitbucket.org/tagfer_team/tagfer-app.git
synced 2025-12-25 03:37:41 +00:00
UPS20-View and search all connections
This commit is contained in:
parent
5263e032b4
commit
6fd3cc46de
@ -20,6 +20,7 @@
|
||||
"react-native-gesture-handler": "^1.0.12",
|
||||
"react-native-image-picker": "^0.28.0",
|
||||
"react-native-masked-text": "^1.9.2",
|
||||
"react-native-material-menu": "^0.4.2",
|
||||
"react-native-permissions": "^1.1.1",
|
||||
"react-native-vector-icons": "^4.6.0",
|
||||
"react-native-webview": "^2.14.3",
|
||||
@ -27,16 +28,10 @@
|
||||
"realm": "^2.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/react-native": "^4.1.6",
|
||||
"babel-jest": "23.6.0",
|
||||
"eslint": "^3.19.0",
|
||||
"eslint-config-rallycoding": "^3.2.0",
|
||||
"eslint-plugin-react": "^7.12.4",
|
||||
"jest": "23.6.0",
|
||||
"metro-react-native-babel-preset": "0.51.1",
|
||||
"react-test-renderer": "16.6.3"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "react-native"
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,6 +55,10 @@ const endpoints = {
|
||||
removeConnectionRequest: {
|
||||
method: 'DELETE',
|
||||
url: `${baseurl}/connections/me`
|
||||
},
|
||||
getAllConnections: {
|
||||
method: 'GET',
|
||||
url: `${baseurl}/connections/me`
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,21 +1,257 @@
|
||||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import { View, Text, FlatList, Keyboard, TouchableOpacity } from 'react-native';
|
||||
import { SearchBar, ListItem, Icon } from 'react-native-elements';
|
||||
import Menu, { MenuItem, MenuDivider } from 'react-native-material-menu';
|
||||
|
||||
import { fetchTagferApi } from '../../utils/fetch';
|
||||
import { showFlashErrorMessage } from '../../utils/errorHandler';
|
||||
|
||||
import TagferAvatar from '../../components/new/TagferAvatar';
|
||||
import endpoints from '../../config/apiEndpoints';
|
||||
import colors from '../../config/colors.json';
|
||||
|
||||
export default class AllConnectionsScreen extends React.Component {
|
||||
|
||||
static navigationOptions = ({ navigation }) => {
|
||||
const title = navigation.getParam('title', 'All');
|
||||
return { title };
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
profileN: 0,
|
||||
dataViewable: [],
|
||||
profile0: [],
|
||||
profile1: [],
|
||||
profile2: [],
|
||||
profile3: [],
|
||||
profile4: [],
|
||||
loading: true,
|
||||
isSearch: false
|
||||
};
|
||||
|
||||
this.allProfiles = [];
|
||||
this.sortMenu = null;
|
||||
this.onFilter = this.onFilter.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.onLoad();
|
||||
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => this.searchMode());
|
||||
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidHide', () => this.setState({ isSearch: false }));
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.keyboardDidShowListener.remove();
|
||||
}
|
||||
|
||||
onFilter(profileN) {
|
||||
this.setState({ profileN, dataViewable: this.state[`profile${profileN}`] });
|
||||
}
|
||||
|
||||
async onLoad() {
|
||||
const response = await fetchTagferApi(endpoints.getAllConnections);
|
||||
if (response.error) {
|
||||
return showFlashErrorMessage(response.error);
|
||||
}
|
||||
|
||||
const { profile1, profile2, profile3, profile4 } = response;
|
||||
this.allProfiles = [...profile1, ...profile2, ...profile3, ...profile4];
|
||||
this.allProfiles.sort(this.compareBy('tagferId'));
|
||||
|
||||
this.setState({
|
||||
dataViewable: this.allProfiles,
|
||||
profile0: this.allProfiles,
|
||||
profile1,
|
||||
profile2,
|
||||
profile3,
|
||||
profile4,
|
||||
loading: false
|
||||
});
|
||||
this.updateTitle();
|
||||
}
|
||||
|
||||
onSearch(text) {
|
||||
const profile0 = this.allProfiles.filter(profile => (
|
||||
profile.fullName.toLowerCase().includes(text.toLowerCase())
|
||||
|| profile.tagferId.toLowerCase().includes(text.toLowerCase())
|
||||
));
|
||||
this.setState((state) => {
|
||||
if (state.profileN === 0) {
|
||||
return { profile0, dataViewable: profile0 };
|
||||
}
|
||||
|
||||
return { profile0 };
|
||||
});
|
||||
}
|
||||
|
||||
onSort(attribute) {
|
||||
const { profileN } = this.state;
|
||||
const sorted = this.state[`profile${profileN}`].sort(this.compareBy(attribute));
|
||||
|
||||
this.setState({ dataViewable: sorted });
|
||||
this.sortMenu.hide();
|
||||
}
|
||||
|
||||
searchMode() {
|
||||
this.setState((state) => {
|
||||
if (state.profileN !== 0) {
|
||||
return { profileN: 0, dataViewable: this.allProfiles, isSearch: true };
|
||||
}
|
||||
|
||||
return { isSearch: true };
|
||||
});
|
||||
}
|
||||
|
||||
updateTitle() {
|
||||
let numOfContacts = this.allProfiles.length;
|
||||
if (numOfContacts > 1000 && numOfContacts < 1000000) { numOfContacts = `${Math.floor(numOfContacts / 1000)}k`; }
|
||||
if (numOfContacts > 1000000) { numOfContacts = `${Math.floor(numOfContacts / 1000000)}m`; }
|
||||
|
||||
this.props.navigation.setParams({ title: `All(${numOfContacts})` });
|
||||
}
|
||||
|
||||
compareBy(attribute) {
|
||||
return (item1, item2) => {
|
||||
if (item1[attribute] > item2[attribute]) {
|
||||
return 1;
|
||||
} else if (item1[attribute] < item2[attribute]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
renderItem(item) {
|
||||
return <UserListItem profile={item} onPress={() => console.log(1)} />;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>All Contacts</Text>
|
||||
<SearchBar
|
||||
lightTheme
|
||||
placeholder='Search Contacts'
|
||||
clearIcon
|
||||
inputStyle={{ fontSize: 15 }}
|
||||
onChangeText={(text) => this.onSearch(text)}
|
||||
autoCorrect={false}
|
||||
/>
|
||||
|
||||
<SortMenu
|
||||
setMenu={ref => (this.sortMenu = ref)}
|
||||
showMenu={() => this.sortMenu.show()}
|
||||
onPress={(attribute) => this.onSort(attribute)}
|
||||
/>
|
||||
|
||||
<FilterBar currFilter={this.state.profileN} onFilter={this.onFilter} isSearch={this.state.isSearch} />
|
||||
|
||||
<FlatList
|
||||
data={this.state.dataViewable}
|
||||
extraData={this.state}
|
||||
renderItem={({ item, index }) => this.renderItem(item, index)}
|
||||
keyExtractor={(item) => item.tagferId}
|
||||
style={{ flex: 1, marginHorizontal: 10, marginTop: 10, borderRadius: 5 }}
|
||||
refreshing={this.state.loading}
|
||||
/>
|
||||
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const UserListItem = ({ profile, onPress }) => {
|
||||
const { tagferId, fullName, jobTitle, companyName, photoURL } = profile;
|
||||
const subtitle = `@${tagferId}\n${jobTitle} at ${companyName}`;
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
roundAvatar
|
||||
avatar={<TagferAvatar size='medium' photoURL={photoURL} color={colors.lightGrey} />}
|
||||
title={fullName}
|
||||
subtitle={subtitle}
|
||||
subtitleNumberOfLines={3}
|
||||
subtitleStyle={{ fontSize: 12, fontWeight: 'normal' }}
|
||||
titleStyle={{ fontSize: 16, color: 'black' }}
|
||||
containerStyle={{ backgroundColor: 'white' }}
|
||||
onPress={onPress}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const FilterBar = ({ currFilter, onFilter, isSearch }) => (
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
||||
<ProfileFilter profileN={0} currFilter={currFilter} onPress={() => onFilter(0)} disabled={isSearch} />
|
||||
<ProfileFilter profileN={1} currFilter={currFilter} onPress={() => onFilter(1)} disabled={isSearch} />
|
||||
<ProfileFilter profileN={2} currFilter={currFilter} onPress={() => onFilter(2)} disabled={isSearch} />
|
||||
<ProfileFilter profileN={3} currFilter={currFilter} onPress={() => onFilter(3)} disabled={isSearch} />
|
||||
<ProfileFilter profileN={4} currFilter={currFilter} onPress={() => onFilter(4)} disabled={isSearch} />
|
||||
</View>
|
||||
);
|
||||
|
||||
const ProfileFilter = ({ profileN, currFilter, onPress, disabled }) => {
|
||||
const title = profileN === 0 ? 'All' : `Profile ${profileN}`;
|
||||
const isSelected = currFilter === profileN;
|
||||
return (
|
||||
<TouchableOpacity activeOpacity={0.5} style={styles.profileButton(isSelected)} onPress={onPress} disabled={disabled}>
|
||||
<Text style={styles.profileButtonTitle(isSelected)}>{title}</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
const SortButton = ({ onPress }) => (
|
||||
<TouchableOpacity activeOpacity={0.8} style={styles.sortButton} onPress={onPress}>
|
||||
<Icon name='chevron-up' type='font-awesome' color='white' size={9} />
|
||||
<Text style={styles.sortButtonTitle}>AZ</Text>
|
||||
<Icon name='chevron-down' type='font-awesome' color='white' size={9} />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
const SortMenu = ({ setMenu, showMenu, onPress }) => (
|
||||
<View style={styles.sortMenu}>
|
||||
<Menu ref={setMenu} button={<SortButton onPress={showMenu} />}>
|
||||
<MenuItem onPress={() => onPress('fullName')} style={{ height: 36 }}>Name</MenuItem>
|
||||
<MenuDivider />
|
||||
<MenuItem onPress={() => onPress('tagferId')} style={{ height: 36 }}>Tagfer ID</MenuItem>
|
||||
</Menu>
|
||||
</View>
|
||||
);
|
||||
|
||||
const styles = {
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#F5F8FA'
|
||||
},
|
||||
sortButton: {
|
||||
backgroundColor: '#AAAFC4',
|
||||
borderRadius: 5,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}
|
||||
paddingHorizontal: 5,
|
||||
marginRight: 10
|
||||
},
|
||||
sortButtonTitle: {
|
||||
fontSize: 13,
|
||||
fontWeight: 'bold',
|
||||
color: 'white'
|
||||
},
|
||||
sortMenu: {
|
||||
alignItems: 'flex-end',
|
||||
marginTop: 10
|
||||
},
|
||||
profileButton: (isSelected) => ({
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
height: 30,
|
||||
justifyContent: 'flex-end',
|
||||
borderBottomWidth: 2,
|
||||
borderColor: isSelected ? '#FF7C41' : '#B3B8CA'
|
||||
}),
|
||||
profileButtonTitle: (isSelected) => ({
|
||||
textAlign: 'center',
|
||||
fontSize: 15,
|
||||
color: isSelected ? '#416788' : '#ACACAC',
|
||||
fontWeight: isSelected ? 'bold' : 'normal'
|
||||
})
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user