├── .buckconfig
├── .expo-shared
└── assets.json
├── .gitattributes
├── .gitignore
├── App.js
├── README.md
├── __tests__
└── App.js
├── app.json
├── assets
└── icons
│ ├── app-icon.png
│ ├── loading-icon-512.png
│ └── loading-icon.png
├── babel.config.js
├── components
├── Nav.js
├── NavAbsolute.js
└── index.js
├── constants
├── Colors.js
└── index.js
├── images
├── iphone11-giphy.gif
└── pixel2-giphy.gif
├── index.js
├── metro.config.js
├── mocks
└── contact.json
├── package-lock.json
├── package.json
├── screens
├── Product1
│ ├── PhotoButton.js
│ ├── Product.js
│ ├── ProductStyle.js
│ ├── index.js
│ └── product.json
├── Profile1
│ ├── Email.js
│ ├── Profile.js
│ ├── Separator.js
│ ├── Tel.js
│ ├── constants.js
│ └── index.js
├── Profile2
│ ├── Post.js
│ ├── Posts.js
│ ├── Profile.js
│ └── index.js
├── Profile3
│ ├── Post.js
│ ├── Posts.js
│ ├── Profile.js
│ ├── ProfileStyle.js
│ ├── contact.json
│ └── index.js
└── Setting1
│ ├── Chevron.js
│ ├── Icon.js
│ ├── InfoText.js
│ ├── Options.js
│ ├── Setting.js
│ └── index.js
└── utils
├── datetime.js
├── image.js
└── index.js
/.buckconfig:
--------------------------------------------------------------------------------
1 |
2 | [android]
3 | target = Google Inc.:Google APIs:23
4 |
5 | [maven_repositories]
6 | central = https://repo1.maven.org/maven2
7 |
--------------------------------------------------------------------------------
/.expo-shared/assets.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IntelliJ
26 | #
27 | build/
28 | .idea
29 | .gradle
30 | local.properties
31 | *.iml
32 |
33 | # node.js
34 | #
35 | node_modules/
36 | npm-debug.log
37 | yarn-error.log
38 |
39 | # BUCK
40 | buck-out/
41 | \.buckd/
42 | *.keystore
43 |
44 | # fastlane
45 | #
46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 | # screenshots whenever they are needed.
48 | # For more information about the recommended setup visit:
49 | # https://docs.fastlane.tools/best-practices/source-control/
50 |
51 | */fastlane/report.xml
52 | */fastlane/Preview.html
53 | */fastlane/screenshots
54 |
55 | # Bundle artifacts
56 | *.jsbundle
57 |
58 | # CocoaPods
59 | /ios/Pods/
60 |
61 | # Expo
62 | .expo/*
63 | web-build/
64 |
--------------------------------------------------------------------------------
/App.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { Icon } from 'react-native-elements'
3 | import { NavigationContainer } from '@react-navigation/native'
4 | import { createStackNavigator } from '@react-navigation/stack'
5 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
6 | import PropTypes from 'prop-types'
7 |
8 | import Profile1 from './screens/Profile1'
9 | import Profile2 from './screens/Profile2'
10 | import Profile3 from './screens/Profile3'
11 | import Setting1 from './screens/Setting1'
12 |
13 | import Product1 from './screens/Product1'
14 |
15 | import SettingOption1 from './screens/Setting1/Options'
16 |
17 | const Setting1Stack = createStackNavigator()
18 | function SettingsStackScreen() {
19 | return (
20 |
21 |
22 |
23 |
24 | )
25 | }
26 |
27 | const Product1Stack = createStackNavigator()
28 | function Product1StackScreen() {
29 | return (
30 |
31 |
32 |
33 | )
34 | }
35 |
36 | const Profile1Stack = createStackNavigator()
37 | function Profile1StackScreen() {
38 | return (
39 |
44 |
45 |
46 | )
47 | }
48 |
49 | const Profile2Stack = createStackNavigator()
50 | function Profile2StackScreen() {
51 | return (
52 |
57 |
58 |
59 | )
60 | }
61 |
62 | const Profile3Stack = createStackNavigator()
63 | function Profile3StackScreen() {
64 | return (
65 |
70 |
71 |
72 | )
73 | }
74 | const Tab = createBottomTabNavigator()
75 |
76 | const HomeIcon = ({ focused, tintColor }) => (
77 |
83 | )
84 |
85 | export default function App() {
86 | return (
87 |
88 | ({
90 | tabBarIcon: props =>
91 | })}
92 | tabBarOptions={{
93 | activeTintColor: 'tomato',
94 | inactiveTintColor: 'gray',
95 | showLabel: false,
96 | showIcon: true,
97 | indicatorStyle: {
98 | backgroundColor: 'transparent',
99 | },
100 | labelStyle: {
101 | fontSize: 12,
102 | },
103 | iconStyle: {
104 | width: 30,
105 | height: 30,
106 | },
107 | style: {
108 | // backgroundColor: 'transparent',
109 | justifyContent: 'center',
110 | },
111 | }}
112 | >
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | )
121 | }
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-user-profile
2 | []()
3 | []()
4 | [](https://snyk.io/test/github/nattatorn-dev/react-native-user-profile?targetFile=package.json)
5 | []()
6 | []()
7 |
8 | A react native mobile starter kit, Examples of user profiles screens to help you create component and design 🎨
9 |
10 | ## Expo 38.0.9
11 | ## Find it on Expo
12 | https://expo.io/@nattatorn-dev/expo-react-native-user-profile
13 |
14 | Scan QR Code and Sharing does not support ios
15 | https://blog.expo.io/upcoming-limitations-to-ios-expo-client-8076d01aee1a
16 |
17 | ## Example
18 | Iphone11
19 | 
20 |
21 | Pixel2
22 | 
23 |
24 | ## Profile1
25 | 
26 |
27 | ## Profile2
28 | 
29 |
30 | ## Profile3
31 | 
32 |
33 | ## Profile4
34 | 
35 |
36 | ## Product1
37 | 
38 |
39 | ## Features
40 | - Carefully crafted user experience and design
41 | - Clean and comprehensive codebase
42 |
43 | ## Install
44 | - Git clone the repository.
45 | - In the repo directory, run "npm install" to install dependencies
46 | - If you have a problem with react-natigation, Do this https://reactnavigation.org/docs/getting-started
47 | - Run "exp start" to initiate expo. Then, you will see instructions to run a demo on a real device or a simulator.
48 |
49 |
50 | ## Made with help of
51 | - [react-native](https://github.com/facebook/react-native)
52 | - [react-native-elements](https://github.com/react-native-training/react-native-elements)
53 | - [react-navigation](https://github.com/react-community/react-navigation)
54 | - [react-native-tab-view](https://github.com/react-native-community/react-native-tab-view)
55 |
56 | ## License
57 | [MIT](LICENSE) license.
58 |
59 | ## How can I support developers?
60 | - Star our GitHub repo :star:
61 | - Create pull requests, submit bugs, suggest new features or documentation updates :wrench:
62 |
63 | We're always happy to receive your feedback!
64 |
--------------------------------------------------------------------------------
/__tests__/App.js:
--------------------------------------------------------------------------------
1 | import 'react-native';
2 | import React from 'react';
3 | import App from '../App';
4 |
5 | // Note: test renderer must be required after react-native.
6 | import renderer from 'react-test-renderer';
7 |
8 | it('renders correctly', () => {
9 | renderer.create();
10 | });
11 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "expo-react-native-user-profile",
3 | "displayName": "expo react native user profile",
4 | "expo": {
5 | "name": "expo-react-native-user-profile",
6 | "description": "An empty new project",
7 | "slug": "expo-react-native-user-profile",
8 | "version": "1.0.0",
9 | "assetBundlePatterns": [
10 | "**/*"
11 | ]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/assets/icons/app-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nattatorn-dev/react-native-user-profile/1b3a05983fa4af4b1c52f9fbe107fd2c3b44083a/assets/icons/app-icon.png
--------------------------------------------------------------------------------
/assets/icons/loading-icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nattatorn-dev/react-native-user-profile/1b3a05983fa4af4b1c52f9fbe107fd2c3b44083a/assets/icons/loading-icon-512.png
--------------------------------------------------------------------------------
/assets/icons/loading-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nattatorn-dev/react-native-user-profile/1b3a05983fa4af4b1c52f9fbe107fd2c3b44083a/assets/icons/loading-icon.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function(api) {
2 | api.cache(true);
3 | return {
4 | presets: ['babel-preset-expo'],
5 | };
6 | };
7 |
--------------------------------------------------------------------------------
/components/Nav.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { StyleSheet, Text, View } from 'react-native'
3 | import { Icon } from 'react-native-elements'
4 | import { Platform } from 'react-native'
5 | import PropTypes from 'prop-types'
6 |
7 | import { Colors } from '../constants'
8 |
9 | const styles = StyleSheet.create({
10 | centerRow: {
11 | alignItems: 'center',
12 | backgroundColor: 'transparent',
13 | flex: 2,
14 | flexDirection: 'row',
15 | justifyContent: 'center',
16 | },
17 | container: {
18 | flexDirection: 'row',
19 | ...Platform.select({
20 | ios: {
21 | height: 55,
22 | },
23 | android: {
24 | height: 80,
25 | },
26 | }),
27 | justifyContent: 'center',
28 | marginLeft: 10,
29 | marginRight: 10,
30 | },
31 | icon: {
32 | justifyContent: 'flex-start',
33 | marginTop: 2.8,
34 | },
35 | iconContainer: {
36 | alignSelf: 'center',
37 | },
38 | leftRow: {
39 | backgroundColor: 'transparent',
40 | flex: 1,
41 | flexDirection: 'row',
42 | justifyContent: 'flex-start',
43 | },
44 | logoutText: {
45 | color: Colors.blue,
46 | fontSize: 18,
47 | fontWeight: '400',
48 | },
49 | rightRow: {
50 | alignItems: 'center',
51 | backgroundColor: 'transparent',
52 | flex: 1,
53 | flexDirection: 'row',
54 | justifyContent: 'flex-end',
55 | },
56 | titleText: {
57 | color: 'black',
58 | fontSize: 18,
59 | fontWeight: '400',
60 | },
61 | })
62 |
63 | const Search = ({ title, navigation, leftIcon }) => (
64 |
65 |
66 |
67 | navigation.goBack(null)}
78 | {...leftIcon}
79 | />
80 |
81 |
82 |
83 | {title}
84 |
85 |
86 |
87 | Log out
88 |
89 |
90 |
91 | )
92 |
93 | Search.propTypes = {
94 | title: PropTypes.string.isRequired,
95 | navigation: PropTypes.object.isRequired,
96 | leftIcon: PropTypes.object,
97 | }
98 |
99 | Search.defaultProps = {
100 | leftIcon: {},
101 | }
102 |
103 | export default Search
104 |
--------------------------------------------------------------------------------
/components/NavAbsolute.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { StyleSheet, Text, View } from 'react-native'
3 | import { Icon } from 'react-native-elements'
4 | import PropTypes from 'prop-types'
5 |
6 | import { Colors } from '../constants'
7 |
8 | const styles = StyleSheet.create({
9 | centerRow: {
10 | alignItems: 'flex-start',
11 | backgroundColor: 'transparent',
12 | flex: 3,
13 | flexDirection: 'column',
14 | justifyContent: 'center',
15 | },
16 |
17 | container: {
18 | backgroundColor: 'transparent',
19 | borderBottomWidth: 0,
20 | elevation: 0,
21 | flexDirection: 'row',
22 | height: 125,
23 | justifyContent: 'center',
24 | left: 0,
25 | marginLeft: 10,
26 | marginRight: 10,
27 | position: 'absolute',
28 | right: 0,
29 | zIndex: 100,
30 | },
31 | icon: {
32 | justifyContent: 'flex-start',
33 | marginTop: 2.8,
34 | },
35 | iconContainer: {
36 | alignSelf: 'center',
37 | },
38 | leftRow: {
39 | backgroundColor: 'transparent',
40 | flex: 1,
41 | flexDirection: 'row',
42 | justifyContent: 'flex-start',
43 | },
44 | rightRow: {
45 | alignItems: 'flex-end',
46 | backgroundColor: 'transparent',
47 | flex: 2,
48 | flexDirection: 'row',
49 | justifyContent: 'flex-end',
50 | marginRight: 4,
51 | },
52 | titleText: {
53 | color: Colors.white,
54 | fontSize: 24,
55 | fontWeight: '600',
56 | },
57 | subTitleText: {
58 | color: Colors.white,
59 | fontSize: 14,
60 | fontWeight: '400',
61 | },
62 | })
63 |
64 | class Nav extends Component {
65 | static propTypes = {
66 | navigation: PropTypes.object.isRequired,
67 | title: PropTypes.string.isRequired,
68 | subTitle: PropTypes.string.isRequired,
69 | }
70 |
71 | state = {
72 | like: false,
73 | }
74 |
75 | onPressLike = () => {
76 | this.setState(state => ({
77 | like: !state.like,
78 | }))
79 | }
80 |
81 | render() {
82 | const { navigation, title, subTitle } = this.props
83 |
84 | return (
85 |
86 |
87 |
88 |
99 |
100 |
101 |
102 | {title}
103 |
104 |
105 | {subTitle}
106 |
107 |
108 |
109 |
121 | null}
127 | iconStyle={styles.icon}
128 | underlayColor="transparent"
129 | underlineColorAndroid="transparent"
130 | containerStyle={styles.iconContainer}
131 | hitSlop={{ top: 15, bottom: 15, left: 15, right: 15 }}
132 | />
133 |
134 |
135 |
136 | )
137 | }
138 | }
139 |
140 | export default Nav
141 |
--------------------------------------------------------------------------------
/components/index.js:
--------------------------------------------------------------------------------
1 | export { default as Nav } from './Nav'
2 | export { default as NavAbsolute } from './NavAbsolute'
3 |
--------------------------------------------------------------------------------
/constants/Colors.js:
--------------------------------------------------------------------------------
1 | // https://developer.apple.com/ios/human-interface-guidelines/visual-design/color/
2 |
3 | const colors = {
4 | red: '#FF3B30',
5 | orange: '#FF9500',
6 | yellow: '#FFCC00',
7 | green: '#4CD964',
8 | tealBlue: '#5AC8FA',
9 | blue: '#007AFF',
10 | purple: '#5856D6',
11 | pink: '#FF2D55',
12 |
13 | white: '#FFFFFF',
14 | customGray: '#EFEFF4',
15 | lightGray: '#E5E5EA',
16 | lightGray2: '#D1D1D6',
17 | midGray: '#C7C7CC',
18 | gray: '#8E8E93',
19 | black: '#000000',
20 | }
21 |
22 | export default colors
23 |
--------------------------------------------------------------------------------
/constants/index.js:
--------------------------------------------------------------------------------
1 | export { default as Colors } from './Colors'
2 |
--------------------------------------------------------------------------------
/images/iphone11-giphy.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nattatorn-dev/react-native-user-profile/1b3a05983fa4af4b1c52f9fbe107fd2c3b44083a/images/iphone11-giphy.gif
--------------------------------------------------------------------------------
/images/pixel2-giphy.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nattatorn-dev/react-native-user-profile/1b3a05983fa4af4b1c52f9fbe107fd2c3b44083a/images/pixel2-giphy.gif
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import { registerRootComponent } from 'expo';
2 |
3 | import App from './App';
4 |
5 | // registerRootComponent calls AppRegistry.registerComponent('main', () => App);
6 | // It also ensures that whether you load the app in the Expo client or in a native build,
7 | // the environment is set up appropriately
8 | registerRootComponent(App);
9 |
--------------------------------------------------------------------------------
/metro.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | transformer: {
3 | assetPlugins: ['expo-asset/tools/hashAssetFiles'],
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/mocks/contact.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Darrell Schmeler",
3 | "username": "Leola_VonRueden",
4 | "address": {
5 | "streetA": "Abbott Shoals",
6 | "streetB": "505 Winona Place",
7 | "streetC": "4306 Hudson Street Suite 875",
8 | "streetD": "Suite 489",
9 | "city": "Ginatown",
10 | "state": "Massachusetts",
11 | "country": "Nepal",
12 | "zipcode": "41428-0189",
13 | "geo": {
14 | "lat": "-75.8513",
15 | "lng": "81.3262"
16 | }
17 | },
18 | "website": "destany.org",
19 | "bio":
20 | "Web & Mobile UI/UX designer, Motion designer following the latest ui & ux trends",
21 | "company": {
22 | "name": "Streich, Harber and Hilpert",
23 | "catchPhrase": "Team-oriented hybrid neural-net",
24 | "bs": "user-centric embrace vortals"
25 | },
26 | "avatar": "https://i.imgur.com/GfkNpVG.jpg",
27 | "avatarBackground":
28 | "https://i.imgur.com/rXVcgTZ.jpg",
29 | "tels": [
30 | { "id": 1, "name": "Mobile", "number": "+66 (089)-928-2134" },
31 | { "id": 2, "name": "Work", "number": "+41 (112)-435-9887" }
32 | ],
33 | "emails": [
34 | { "id": 1, "name": "Personal", "email": "elsie-goodman@mail.com" },
35 | { "id": 2, "name": "Work", "email": "elsie@work.com" }
36 | ],
37 | "posts": [
38 | {
39 | "id": 1,
40 | "words": "cupiditate qui cum",
41 | "sentence": "Ipsum laborum quasi debitis dolores veniam.",
42 | "sentences":
43 | "Impedit veritatis harum nihil dolores dolorem optio assumenda. Laborum saepe voluptas officia odit. Ut voluptas mollitia mollitia eum autem quisquam qui aut. Et ipsa hic harum molestias et quam qui cum. Sint sit soluta.",
44 | "paragraph":
45 | "Beatae voluptas ea magni quibusdam dolorem sit aut qui. Dolorem rerum et consequuntur inventore officia excepturi dolore architecto fuga. Quia consequatur asperiores rerum qui corporis dolorum. At harum velit adipisci iste odit modi veniam ut. Deserunt quibusdam velit non ea.",
46 | "image":
47 | "https://d25tv1xepz39hi.cloudfront.net/2016-12-19/files/foodphotoghacks_image8.jpg",
48 | "createdDate": "2017-11-21T02:33:53.770Z",
49 | "user": {
50 | "name": "Ronaldo",
51 | "username": "Ronaldo.Effertz",
52 | "avatar":
53 | "https://s3.amazonaws.com/uifaces/faces/twitter/samuelkraft/128.jpg",
54 | "email": "Ronaldo.Effertz.Deckow@hotmail.com"
55 | }
56 | },
57 | {
58 | "id": 2,
59 | "words": "est voluptatum aut",
60 | "sentence": "Omnis omnis aut dolor quaerat sunt et optio.",
61 | "sentences":
62 | "Nam numquam magni saepe. Deserunt aspernatur dolorem libero soluta sint molestias et sint sed. Maiores id quis assumenda voluptates quos ut saepe officia voluptatem. Ea placeat sed ut. Modi sed earum voluptas cumque unde eum doloribus ipsam.",
63 | "paragraph":
64 | "Quam aut reprehenderit asperiores aut. Sunt quis aspernatur incidunt. Illo et perferendis ex incidunt eos ut maxime dolorem voluptatem. Qui rem nihil quos cumque eum doloribus. Quae beatae tempore commodi.",
65 | "createdDate": "2017-11-20T18:04:58.858Z",
66 | "user": {
67 | "name": "Markus",
68 | "username": "Markus.Price68",
69 | "avatar":
70 | "https://s3.amazonaws.com/uifaces/faces/twitter/kikillo/128.jpg",
71 | "email": "Markus.Price68.Dicki@yahoo.com"
72 | }
73 | },
74 | {
75 | "id": 3,
76 | "words": "vitae voluptas quia",
77 | "sentence": "Voluptates dolor ad rem amet voluptas.",
78 | "sentences":
79 | "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
80 | "paragraph":
81 | "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
82 | "createdDate": "2017-03-24T10:56:15.461Z",
83 | "image": "https://touristmeetstraveler.com/wp-content/uploads/sushi.jpg",
84 | "user": {
85 | "name": "Magali",
86 | "username": "Magali16",
87 | "avatar":
88 | "https://s3.amazonaws.com/uifaces/faces/twitter/mastermindesign/128.jpg",
89 | "email": "Magali1664@gmail.com"
90 | }
91 | }
92 | ]
93 | }
94 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-user-profile",
3 | "version": "0.0.3",
4 | "description": "Hello Expo!",
5 | "author": "nattatorn-dev",
6 | "main": "index.js",
7 | "scripts": {
8 | "android": "react-native run-android",
9 | "ios": "react-native run-ios",
10 | "web": "expo start",
11 | "start": "expo start",
12 | "test": "jest"
13 | },
14 | "dependencies": {
15 | "@react-native-community/masked-view": "0.1.10",
16 | "@react-navigation/bottom-tabs": "^5.8.0",
17 | "@react-navigation/native": "^5.7.3",
18 | "@react-navigation/stack": "^5.9.0",
19 | "expo": "~38.0.9",
20 | "expo-splash-screen": "^0.5.0",
21 | "expo-status-bar": "^1.0.0",
22 | "expo-updates": "~0.2.10",
23 | "react": "~16.11.0",
24 | "react-dom": "~16.11.0",
25 | "react-native": "~0.62.2",
26 | "react-native-elements": "^2.2.1",
27 | "react-native-gesture-handler": "~1.6.0",
28 | "react-native-reanimated": "~1.9.0",
29 | "react-native-safe-area-context": "~3.0.7",
30 | "react-native-screens": "~2.9.0",
31 | "react-native-tab-view": "^2.15.1",
32 | "react-native-unimodules": "~0.10.1",
33 | "react-native-web": "~0.11.7"
34 | },
35 | "devDependencies": {
36 | "@babel/core": "~7.9.0",
37 | "babel-jest": "~25.2.6",
38 | "jest": "~25.2.6",
39 | "react-test-renderer": "~16.11.0"
40 | },
41 | "jest": {
42 | "preset": "react-native"
43 | },
44 | "private": true
45 | }
46 |
--------------------------------------------------------------------------------
/screens/Product1/PhotoButton.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { StyleSheet, View } from 'react-native'
3 | import { Button, Icon } from 'react-native-elements'
4 |
5 | import ProductStyles from './ProductStyle'
6 |
7 | const styles = StyleSheet.create({ ...ProductStyles })
8 |
9 | const PhotoButton = () => (
10 |
11 |
31 |
32 | )
33 |
34 | export default PhotoButton
35 |
--------------------------------------------------------------------------------
/screens/Product1/Product.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import {
3 | ImageBackground,
4 | ScrollView,
5 | StyleSheet,
6 | Text,
7 | TouchableOpacity,
8 | View,
9 | } from 'react-native'
10 | import PropTypes from 'prop-types'
11 |
12 | import productData from './product.json'
13 |
14 | import PhotoButton from './PhotoButton'
15 | import ProductStyles from './ProductStyle'
16 |
17 | const styles = StyleSheet.create({ ...ProductStyles })
18 |
19 | class Product extends Component {
20 | static propTypes = {
21 | img: PropTypes.string.isRequired,
22 | detail: PropTypes.string.isRequired,
23 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
24 | }
25 |
26 | static defaultProps = {
27 | containerStyle: {},
28 | }
29 |
30 | renderDetail = () => {
31 | return (
32 |
33 | For Sale Property Details
34 | {this.props.detail}
35 |
36 | )
37 | }
38 |
39 | renderDescription = () => {
40 | return (
41 |
42 | $175,000
43 | 1 Bed, 2 Bath, 1088 soft
44 | Condo, 342 Days on Trulia
45 | Est. Mortgage $52,604
46 |
47 | )
48 | }
49 |
50 | renderNavigator = () => {
51 | return (
52 |
53 |
54 | DIRECTIONS
55 |
56 |
57 | STREET VIEW
58 |
59 |
60 | MAP
61 |
62 |
63 | )
64 | }
65 |
66 | renderContactHeader = () => {
67 | return (
68 |
69 |
70 |
74 |
75 |
76 |
77 |
78 | )
79 | }
80 |
81 | render() {
82 | return (
83 |
84 |
85 |
86 |
87 | {this.renderContactHeader()}
88 |
89 |
90 | {this.renderDescription()}
91 | {this.renderNavigator()}
92 | {this.renderDetail()}
93 |
94 |
95 |
96 | CALL
97 |
98 |
99 |
100 | EMAIL
101 |
102 |
103 |
104 | )
105 | }
106 | }
107 |
108 | export default Product
109 |
--------------------------------------------------------------------------------
/screens/Product1/ProductStyle.js:
--------------------------------------------------------------------------------
1 | import { Dimensions } from 'react-native'
2 | import { Colors } from '../../constants'
3 |
4 | export default {
5 | cardContainer: {
6 | flex: 1,
7 | },
8 | container: {
9 | flex: 1,
10 | flexDirection: 'column',
11 | },
12 | coverContainer: {
13 | position: 'relative',
14 | },
15 | coverImage: {
16 | height: Dimensions.get('window').width * (3 / 4),
17 | width: Dimensions.get('window').width,
18 | },
19 | headerContainer: {
20 | alignItems: 'center',
21 | backgroundColor: '#FFF',
22 | },
23 | scroll: {
24 | backgroundColor: '#FFF',
25 | flex: 1,
26 | marginBottom: 55,
27 | },
28 | productRow: {
29 | margin: 25,
30 | },
31 | mainViewStyle: {
32 | flex: 1,
33 | flexDirection: 'column',
34 | flexGrow: 1,
35 | },
36 | coverMetaContainer: {
37 | alignItems: 'flex-end',
38 | flex: 1,
39 | justifyContent: 'flex-end',
40 | },
41 | footer: {
42 | alignItems: 'center',
43 | backgroundColor: '#e36449',
44 | bottom: 0,
45 | flex: 0.1,
46 | flexDirection: 'row',
47 | height: 65,
48 | left: 0,
49 | position: 'absolute',
50 | right: 0,
51 | },
52 | buttonFooter: {
53 | alignItems: 'center',
54 | flex: 1,
55 | justifyContent: 'center',
56 | },
57 | navigatorButton: {
58 | alignItems: 'flex-start',
59 | flex: 1,
60 | justifyContent: 'center',
61 | },
62 | navigatorText: {
63 | alignItems: 'flex-start',
64 | color: Colors.green,
65 | fontSize: 16,
66 | fontWeight: 'bold',
67 | justifyContent: 'center',
68 | },
69 | borderCenter: {
70 | borderColor: '#FFA890',
71 | borderWidth: 0.5,
72 | height: 55,
73 | },
74 | textFooter: {
75 | alignItems: 'center',
76 | color: 'white',
77 | fontSize: 18,
78 | fontWeight: 'bold',
79 | },
80 | priceText: {
81 | color: Colors.black,
82 | fontSize: 36,
83 | fontWeight: '400',
84 | letterSpacing: 1,
85 | marginBottom: 5,
86 | },
87 | detailText: {
88 | color: Colors.black,
89 | fontSize: 22,
90 | fontWeight: '600',
91 | letterSpacing: 0.5,
92 | marginBottom: 4,
93 | },
94 | subDetailText: {
95 | color: Colors.black,
96 | fontSize: 16,
97 | fontWeight: '100',
98 | letterSpacing: 0.5,
99 | lineHeight: 28,
100 | },
101 | descriptionText: {
102 | color: Colors.gray,
103 | fontSize: 16,
104 | fontWeight: '400',
105 | letterSpacing: 1,
106 | marginBottom: 4,
107 | },
108 | }
109 |
--------------------------------------------------------------------------------
/screens/Product1/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | import productData from './product.json'
5 |
6 | import { NavAbsolute } from '../../components'
7 | import Product from './Product'
8 |
9 | const ProductScreen = (props) => {
10 | props.navigation.setOptions({
11 | header: ({ navigation }) => (
12 |
17 | ),
18 | })
19 |
20 | return
21 | }
22 |
23 | export default ProductScreen
24 |
--------------------------------------------------------------------------------
/screens/Product1/product.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Jennis BNK48",
3 | "username": "Jennis_BNK48",
4 | "bio": "Singer",
5 | "title": "338 Spear St #26G",
6 | "address": "San Francisco, CA 94105",
7 | "img":
8 | "https://i.imgur.com/EUk0768.jpg",
9 | "detail": "Enjoy true urban living in this spacious one bedroom, one bath home at The Infinity. This full service home is finished with Studio Becker cabinetry, hardwood floors, Bosch and Thermador appliances, in-unit washer/dryer and custom lighting. Premium Secure Undergroud"
10 | }
11 |
--------------------------------------------------------------------------------
/screens/Profile1/Email.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
3 | import { Icon } from 'react-native-elements'
4 | import PropTypes from 'prop-types'
5 |
6 | const styles = StyleSheet.create({
7 | container: {
8 | flexDirection: 'row',
9 | justifyContent: 'flex-start',
10 | marginBottom: 25,
11 | },
12 | emailColumn: {
13 | flexDirection: 'row',
14 | justifyContent: 'flex-start',
15 | marginBottom: 5,
16 | },
17 | emailIcon: {
18 | color: 'gray',
19 | fontSize: 30,
20 | },
21 | emailNameColumn: {
22 | flexDirection: 'row',
23 | justifyContent: 'flex-start',
24 | },
25 | emailNameText: {
26 | color: 'gray',
27 | fontSize: 14,
28 | fontWeight: '200',
29 | },
30 | emailRow: {
31 | flex: 8,
32 | flexDirection: 'column',
33 | justifyContent: 'center',
34 | },
35 | emailText: {
36 | fontSize: 16,
37 | },
38 | iconRow: {
39 | flex: 2,
40 | justifyContent: 'center',
41 | },
42 | })
43 |
44 | const Email = ({ containerStyle, onPressEmail, name, email, index }) => (
45 | onPressEmail(email)}>
46 |
47 |
48 | {index === 0 && (
49 | onPressEmail()}
54 | />
55 | )}
56 |
57 |
58 |
59 | {email}
60 |
61 |
62 | {name.length !== 0 && (
63 | {name}
64 | )}
65 |
66 |
67 |
68 |
69 | )
70 |
71 | Email.propTypes = {
72 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
73 | email: PropTypes.string.isRequired,
74 | index: PropTypes.number.isRequired,
75 | name: PropTypes.string,
76 | onPressEmail: PropTypes.func.isRequired,
77 | }
78 |
79 | Email.defaultProps = {
80 | containerStyle: {},
81 | name: null,
82 | }
83 |
84 | export default Email
85 |
--------------------------------------------------------------------------------
/screens/Profile1/Profile.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Card, Icon } from 'react-native-elements'
3 | import {
4 | FlatList,
5 | Image,
6 | ImageBackground,
7 | Linking,
8 | Platform,
9 | ScrollView,
10 | StyleSheet,
11 | Text,
12 | View,
13 | } from 'react-native'
14 | import PropTypes from 'prop-types'
15 |
16 | import Email from './Email'
17 | import Separator from './Separator'
18 | import Tel from './Tel'
19 |
20 | const styles = StyleSheet.create({
21 | cardContainer: {
22 | backgroundColor: '#FFF',
23 | borderWidth: 0,
24 | flex: 1,
25 | margin: 0,
26 | padding: 0,
27 | },
28 | container: {
29 | flex: 1,
30 | },
31 | emailContainer: {
32 | backgroundColor: '#FFF',
33 | flex: 1,
34 | paddingTop: 30,
35 | },
36 | headerBackgroundImage: {
37 | paddingBottom: 20,
38 | paddingTop: 45,
39 | },
40 | headerContainer: {},
41 | headerColumn: {
42 | backgroundColor: 'transparent',
43 | ...Platform.select({
44 | ios: {
45 | alignItems: 'center',
46 | elevation: 1,
47 | marginTop: -1,
48 | },
49 | android: {
50 | alignItems: 'center',
51 | },
52 | }),
53 | },
54 | placeIcon: {
55 | color: 'white',
56 | fontSize: 26,
57 | },
58 | scroll: {
59 | backgroundColor: '#FFF',
60 | },
61 | telContainer: {
62 | backgroundColor: '#FFF',
63 | flex: 1,
64 | paddingTop: 30,
65 | },
66 | userAddressRow: {
67 | alignItems: 'center',
68 | flexDirection: 'row',
69 | },
70 | userCityRow: {
71 | backgroundColor: 'transparent',
72 | },
73 | userCityText: {
74 | color: '#A5A5A5',
75 | fontSize: 15,
76 | fontWeight: '600',
77 | textAlign: 'center',
78 | },
79 | userImage: {
80 | borderColor: '#FFF',
81 | borderRadius: 85,
82 | borderWidth: 3,
83 | height: 170,
84 | marginBottom: 15,
85 | width: 170,
86 | },
87 | userNameText: {
88 | color: '#FFF',
89 | fontSize: 22,
90 | fontWeight: 'bold',
91 | paddingBottom: 8,
92 | textAlign: 'center',
93 | },
94 | })
95 |
96 | class Contact extends Component {
97 | static propTypes = {
98 | avatar: PropTypes.string.isRequired,
99 | avatarBackground: PropTypes.string.isRequired,
100 | name: PropTypes.string.isRequired,
101 | address: PropTypes.shape({
102 | city: PropTypes.string.isRequired,
103 | country: PropTypes.string.isRequired,
104 | }).isRequired,
105 | emails: PropTypes.arrayOf(
106 | PropTypes.shape({
107 | email: PropTypes.string.isRequired,
108 | id: PropTypes.number.isRequired,
109 | name: PropTypes.string.isRequired,
110 | })
111 | ).isRequired,
112 | tels: PropTypes.arrayOf(
113 | PropTypes.shape({
114 | id: PropTypes.number.isRequired,
115 | name: PropTypes.string.isRequired,
116 | number: PropTypes.string.isRequired,
117 | })
118 | ).isRequired,
119 | }
120 |
121 | onPressPlace = () => {
122 | console.log('place')
123 | }
124 |
125 | onPressTel = number => {
126 | Linking.openURL(`tel://${number}`).catch(err => console.log('Error:', err))
127 | }
128 |
129 | onPressSms = () => {
130 | console.log('sms')
131 | }
132 |
133 | onPressEmail = email => {
134 | Linking.openURL(`mailto://${email}?subject=subject&body=body`).catch(err =>
135 | console.log('Error:', err)
136 | )
137 | }
138 |
139 | renderHeader = () => {
140 | const {
141 | avatar,
142 | avatarBackground,
143 | name,
144 | address: { city, country },
145 | } = this.props
146 |
147 | return (
148 |
149 |
154 |
155 |
159 | {name}
160 |
161 |
162 |
168 |
169 |
170 |
171 | {city}, {country}
172 |
173 |
174 |
175 |
176 |
177 |
178 | )
179 | }
180 |
181 | renderTel = () => (
182 | {
186 | const { id, name, number } = list.item
187 |
188 | return (
189 |
197 | )
198 | }}
199 | />
200 | )
201 |
202 | renderEmail = () => (
203 | {
207 | const { email, id, name } = list.item
208 |
209 | return (
210 |
217 | )
218 | }}
219 | />
220 | )
221 |
222 | render() {
223 | return (
224 |
225 |
226 |
227 | {this.renderHeader()}
228 | {this.renderTel()}
229 | {Separator()}
230 | {this.renderEmail()}
231 |
232 |
233 |
234 | )
235 | }
236 | }
237 |
238 | export default Contact
239 |
--------------------------------------------------------------------------------
/screens/Profile1/Separator.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { StyleSheet, View } from 'react-native'
3 |
4 | const styles = StyleSheet.create({
5 | container: {
6 | flexDirection: 'row',
7 | },
8 | separatorOffset: {
9 | flex: 2,
10 | flexDirection: 'row',
11 | },
12 | separator: {
13 | borderColor: '#EDEDED',
14 | borderWidth: 0.8,
15 | flex: 8,
16 | flexDirection: 'row',
17 | },
18 | })
19 |
20 | const Separator = () => (
21 |
22 |
23 |
24 |
25 | )
26 |
27 | export default Separator
28 |
--------------------------------------------------------------------------------
/screens/Profile1/Tel.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
3 | import { Icon } from 'react-native-elements'
4 | import PropTypes from 'prop-types'
5 |
6 | import mainColor from './constants'
7 |
8 | const styles = StyleSheet.create({
9 | container: {
10 | flexDirection: 'row',
11 | justifyContent: 'flex-start',
12 | marginBottom: 25,
13 | },
14 | iconRow: {
15 | flex: 2,
16 | justifyContent: 'center',
17 | },
18 | smsIcon: {
19 | color: 'darkgray',
20 | fontSize: 30,
21 | },
22 | smsRow: {
23 | flex: 2,
24 | justifyContent: 'flex-start',
25 | },
26 | telIcon: {
27 | color: mainColor,
28 | fontSize: 30,
29 | },
30 | telNameColumn: {
31 | flexDirection: 'row',
32 | justifyContent: 'flex-start',
33 | },
34 | telNameText: {
35 | color: 'gray',
36 | fontSize: 14,
37 | fontWeight: '200',
38 | },
39 | telNumberColumn: {
40 | flexDirection: 'row',
41 | justifyContent: 'flex-start',
42 | marginBottom: 5,
43 | },
44 | telNumberText: {
45 | fontSize: 16,
46 | },
47 | telRow: {
48 | flex: 6,
49 | flexDirection: 'column',
50 | justifyContent: 'center',
51 | },
52 | })
53 |
54 | const Tel = ({
55 | containerStyle,
56 | index,
57 | name,
58 | number,
59 | onPressSms,
60 | onPressTel,
61 | }) => {
62 |
63 | return (
64 | onPressTel(number)}>
65 |
66 |
67 | {index === 0 && (
68 | onPressTel(number)}
73 | />
74 | )}
75 |
76 |
77 |
78 | {number}
79 |
80 |
81 | {name.length !== 0 && (
82 | {name}
83 | )}
84 |
85 |
86 |
87 | onPressSms()}
92 | />
93 |
94 |
95 |
96 | )
97 | }
98 |
99 | Tel.propTypes = {
100 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
101 | index: PropTypes.number.isRequired,
102 | name: PropTypes.string,
103 | number: PropTypes.string.isRequired,
104 | onPressSms: PropTypes.func.isRequired,
105 | onPressTel: PropTypes.func.isRequired,
106 | }
107 |
108 | Tel.defaultProps = {
109 | containerStyle: {},
110 | name: null,
111 | }
112 |
113 | export default Tel
114 |
--------------------------------------------------------------------------------
/screens/Profile1/constants.js:
--------------------------------------------------------------------------------
1 | const mainColor = 'gray'
2 |
3 | export default mainColor
4 |
--------------------------------------------------------------------------------
/screens/Profile1/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | import contactData from '../../mocks/contact.json'
5 |
6 | import Profile from './Profile'
7 |
8 | const ProfileScreen = () =>
9 |
10 | ProfileScreen.navigationOptions = () => ({
11 | header: null,
12 | })
13 |
14 | ProfileScreen.propTypes = {
15 | navigation: PropTypes.object.isRequired,
16 | }
17 |
18 | export default ProfileScreen
19 |
--------------------------------------------------------------------------------
/screens/Profile2/Post.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Dimensions, Image, View, Text, StyleSheet } from 'react-native'
3 | import { Avatar } from 'react-native-elements'
4 | import PropTypes from 'prop-types'
5 |
6 | import { datetime } from '../../utils'
7 |
8 | const styles = StyleSheet.create({
9 | container: {
10 | borderWidth: 0,
11 | justifyContent: 'space-between',
12 | marginBottom: 5,
13 | marginLeft: 12,
14 | marginRight: 12,
15 | marginTop: 10,
16 | padding: 0,
17 | },
18 | date: {
19 | color: 'gray',
20 | fontSize: 12.5,
21 | },
22 | postRow: {
23 | alignItems: 'center',
24 | flexDirection: 'row',
25 | paddingBottom: 6,
26 | paddingLeft: 15,
27 | paddingRight: 15,
28 | paddingTop: 6,
29 | width: Dimensions.get('window').width * 1,
30 | },
31 | postImage: {
32 | backgroundColor: 'rgba(0, 0, 0, 0.075)',
33 | height: 200,
34 | },
35 | userImage: {
36 | marginRight: 12,
37 | },
38 | wordRow: {
39 | marginBottom: 10,
40 | paddingLeft: 15,
41 | paddingRight: 15,
42 | paddingTop: 6,
43 | },
44 | wordText: {
45 | fontSize: 14,
46 | fontWeight: '500',
47 | lineHeight: 22,
48 | },
49 | })
50 |
51 | const Post = ({ containerStyle, user, image, createdDate, sentences }) => (
52 |
53 |
54 |
55 |
62 |
63 |
64 | {user.name}
65 |
66 | {datetime.timeDifferenceForDate(createdDate)}
67 |
68 |
69 |
70 |
71 | {sentences}
72 |
73 | {image && }
74 |
75 | )
76 |
77 | Post.propTypes = {
78 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
79 | image: PropTypes.string,
80 | user: PropTypes.shape({
81 | name: PropTypes.string.isRequired,
82 | avatar: PropTypes.string.isRequired,
83 | }).isRequired,
84 | createdDate: PropTypes.string.isRequired,
85 | sentences: PropTypes.string.isRequired,
86 | }
87 |
88 | Post.defaultProps = {
89 | containerStyle: {},
90 | image: null,
91 | }
92 |
93 | export default Post
94 |
--------------------------------------------------------------------------------
/screens/Profile2/Posts.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { FlatList, StyleSheet } from 'react-native'
3 | import PropTypes from 'prop-types'
4 |
5 | import Post from './Post'
6 |
7 | const styles = StyleSheet.create({
8 | container: {
9 | flex: 1,
10 | flexDirection: 'column',
11 | alignItems: 'center',
12 | justifyContent: 'center',
13 | },
14 | postContainer: {
15 | justifyContent: 'space-between',
16 | marginBottom: 5,
17 | marginLeft: 12,
18 | marginRight: 12,
19 | marginTop: 10,
20 | padding: 0,
21 | borderWidth: 0,
22 | },
23 | })
24 |
25 | class Posts extends Component {
26 | static propTypes = {
27 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
28 | posts: PropTypes.arrayOf(
29 | PropTypes.shape({
30 | id: PropTypes.number.isRequired,
31 | words: PropTypes.string.isRequired,
32 | sentence: PropTypes.string.isRequired,
33 | paragraph: PropTypes.string.isRequired,
34 | image: PropTypes.string,
35 | user: PropTypes.shape({
36 | name: PropTypes.string.isRequired,
37 | username: PropTypes.string.isRequired,
38 | avatar: PropTypes.string.isRequired,
39 | email: PropTypes.string.isRequired,
40 | }),
41 | })
42 | ).isRequired,
43 | }
44 |
45 | static defaultProps = {
46 | containerStyle: {},
47 | }
48 |
49 | render() {
50 | return (
51 | {
57 | return (
58 |
63 | )
64 | }}
65 | />
66 | )
67 | }
68 | }
69 |
70 | export default Posts
71 |
--------------------------------------------------------------------------------
/screens/Profile2/Profile.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import {
3 | Animated,
4 | Image,
5 | Platform,
6 | ScrollView,
7 | StyleSheet,
8 | Text,
9 | View,
10 | } from 'react-native'
11 | import { Icon } from 'react-native-elements'
12 | import {
13 | TabView,
14 | TabBar,
15 | TabViewPagerScroll,
16 | TabViewPagerPan,
17 | } from 'react-native-tab-view'
18 | import PropTypes from 'prop-types'
19 |
20 | import Posts from './Posts'
21 |
22 | const styles = StyleSheet.create({
23 | cardContainer: {
24 | flex: 1,
25 | },
26 | container: {
27 | flex: 1,
28 | },
29 | headerContainer: {
30 | alignItems: 'center',
31 | backgroundColor: '#FFF',
32 | marginBottom: 10,
33 | marginTop: 45,
34 | },
35 | indicatorTab: {
36 | backgroundColor: 'transparent',
37 | },
38 | scroll: {
39 | backgroundColor: '#FFF',
40 | },
41 | sceneContainer: {
42 | marginTop: 10,
43 | },
44 | socialIcon: {
45 | marginLeft: 14,
46 | marginRight: 14,
47 | },
48 | socialRow: {
49 | flexDirection: 'row',
50 | },
51 | tabBar: {
52 | backgroundColor: '#EEE',
53 | },
54 | tabContainer: {
55 | flex: 1,
56 | marginBottom: 12,
57 | },
58 | tabLabelNumber: {
59 | color: 'gray',
60 | fontSize: 12.5,
61 | textAlign: 'center',
62 | },
63 | tabLabelText: {
64 | color: 'black',
65 | fontSize: 22.5,
66 | fontWeight: '600',
67 | textAlign: 'center',
68 | },
69 | userBioRow: {
70 | marginLeft: 40,
71 | marginRight: 40,
72 | },
73 | userBioText: {
74 | color: 'gray',
75 | fontSize: 13.5,
76 | textAlign: 'center',
77 | },
78 | userImage: {
79 | borderRadius: 60,
80 | height: 120,
81 | marginBottom: 10,
82 | width: 120,
83 | },
84 | userNameRow: {
85 | marginBottom: 10,
86 | },
87 | userNameText: {
88 | color: '#5B5A5A',
89 | fontSize: 18,
90 | fontWeight: 'bold',
91 | textAlign: 'center',
92 | },
93 | userRow: {
94 | alignItems: 'center',
95 | flexDirection: 'column',
96 | justifyContent: 'center',
97 | marginBottom: 12,
98 | },
99 | })
100 |
101 | class Profile2 extends Component {
102 | static propTypes = {
103 | avatar: PropTypes.string.isRequired,
104 | name: PropTypes.string.isRequired,
105 | bio: PropTypes.string.isRequired,
106 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
107 | tabContainerStyle: PropTypes.oneOfType([
108 | PropTypes.object,
109 | PropTypes.number,
110 | ]),
111 | posts: PropTypes.arrayOf(
112 | PropTypes.shape({
113 | id: PropTypes.number.isRequired,
114 | words: PropTypes.string.isRequired,
115 | sentence: PropTypes.string.isRequired,
116 | paragraph: PropTypes.string.isRequired,
117 | image: PropTypes.string,
118 | user: PropTypes.shape({
119 | name: PropTypes.string.isRequired,
120 | username: PropTypes.string.isRequired,
121 | avatar: PropTypes.string.isRequired,
122 | email: PropTypes.string.isRequired,
123 | }),
124 | })
125 | ).isRequired,
126 | }
127 |
128 | static defaultProps = {
129 | containerStyle: {},
130 | tabContainerStyle: {},
131 | }
132 |
133 | state = {
134 | tabs: {
135 | index: 0,
136 | routes: [
137 | { key: '1', title: 'active', count: 31 },
138 | { key: '2', title: 'like', count: 86 },
139 | { key: '3', title: 'following', count: 95 },
140 | { key: '4', title: 'followers', count: '1.3 K' },
141 | ],
142 | },
143 | }
144 |
145 | onPressPlace = () => {
146 | console.log('place')
147 | }
148 |
149 | handleIndexChange = index => {
150 | this.setState({
151 | tabs: {
152 | ...this.state.tabs,
153 | index,
154 | },
155 | })
156 | }
157 |
158 | renderTabBar = props => {
159 | return
166 | };
167 |
168 | renderLabel = props => ({ route }) => {
169 | const routes = props.navigationState.routes
170 |
171 | let labels = []
172 | routes.forEach((e, index) => {
173 | labels.push(index === props.navigationState.index ? 'black' : 'gray')
174 | })
175 |
176 | const currentIndex = parseInt(route.key) - 1
177 | const color = labels[currentIndex]
178 |
179 | return (
180 |
181 |
182 | {route.count}
183 |
184 |
185 | {route.title}
186 |
187 |
188 | )
189 | }
190 |
191 | renderScene = ({ route: { key } }) => {
192 | const { posts } = this.props
193 |
194 | switch (key) {
195 | case '1':
196 | return
197 | case '2':
198 | return
199 | case '3':
200 | return
201 | case '4':
202 | return
203 | default:
204 | return
205 | }
206 | }
207 |
208 | renderContactHeader = () => {
209 | const { avatar, name, bio } = this.props
210 |
211 | return (
212 |
213 |
214 |
218 |
219 | {name}
220 |
221 |
222 | {bio}
223 |
224 |
225 |
226 |
227 | console.log('facebook')}
233 | />
234 |
235 |
236 | console.log('twitter')}
242 | />
243 |
244 |
245 | console.log('google')}
251 | />
252 |
253 |
254 |
255 | )
256 | }
257 |
258 | render() {
259 | return (
260 |
261 |
262 |
263 | {this.renderContactHeader()}
264 |
271 |
272 |
273 |
274 | )
275 | }
276 | }
277 |
278 | export default Profile2
279 |
--------------------------------------------------------------------------------
/screens/Profile2/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | import contactData from '../../mocks/contact.json'
5 |
6 | import Profile from './Profile'
7 |
8 | const ProfileScreen = () =>
9 |
10 | ProfileScreen.navigationOptions = () => ({
11 | header: null,
12 | })
13 |
14 | ProfileScreen.propTypes = {
15 | navigation: PropTypes.object.isRequired,
16 | }
17 |
18 | export default ProfileScreen
19 |
--------------------------------------------------------------------------------
/screens/Profile3/Post.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Image, StyleSheet, View } from 'react-native'
3 | import PropTypes from 'prop-types'
4 |
5 | const styles = StyleSheet.create({
6 | container: {},
7 | postImage: {},
8 | })
9 |
10 | const Post = ({
11 | containerStyle,
12 | image,
13 | imageHeight,
14 | imageWidth,
15 | postWidth,
16 | }) => {
17 | return (
18 |
19 | {image && (
20 |
30 | )}
31 |
32 | )
33 | }
34 |
35 | Post.propTypes = {
36 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
37 | image: PropTypes.string,
38 | imageHeight: PropTypes.number,
39 | imageWidth: PropTypes.number,
40 | postWidth: PropTypes.number,
41 | }
42 |
43 | Post.defaultProps = {
44 | containerStyle: {},
45 | image: null,
46 | imageHeight: null,
47 | imageWidth: null,
48 | postWidth: null,
49 | }
50 |
51 | export default Post
52 |
--------------------------------------------------------------------------------
/screens/Profile3/Posts.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Dimensions, FlatList, StyleSheet } from 'react-native'
3 | import PropTypes from 'prop-types'
4 |
5 | import Post from './Post'
6 |
7 | const space = 1
8 | const postContainerWidth = (Dimensions.get('window').width - space * 2) / 2
9 |
10 | const styles = StyleSheet.create({
11 | container: {},
12 | postContainer: {
13 | marginBottom: 1,
14 | padding: 0,
15 | borderWidth: 0,
16 | },
17 | })
18 |
19 | class Posts extends Component {
20 | static propTypes = {
21 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
22 | posts: PropTypes.arrayOf(
23 | PropTypes.shape({
24 | image: PropTypes.string,
25 | imageHeight: PropTypes.number,
26 | imageWidth: PropTypes.number,
27 | })
28 | ).isRequired,
29 | }
30 |
31 | static defaultProps = {
32 | containerStyle: {},
33 | }
34 |
35 | render() {
36 | return (
37 | {
43 | return (
44 |
50 | )
51 | }}
52 | />
53 | )
54 | }
55 | }
56 |
57 | export default Posts
58 |
--------------------------------------------------------------------------------
/screens/Profile3/Profile.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import {
3 | Animated,
4 | Image,
5 | ImageBackground,
6 | Platform,
7 | ScrollView,
8 | StyleSheet,
9 | Text,
10 | View,
11 | } from 'react-native'
12 | import {
13 | TabView,
14 | TabBar,
15 | TabViewPagerScroll,
16 | TabViewPagerPan,
17 | } from 'react-native-tab-view'
18 | import PropTypes from 'prop-types'
19 | import { image } from '../../utils'
20 |
21 | import profileStyles from './ProfileStyle'
22 | import Posts from './Posts'
23 |
24 | const styles = StyleSheet.create({ ...profileStyles })
25 |
26 | class Profile3 extends Component {
27 | static propTypes = {
28 | avatar: PropTypes.string.isRequired,
29 | avatarBackground: PropTypes.string.isRequired,
30 | bio: PropTypes.string.isRequired,
31 | name: PropTypes.string.isRequired,
32 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
33 | tabContainerStyle: PropTypes.oneOfType([
34 | PropTypes.number,
35 | PropTypes.object,
36 | ]),
37 | posts: PropTypes.arrayOf(
38 | PropTypes.shape({
39 | image: PropTypes.string,
40 | imageHeight: PropTypes.number,
41 | imageWidth: PropTypes.number,
42 | postWidth: PropTypes.number,
43 | })
44 | ).isRequired,
45 | }
46 |
47 | static defaultProps = {
48 | containerStyle: {},
49 | tabContainerStyle: {},
50 | }
51 |
52 | state = {
53 | tabs: {
54 | index: 0,
55 | routes: [
56 | { key: '1', title: 'PHOTOS', count: 687 },
57 | { key: '2', title: 'FOLLOWING', count: 1224 },
58 | { key: '3', title: 'FOLLOWERS', count: '3 M' },
59 | ],
60 | },
61 | postsMasonry: {},
62 | }
63 |
64 | componentWillMount() {
65 | this.setState({
66 | postsMasonry: image.mansonry(this.props.posts, 'imageHeight'),
67 | })
68 | }
69 |
70 | handleIndexChange = index => {
71 | this.setState({
72 | tabs: {
73 | ...this.state.tabs,
74 | index,
75 | },
76 | })
77 | }
78 |
79 | renderTabBar = props => {
80 | return
87 | };
88 |
89 | renderLabel = props => ({ route }) => {
90 | const routes = props.navigationState.routes
91 |
92 | let labels = []
93 | routes.forEach((e, index) => {
94 | labels.push(index === props.navigationState.index ? 'black' : 'gray')
95 | })
96 |
97 | const currentIndex = parseInt(route.key) - 1
98 | const color = labels[currentIndex]
99 |
100 | return (
101 |
102 |
103 | {route.count}
104 |
105 |
106 | {route.title}
107 |
108 |
109 | )
110 | }
111 |
112 | renderScene = ({ route: { key } }) => {
113 | switch (key) {
114 | case '1':
115 | return this.renderMansonry2Col()
116 | case '2':
117 | return this.renderMansonry2Col()
118 | case '3':
119 | return this.renderMansonry2Col()
120 | default:
121 | return
122 | }
123 | }
124 |
125 | renderContactHeader = () => {
126 | const { avatar, avatarBackground, name, bio } = this.props
127 |
128 | return (
129 |
130 |
131 |
135 |
136 |
137 |
138 |
139 | {name}
140 | {bio}
141 |
142 |
143 |
144 |
145 |
149 |
150 |
151 | )
152 | }
153 |
154 | renderMansonry2Col = () => {
155 | return (
156 |
157 |
158 |
162 |
163 |
164 |
168 |
169 |
170 | )
171 | }
172 |
173 | render() {
174 | return (
175 |
176 |
177 |
178 | {this.renderContactHeader()}
179 |
186 |
187 |
188 |
189 | )
190 | }
191 | }
192 |
193 | export default Profile3
194 |
--------------------------------------------------------------------------------
/screens/Profile3/ProfileStyle.js:
--------------------------------------------------------------------------------
1 | import { Dimensions } from 'react-native'
2 |
3 | export default {
4 | cardContainer: {
5 | flex: 1,
6 | },
7 | container: {
8 | flex: 1,
9 | },
10 | coverBio: {
11 | color: '#FFF',
12 | fontSize: 15,
13 | fontWeight: '600',
14 | },
15 | coverContainer: {
16 | marginBottom: 55,
17 | position: 'relative',
18 | },
19 | coverImage: {
20 | height: Dimensions.get('window').width * (3.5 / 4),
21 | width: Dimensions.get('window').width,
22 | },
23 | coverMetaContainer: {
24 | backgroundColor: 'transparent',
25 | paddingBottom: 10,
26 | paddingLeft: 135,
27 | },
28 | coverName: {
29 | color: '#FFF',
30 | fontSize: 28,
31 | fontWeight: 'bold',
32 | paddingBottom: 2,
33 | },
34 | coverTitle: {
35 | color: '#FFF',
36 | fontSize: 24,
37 | fontWeight: 'bold',
38 | textAlign: 'center',
39 | },
40 | coverTitleContainer: {
41 | backgroundColor: 'transparent',
42 | flex: 1,
43 | justifyContent: 'space-between',
44 | paddingTop: 45,
45 | },
46 | headerContainer: {
47 | alignItems: 'center',
48 | backgroundColor: '#FFF',
49 | },
50 | indicatorTab: {
51 | backgroundColor: 'transparent',
52 | },
53 | masonryContainer: {
54 | flexDirection: 'row',
55 | flexWrap: 'wrap',
56 | justifyContent: 'space-between',
57 | marginLeft: 0,
58 | marginRight: 0,
59 | },
60 | profileImage: {
61 | borderColor: '#FFF',
62 | borderRadius: 55,
63 | borderWidth: 3,
64 | height: 110,
65 | width: 110,
66 | },
67 | profileImageContainer: {
68 | bottom: 0,
69 | left: 10,
70 | position: 'absolute',
71 | },
72 | sceneContainer: {
73 | marginTop: 15,
74 | },
75 | scroll: {
76 | backgroundColor: '#FFF',
77 | },
78 | tabBar: {
79 | backgroundColor: 'transparent',
80 | marginBottom: -10,
81 | marginLeft: 120,
82 | marginRight: 5,
83 | },
84 | tabContainer: {
85 | flex: 1,
86 | marginBottom: 12,
87 | marginTop: -55,
88 | position: 'relative',
89 | zIndex: 10,
90 | },
91 | tabRow: {
92 | flexWrap: 'wrap',
93 | flexDirection: 'column',
94 | justifyContent: 'flex-start',
95 | alignItems: 'flex-start',
96 | flex: 1,
97 | },
98 | tabLabelNumber: {
99 | color: 'black',
100 | fontSize: 22,
101 | textAlign: 'center',
102 | marginBottom: 2,
103 | },
104 | tabLabelText: {
105 | color: 'black',
106 | fontSize: 10,
107 | textAlign: 'left',
108 | },
109 | }
110 |
--------------------------------------------------------------------------------
/screens/Profile3/contact.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Cherprang BNK48",
3 | "username": "cherprang_BNK48",
4 | "bio": "Singer",
5 | "avatar":
6 | "https://i.imgur.com/FmeKYGe.jpg",
7 | "avatarBackground":
8 | "https://i.imgur.com/k2XhDRw.jpg",
9 | "posts": [
10 | {
11 | "id": 1,
12 | "words": "cupiditate qui cum",
13 | "sentence": "Ipsum laborum quasi debitis dolores veniam.",
14 | "sentences":
15 | "Impedit veritatis harum nihil dolores dolorem optio assumenda. Laborum saepe voluptas officia odit. Ut voluptas mollitia mollitia eum autem quisquam qui aut. Et ipsa hic harum molestias et quam qui cum. Sint sit soluta.",
16 | "paragraph":
17 | "Beatae voluptas ea magni quibusdam dolorem sit aut qui. Dolorem rerum et consequuntur inventore officia excepturi dolore architecto fuga. Quia consequatur asperiores rerum qui corporis dolorum. At harum velit adipisci iste odit modi veniam ut. Deserunt quibusdam velit non ea.",
18 | "image":
19 | "https://i.imgur.com/9JWV4yR.jpg",
20 | "imageHeight": 1080,
21 | "imageWidth": 1350,
22 | "createdDate": "2017-11-21T02:33:53.770Z",
23 | "user": {
24 | "name": "Ronaldo",
25 | "username": "Ronaldo.Effertz",
26 | "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/samuelkraft/128.jpg",
27 | "email": "Ronaldo.Effertz.Deckow@hotmail.com"
28 | }
29 | },
30 | {
31 | "id": 2,
32 | "words": "est voluptatum aut",
33 | "sentence": "Omnis omnis aut dolor quaerat sunt et optio.",
34 | "sentences":
35 | "Nam numquam magni saepe. Deserunt aspernatur dolorem libero soluta sint molestias et sint sed. Maiores id quis assumenda voluptates quos ut saepe officia voluptatem. Ea placeat sed ut. Modi sed earum voluptas cumque unde eum doloribus ipsam.",
36 | "paragraph":
37 | "Quam aut reprehenderit asperiores aut. Sunt quis aspernatur incidunt. Illo et perferendis ex incidunt eos ut maxime dolorem voluptatem. Qui rem nihil quos cumque eum doloribus. Quae beatae tempore commodi.",
38 | "image":
39 | "https://i.pinimg.com/564x/20/60/f7/2060f7703b82b54bc3fee157589044a2.jpg",
40 | "imageHeight": 1350,
41 | "imageWidth": 1080,
42 | "createdDate": "2017-11-20T18:04:58.858Z",
43 | "user": {
44 | "name": "Markus",
45 | "username": "Markus.Price68",
46 | "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/kikillo/128.jpg",
47 | "email": "Markus.Price68.Dicki@yahoo.com"
48 | }
49 | },
50 | {
51 | "id": 3,
52 | "words": "vitae voluptas quia",
53 | "sentence": "Voluptates dolor ad rem amet voluptas.",
54 | "sentences": "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
55 | "paragraph": "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
56 | "createdDate": "2017-03-24T10:56:15.461Z",
57 | "image":
58 | "https://i.pinimg.com/564x/1d/d8/87/1dd887fb10b2805e1023a6d27dc1f0ec.jpg",
59 | "imageHeight": 1235,
60 | "imageWidth": 1080,
61 | "user": {
62 | "name": "Magali",
63 | "username": "Magali16",
64 | "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/mastermindesign/128.jpg",
65 | "email": "Magali1664@gmail.com"
66 | }
67 | },
68 | {
69 | "id": 4,
70 | "words": "vitae voluptas quia",
71 | "sentence": "Voluptates dolor ad rem amet voluptas.",
72 | "sentences": "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
73 | "paragraph": "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
74 | "createdDate": "2017-03-24T10:56:15.461Z",
75 | "image":
76 | "https://i.imgur.com/SClIy2m.jpg",
77 | "imageHeight": 826,
78 | "imageWidth": 1080,
79 | "user": {
80 | "name": "Magali",
81 | "username": "Magali16",
82 | "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/mastermindesign/128.jpg",
83 | "email": "Magali1664@gmail.com"
84 | }
85 | },
86 | {
87 | "id": 5,
88 | "words": "vitae voluptas quia",
89 | "sentence": "Voluptates dolor ad rem amet voluptas.",
90 | "sentences": "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
91 | "paragraph": "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
92 | "createdDate": "2017-03-24T10:56:15.461Z",
93 | "image":
94 | "https://i.pinimg.com/564x/a2/ab/be/a2abbe14490fdda55aba52326474a4c7.jpg",
95 | "imageHeight": 634,
96 | "imageWidth": 960,
97 | "user": {
98 | "name": "Magali",
99 | "username": "Magali16",
100 | "avatar": "https://i.pinimg.com/736x/af/2f/94/af2f94edd3905359b3f7f99a70d5288a.jpg",
101 | "email": "Magali1664@gmail.com"
102 | }
103 | },
104 | {
105 | "id": 6,
106 | "words": "vitae voluptas quia",
107 | "sentence": "Voluptates dolor ad rem amet voluptas.",
108 | "sentences": "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
109 | "paragraph": "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
110 | "createdDate": "2017-03-24T10:56:15.461Z",
111 | "image":
112 | "https://i.pinimg.com/564x/c3/bc/66/c3bc666fe2cb6407580ef494637eea8e.jpg",
113 | "imageHeight": 720,
114 | "imageWidth": 960,
115 | "user": {
116 | "name": "Magali",
117 | "username": "Magali16",
118 | "avatar": "https://i.pinimg.com/236x/67/7e/74/677e74d51a75d4f82448604e83c182c1.jpg",
119 | "email": "Magali1664@gmail.com"
120 | }
121 | },
122 | {
123 | "id": 7,
124 | "words": "vitae voluptas quia",
125 | "sentence": "Voluptates dolor ad rem amet voluptas.",
126 | "sentences": "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
127 | "paragraph": "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
128 | "createdDate": "2017-03-24T10:56:15.461Z",
129 | "image":
130 | "https://i.imgur.com/hRC0U2s.jpg",
131 | "imageHeight": 525,
132 | "imageWidth": 680,
133 | "user": {
134 | "name": "Magali",
135 | "username": "Magali16",
136 | "avatar":
137 | "https://s3.amazonaws.com/uifaces/faces/twitter/mastermindesign/128.jpg",
138 | "email": "Magali1664@gmail.com"
139 | }
140 | },
141 | {
142 | "id": 8,
143 | "words": "vitae voluptas quia",
144 | "sentence": "Voluptates dolor ad rem amet voluptas.",
145 | "sentences":
146 | "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
147 | "paragraph":
148 | "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
149 | "createdDate": "2017-03-24T10:56:15.461Z",
150 | "image":
151 | "https://i.imgur.com/ZWiVaKl.jpg",
152 | "imageHeight": 480,
153 | "imageWidth": 480,
154 | "user": {
155 | "name": "Magali",
156 | "username": "Magali16",
157 | "avatar":
158 | "https://s3.amazonaws.com/uifaces/faces/twitter/mastermindesign/128.jpg",
159 | "email": "Magali1664@gmail.com"
160 | }
161 | },
162 | {
163 | "id": 9,
164 | "words": "vitae voluptas quia",
165 | "sentence": "Voluptates dolor ad rem amet voluptas.",
166 | "sentences":
167 | "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
168 | "paragraph":
169 | "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
170 | "createdDate": "2017-03-24T10:56:15.461Z",
171 | "image":
172 | "https://i.imgur.com/1iDsg9Q.jpg",
173 | "imageHeight": 600,
174 | "imageWidth": 600,
175 | "user": {
176 | "name": "Magali",
177 | "username": "Magali16",
178 | "avatar":
179 | "https://s3.amazonaws.com/uifaces/faces/twitter/mastermindesign/128.jpg",
180 | "email": "Magali1664@gmail.com"
181 | }
182 | },
183 | {
184 | "id": 10,
185 | "words": "vitae voluptas quia",
186 | "sentence": "Voluptates dolor ad rem amet voluptas.",
187 | "sentences":
188 | "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
189 | "paragraph":
190 | "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
191 | "createdDate": "2017-03-24T10:56:15.461Z",
192 | "image":
193 | "https://i.imgur.com/tjHSIUK.jpg",
194 | "imageHeight": 600,
195 | "imageWidth": 600,
196 | "user": {
197 | "name": "Magali",
198 | "username": "Magali16",
199 | "avatar":
200 | "https://s3.amazonaws.com/uifaces/faces/twitter/mastermindesign/128.jpg",
201 | "email": "Magali1664@gmail.com"
202 | }
203 | },
204 | {
205 | "id": 11,
206 | "words": "vitae voluptas quia",
207 | "sentence": "Voluptates dolor ad rem amet voluptas.",
208 | "sentences":
209 | "Rem ipsum quis. Animi ipsum ut at possimus. Beatae molestiae non odio soluta quidem ut suscipit.",
210 | "paragraph":
211 | "Veniam veritatis nihil illum rerum et. Temporibus facere sed delectus corporis alias. Et odio aliquid est. Quas sit et quia tempora sit eveniet quam.",
212 | "createdDate": "2017-03-24T10:56:15.461Z",
213 | "image":
214 | "https://i.imgur.com/BxQO3ac.jpg",
215 | "imageHeight": 600,
216 | "imageWidth": 600,
217 | "user": {
218 | "name": "Magali",
219 | "username": "Magali16",
220 | "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/mastermindesign/128.jpg",
221 | "email": "Magali1664@gmail.com"
222 | }
223 | }
224 | ]
225 | }
--------------------------------------------------------------------------------
/screens/Profile3/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | import contactData from './contact.json'
5 |
6 | import Profile from './Profile'
7 |
8 | const ProfileScreen = () =>
9 |
10 | ProfileScreen.navigationOptions = () => ({
11 | header: null,
12 | })
13 |
14 | ProfileScreen.propTypes = {
15 | navigation: PropTypes.object.isRequired,
16 | }
17 |
18 | export default ProfileScreen
19 |
--------------------------------------------------------------------------------
/screens/Setting1/Chevron.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Icon } from 'react-native-elements'
3 | import { Colors } from '../../constants'
4 |
5 | const Chevron = () => (
6 |
12 | )
13 |
14 | export default Chevron
15 |
--------------------------------------------------------------------------------
/screens/Setting1/Icon.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { StyleSheet, View } from 'react-native'
3 | import { Icon } from 'react-native-elements'
4 | import PropTypes from 'prop-types'
5 |
6 | const styles = StyleSheet.create({
7 | container: {
8 | alignItems: 'center',
9 | backgroundColor: 'black',
10 | borderColor: 'transparent',
11 | borderRadius: 10,
12 | borderWidth: 1,
13 | height: 34,
14 | justifyContent: 'center',
15 | marginLeft: 10,
16 | marginRight: 18,
17 | width: 34,
18 | },
19 | })
20 |
21 | const BaseIcon = ({ containerStyle, icon }) => (
22 |
23 |
30 |
31 | )
32 |
33 | BaseIcon.propTypes = {
34 | containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
35 | icon: PropTypes.object,
36 | iconStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
37 | }
38 |
39 | BaseIcon.defaultProps = {
40 | containerStyle: {},
41 | icon: {},
42 | iconStyle: {},
43 | }
44 |
45 | export default BaseIcon
46 |
--------------------------------------------------------------------------------
/screens/Setting1/InfoText.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { StyleSheet, Text, View } from 'react-native'
3 | import PropTypes from 'prop-types'
4 |
5 | const styles = StyleSheet.create({
6 | container: {
7 | paddingTop: 20,
8 | paddingBottom: 12,
9 | backgroundColor: '#F4F5F4',
10 | },
11 | infoText: {
12 | fontSize: 16,
13 | marginLeft: 20,
14 | color: 'gray',
15 | fontWeight: '500',
16 | },
17 | })
18 | const InfoText = ({ text }) => (
19 |
20 | {text}
21 |
22 | )
23 |
24 | InfoText.propTypes = {
25 | text: PropTypes.string.isRequired,
26 | }
27 |
28 | export default InfoText
29 |
--------------------------------------------------------------------------------
/screens/Setting1/Options.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { SafeAreaView, View } from 'react-native'
3 |
4 | import { Nav } from '../../components'
5 |
6 | const Options = (props) => {
7 | props.navigation.setOptions({
8 | header: ({navigation}) => (
9 |
10 |
11 |
12 | ),
13 | })
14 |
15 | return
16 | }
17 |
18 | export default Options
19 |
--------------------------------------------------------------------------------
/screens/Setting1/Setting.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { ScrollView, Switch, StyleSheet, Text, View } from 'react-native'
3 | import { Avatar, ListItem } from 'react-native-elements'
4 | import PropTypes from 'prop-types'
5 |
6 | import BaseIcon from './Icon'
7 | import Chevron from './Chevron'
8 | import InfoText from './InfoText'
9 |
10 | const styles = StyleSheet.create({
11 | scroll: {
12 | backgroundColor: 'white',
13 | },
14 | userRow: {
15 | alignItems: 'center',
16 | flexDirection: 'row',
17 | paddingBottom: 8,
18 | paddingLeft: 15,
19 | paddingRight: 15,
20 | paddingTop: 6,
21 | },
22 | userImage: {
23 | marginRight: 12,
24 | },
25 | listItemContainer: {
26 | height: 55,
27 | borderWidth: 0.5,
28 | borderColor: '#ECECEC',
29 | },
30 | })
31 |
32 | class SettingsScreen extends Component {
33 | static propTypes = {
34 | avatar: PropTypes.string.isRequired,
35 | name: PropTypes.string.isRequired,
36 | navigation: PropTypes.object.isRequired,
37 | emails: PropTypes.arrayOf(
38 | PropTypes.shape({
39 | email: PropTypes.string.isRequired,
40 | })
41 | ).isRequired,
42 | }
43 |
44 | state = {
45 | pushNotifications: true,
46 | }
47 |
48 | onPressSetting = () => {
49 | this.props.navigation.navigate('Options')
50 | }
51 |
52 | onChangePushNotifications = () => {
53 | this.setState(state => ({
54 | pushNotifications: !state.pushNotifications,
55 | }))
56 | }
57 |
58 | render() {
59 | const { avatar, name, emails: [firstEmail] } = this.props
60 | return (
61 |
62 |
63 |
64 |
69 |
70 |
71 | {name}
72 |
78 | {firstEmail.email}
79 |
80 |
81 |
82 |
83 |
84 |
93 | }
94 | leftIcon={
95 |
104 | }
105 | />
106 | this.onPressSetting()}
112 | containerStyle={styles.listItemContainer}
113 | leftIcon={
114 |
121 | }
122 | rightIcon={}
123 | />
124 | this.onPressSetting()}
129 | containerStyle={styles.listItemContainer}
130 | leftIcon={
131 |
138 | }
139 | rightIcon={}
140 | />
141 | this.onPressSetting()}
146 | containerStyle={styles.listItemContainer}
147 | leftIcon={
148 |
155 | }
156 | rightIcon={}
157 | />
158 |
159 |
160 |
161 | this.onPressSetting()}
164 | containerStyle={styles.listItemContainer}
165 | leftIcon={
166 |
173 | }
174 | rightIcon={}
175 | />
176 | this.onPressSetting()}
179 | containerStyle={styles.listItemContainer}
180 | leftIcon={
181 |
188 | }
189 | rightIcon={}
190 | />
191 | this.onPressSetting()}
194 | containerStyle={styles.listItemContainer}
195 | leftIcon={
196 |
205 | }
206 | rightIcon={}
207 | />
208 | this.onPressSetting()}
211 | containerStyle={styles.listItemContainer}
212 | leftIcon={
213 |
222 | }
223 | rightIcon={}
224 | />
225 | this.onPressSetting()}
228 | containerStyle={styles.listItemContainer}
229 | badge={{
230 | value: 999,
231 | textStyle: { fontSize: 14, color: 'white' },
232 | }}
233 | leftIcon={
234 |
243 | }
244 | rightIcon={}
245 | />
246 |
247 |
248 | )
249 | }
250 | }
251 |
252 | export default SettingsScreen
253 |
--------------------------------------------------------------------------------
/screens/Setting1/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { SafeAreaView } from 'react-native'
4 |
5 | import contactData from '../../mocks/contact.json'
6 |
7 | import { Nav } from '../../components'
8 | import Setting from './Setting'
9 |
10 | const SettingScreen = (props) => {
11 | props.navigation.setOptions({
12 | header: ({navigation}) => (
13 |
14 |
23 |
24 | ),
25 | })
26 |
27 | return
28 | }
29 |
30 | SettingScreen.propTypes = {
31 | navigation: PropTypes.object.isRequired,
32 | }
33 |
34 | export default SettingScreen
35 |
--------------------------------------------------------------------------------
/utils/datetime.js:
--------------------------------------------------------------------------------
1 | const timeDifference = (current, previous) => {
2 | const milliSecondsPerMinute = 60 * 1000
3 | const milliSecondsPerHour = milliSecondsPerMinute * 60
4 | const milliSecondsPerDay = milliSecondsPerHour * 24
5 | const milliSecondsPerMonth = milliSecondsPerDay * 30
6 | const milliSecondsPerYear = milliSecondsPerDay * 365
7 |
8 | const elapsed = current - previous
9 |
10 | if (elapsed < milliSecondsPerMinute / 3) {
11 | return 'just now'
12 | }
13 |
14 | if (elapsed < milliSecondsPerMinute) {
15 | return 'less than 1 min'
16 | } else if (elapsed < milliSecondsPerHour) {
17 | return Math.round(elapsed / milliSecondsPerMinute) + ' min'
18 | } else if (elapsed < milliSecondsPerDay) {
19 | return Math.round(elapsed / milliSecondsPerHour) + ' h'
20 | } else if (elapsed < milliSecondsPerMonth) {
21 | let days = Math.round(elapsed / milliSecondsPerDay)
22 | return `${days} day${days > 1 ? 's' : ''}`
23 | } else if (elapsed < milliSecondsPerYear) {
24 | return Math.round(elapsed / milliSecondsPerMonth) + ' mo'
25 | } else {
26 | return Math.round(elapsed / milliSecondsPerYear) + ' years'
27 | }
28 | }
29 |
30 | const timeDifferenceForDate = date => {
31 | const now = new Date().getTime()
32 | const updated = new Date(date).getTime()
33 |
34 | return timeDifference(now, updated)
35 | }
36 |
37 | export { timeDifference, timeDifferenceForDate }
38 |
--------------------------------------------------------------------------------
/utils/image.js:
--------------------------------------------------------------------------------
1 | const mansonry = (items, propName) => {
2 | return items.reduce(
3 | (p, c, k) => {
4 | if (k > 1) {
5 | if (p.leftHeight <= p.rightHeight) {
6 | return {
7 | ...p,
8 | leftCol: [...p.leftCol, c],
9 | leftHeight: p.leftHeight + c[propName],
10 | }
11 | } else {
12 | return {
13 | ...p,
14 | rightCol: [...p.rightCol, c],
15 | rightHeight: p.rightHeight + c[propName],
16 | }
17 | }
18 | } else {
19 | return p
20 | }
21 | },
22 | {
23 | leftCol: [items[0]],
24 | rightCol: [items[1]],
25 | leftHeight: items[0].imageHeight,
26 | rightHeight: items[1].imageHeight,
27 | }
28 | )
29 | }
30 |
31 | export { mansonry }
32 |
--------------------------------------------------------------------------------
/utils/index.js:
--------------------------------------------------------------------------------
1 | import * as datetime from './datetime'
2 | import * as image from './image'
3 |
4 | export { datetime, image }
5 |
--------------------------------------------------------------------------------