Skip to content
This repository was archived by the owner on Jan 8, 2021. It is now read-only.

Commit e2f8a68

Browse files
author
andela-akhenda
committed
feat(profile): create profile page
1 parent a6a91b3 commit e2f8a68

File tree

3 files changed

+246
-2
lines changed

3 files changed

+246
-2
lines changed

src/components/DrawerContent.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import styles from './styles/DrawerContentStyles';
1111
class DrawerContent extends Component {
1212
renderMenuItem(icon, action, title, color, style) {
1313
return (
14-
<TouchableOpacity onPress={action} style={[styles.menuItem, style]}>
14+
<TouchableOpacity key={icon} onPress={action} style={[styles.menuItem, style]}>
1515
<Icon name={icon} style={[styles.menuItemIcon, { color }]} />
1616
<Text style={styles.menuItemText}>{title}</Text>
1717
</TouchableOpacity>
@@ -41,7 +41,7 @@ class DrawerContent extends Component {
4141
<Text style={styles.profileButtonText}>Profile</Text>
4242
</Button>
4343
</View>
44-
<Image source={images.avatar} style={styles.avatar} />
44+
<Image source={{ uri: user.avatar_urls['96'] }} style={styles.avatar} />
4545
<View style={styles.menuItems}>
4646
{this.renderMenuItem('home', Actions.home, 'Home', 'blue')}
4747
{this.renderMenuItem('settings', Actions.home, 'Settings', 'black', styles.lastMenuItem)}

src/containers/ProfileScreen.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import React, { Component } from 'react';
2+
import PropTypes from 'prop-types';
3+
import { View, Image, TouchableOpacity, ActivityIndicator } from 'react-native';
4+
import { connect } from 'react-redux';
5+
import { Container, Content, Button, Text, Tab, Tabs, Icon } from 'native-base';
6+
import { Actions } from 'react-native-router-flux';
7+
8+
import { images } from 'src/theme';
9+
import LoadingIndicator from 'src/components/LoadingIndicator';
10+
import styles from './styles/ProfileScreenStyles';
11+
12+
13+
class ProfileScreen extends Component {
14+
constructor(props) {
15+
super(props);
16+
17+
this.state = {
18+
loading: false,
19+
};
20+
}
21+
22+
renderItem = (item) => {
23+
return (
24+
<TouchableOpacity key={item.id} style={styles.itemContainer}>
25+
<View style={styles.itemLoading}>
26+
<ActivityIndicator size="small" />
27+
</View>
28+
<Image
29+
style={styles.item}
30+
source={{ uri: item.featured_image_url[0] }}
31+
/>
32+
<View style={styles.itemTextContainer}>
33+
<Text style={styles.itemText}>{item.title.rendered}</Text>
34+
</View>
35+
</TouchableOpacity>
36+
);
37+
}
38+
39+
renderEmpty(message) {
40+
return (
41+
<View style={styles.empty}>
42+
<Text style={styles.emptyText}>{message}</Text>
43+
</View>
44+
);
45+
}
46+
47+
render() {
48+
const { user } = this.props;
49+
if (this.state.loading) return <LoadingIndicator />;
50+
51+
return (
52+
<Container style={styles.container}>
53+
<Content bounces={false} style={styles.content}>
54+
<View style={styles.headerBanner}>
55+
<Image source={images.banner} style={styles.banner} />
56+
<View style={styles.backgroundMask} />
57+
<Image source={{ uri: user.avatar_urls['96'] }} style={styles.avatar} />
58+
<Button transparent style={styles.leftMenuButton} onPress={Actions.pop}>
59+
<Icon name='arrow-back' style={styles.menuButton} />
60+
</Button>
61+
<Button transparent style={styles.rightMenuButton}>
62+
<Icon name='create' style={styles.menuButton} />
63+
</Button>
64+
</View>
65+
<View style={styles.info}>
66+
<Text style={styles.name}>{(user.name || user.username).toUpperCase()}</Text>
67+
<Text style={styles.bio}>
68+
{user.description || '~ Use the online portal to update your bio ~'}
69+
</Text>
70+
<Button rounded light bordered small style={styles.button}>
71+
<Text style={styles.buttonText}>Edit Profile</Text>
72+
</Button>
73+
</View>
74+
<Tabs initialPage={0}>
75+
<Tab heading="Favourites">
76+
{Object.keys(this.props.favourites).length > 0
77+
? <View style={styles.itemWrapper}>
78+
{Object.keys(this.props.favourites)
79+
.map(item => this.renderItem(this.props.favourites[item]))}
80+
</View>
81+
: this.renderEmpty('You have not saved any items ¯\\_(ツ)_/¯')}
82+
</Tab>
83+
<Tab heading="My Items">
84+
{this.renderEmpty('You do not have any items on our platform')}
85+
</Tab>
86+
<Tab heading="Feed">
87+
{this.renderEmpty('Feature coming soon...')}
88+
</Tab>
89+
</Tabs>
90+
</Content>
91+
</Container>
92+
);
93+
}
94+
}
95+
96+
ProfileScreen.propTypes = {
97+
user: PropTypes.object,
98+
favourites: PropTypes.object,
99+
};
100+
101+
const mapStateToProps = (state) => {
102+
return {
103+
user: state.auth.user,
104+
favourites: state.app.favourites,
105+
};
106+
};
107+
108+
export default connect(mapStateToProps, null)(ProfileScreen);
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import { StyleSheet, Platform } from 'react-native';
2+
3+
import { colors, metrics } from 'src/theme';
4+
5+
const styles = StyleSheet.create({
6+
container: {
7+
flex: 1,
8+
backgroundColor: colors.primary.text,
9+
},
10+
content: {
11+
flex: 1,
12+
},
13+
headerBanner: {
14+
height: metrics.screenHeight * 0.33,
15+
alignItems: 'center',
16+
},
17+
banner: {
18+
width: metrics.screenWidth,
19+
height: metrics.screenHeight * 0.33,
20+
resizeMode: 'cover',
21+
},
22+
backgroundMask: {
23+
position: 'absolute',
24+
top: 0,
25+
left: 0,
26+
right: 0,
27+
bottom: 0,
28+
backgroundColor: colors.statusBarTranslucentDarker,
29+
},
30+
avatar: {
31+
width: 80,
32+
height: 80,
33+
borderWidth: 5,
34+
marginTop: -40,
35+
borderRadius: 40,
36+
resizeMode: 'cover',
37+
borderColor: colors.primary.text,
38+
},
39+
leftMenuButton: {
40+
position: 'absolute',
41+
top: Platform.OS === 'ios' ? 15 : 20,
42+
left: 3,
43+
},
44+
rightMenuButton: {
45+
position: 'absolute',
46+
top: Platform.OS === 'ios' ? 15 : 20,
47+
right: 3,
48+
},
49+
menuButton: {
50+
color: colors.primary.text,
51+
},
52+
info: {
53+
padding: 15,
54+
paddingTop: 50,
55+
alignItems: 'center',
56+
justifyContent: 'center',
57+
},
58+
name: {
59+
fontSize: 14,
60+
fontWeight: '800',
61+
marginBottom: 10,
62+
},
63+
bio: {
64+
fontSize: 13,
65+
marginBottom: 15,
66+
textAlign: 'center',
67+
color: colors.lightestText,
68+
},
69+
button: {
70+
marginTop: 10,
71+
marginBottom: 20,
72+
alignSelf: 'center',
73+
borderColor: colors.primary.lighter,
74+
},
75+
buttonText: {
76+
color: colors.primary.main,
77+
},
78+
79+
itemWrapper: {
80+
flexDirection: 'row',
81+
flexWrap: 'wrap',
82+
},
83+
itemContainer: {
84+
width: metrics.screenWidth / 3,
85+
height: metrics.screenWidth / 3,
86+
// margin: metrics.screenWidth / (4/600),
87+
},
88+
itemLoading: {
89+
position: 'absolute',
90+
top: 0,
91+
left: 0,
92+
right: 0,
93+
bottom: 0,
94+
alignItems: 'center',
95+
justifyContent: 'center',
96+
backgroundColor: colors.primary.lightest,
97+
},
98+
item: {
99+
position: 'absolute',
100+
top: 0,
101+
left: 0,
102+
width: '100%',
103+
height: '100%',
104+
resizeMode: 'cover',
105+
},
106+
itemTextContainer: {
107+
width: metrics.screenWidth / 3,
108+
height: metrics.screenWidth / 3,
109+
borderRadius: 5,
110+
overflow: 'hidden',
111+
alignItems: 'center',
112+
justifyContent: 'center',
113+
},
114+
itemText: {
115+
padding: 5,
116+
fontSize: 17,
117+
borderRadius: 5,
118+
textAlign: 'center',
119+
color: colors.primary.text,
120+
textAlignVertical: 'center',
121+
backgroundColor: colors.statusBarTranslucentDark,
122+
},
123+
124+
empty: {
125+
justifyContent: 'center',
126+
width: metrics.screenWidth,
127+
height: metrics.screenHeight * 0.35,
128+
},
129+
emptyText: {
130+
fontSize: 18,
131+
textAlign: 'center',
132+
color: colors.lightestText,
133+
},
134+
});
135+
136+
export default styles;

0 commit comments

Comments
 (0)