mirror of
https://bitbucket.org/tagfer_team/tagfer-app.git
synced 2025-12-25 03:37:41 +00:00
UPS8: Added ProfileView Form with header, footer
-still working on menu press functionality that renders menus - working on rendering profile switching modal popup - working on integrating getProfile calls from server
This commit is contained in:
parent
a01d5345cf
commit
9b2b3c3402
2
.gitignore
vendored
2
.gitignore
vendored
@ -37,6 +37,8 @@ node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
.envrc
|
||||
.vscode/
|
||||
storybook/
|
||||
|
||||
# BUCK
|
||||
buck-out/
|
||||
|
||||
BIN
assets/GreenCheck.png
Normal file
BIN
assets/GreenCheck.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 738 B |
9022
package-lock.json
generated
9022
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,7 @@
|
||||
"react-native-flash-message": "^0.1.10",
|
||||
"react-native-gesture-handler": "^1.0.12",
|
||||
"react-native-masked-text": "^1.9.2",
|
||||
"react-native-modal-dropdown": "^0.6.2",
|
||||
"react-native-vector-icons": "^4.6.0",
|
||||
"react-native-webview": "^2.14.3",
|
||||
"react-navigation": "^3.0.9",
|
||||
|
||||
60
src/components/BizCard/BizCardView.js
Normal file
60
src/components/BizCard/BizCardView.js
Normal file
@ -0,0 +1,60 @@
|
||||
/** Contains the base fields for a contact reuse **/
|
||||
import React, { Component } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { Tile } from 'react-native-elements';
|
||||
import { PROFILE_FORM, CONTACT_FORM, SOCIAL_FORM } from '../FormTypes';
|
||||
import { Spacer } from '../common';
|
||||
import { strings } from '../../locales/i18n';
|
||||
import styles from './styles';
|
||||
|
||||
// Since we have duplicate keys between contact and profile we can't use this.props
|
||||
// so we track what has been populated here
|
||||
|
||||
export default class BizCard extends Component {
|
||||
|
||||
/**
|
||||
* Renders the business card tile
|
||||
**/
|
||||
renderBusinessCardTile() {
|
||||
let base64 = '';
|
||||
if (this.props.formType === CONTACT_FORM) {
|
||||
base64 = this.props.contactBizCardImg;
|
||||
} else if (this.props.formType === PROFILE_FORM) {
|
||||
base64 = this.props.profileBizCardImg;
|
||||
} else if (this.props.formType === SOCIAL_FORM) {
|
||||
base64 = this.props.socialBizCardImg;
|
||||
}
|
||||
if (base64) {
|
||||
return (
|
||||
<Tile
|
||||
imageSrc={{ uri: base64 }}
|
||||
featured
|
||||
containerStyle={styles.tileContainerStyle}
|
||||
imageContainerStyle={styles.tileStyle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Tile
|
||||
featured
|
||||
title={strings('bizCard.photoTile_noCard')}
|
||||
containerStyle={styles.tileContainerStyle}
|
||||
imageContainerStyle={styles.tileStyle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render method
|
||||
**/
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.viewStyle}>
|
||||
<Spacer space={45} />
|
||||
{this.renderBusinessCardTile()}
|
||||
<View style={styles.buttonContainerStyle} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
37
src/components/BizCard/styles.js
Normal file
37
src/components/BizCard/styles.js
Normal file
@ -0,0 +1,37 @@
|
||||
import { colors, Dimensions } from '../styleVars';
|
||||
|
||||
const width = Dimensions.get('window').width * 0.9;
|
||||
const height = width * 0.57; // ( 2 / 3.5 = 0.57) Business card dimensions
|
||||
|
||||
const styles = {
|
||||
tileContainerStyle: {
|
||||
height,
|
||||
width,
|
||||
marginTop: 15,
|
||||
marginBottom: 15
|
||||
},
|
||||
tileStyle: {
|
||||
height,
|
||||
width
|
||||
},
|
||||
buttonContainerStyle: {
|
||||
flex: 2,
|
||||
marginTop: 15,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
halfButtonStyle: {
|
||||
backgroundColor: colors.buttonBlue,
|
||||
flex: 1,
|
||||
borderRadius: 5
|
||||
},
|
||||
viewStyle: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
colors
|
||||
};
|
||||
|
||||
export default styles;
|
||||
@ -2,24 +2,21 @@
|
||||
import _ from 'lodash';
|
||||
import React, { Component } from 'react';
|
||||
import { Dimensions, Image, Text, View } from 'react-native';
|
||||
import { NavigationActions } from 'react-navigation';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import ModalDropdown from 'react-native-modal-dropdown';
|
||||
import { connect } from 'react-redux';
|
||||
import colors from '../../config/colors.json';
|
||||
import { profileFetch } from '../../actions';
|
||||
|
||||
const GREEN_CHECK_IMAGE = require('../../../assets/GreenCheck.png');
|
||||
|
||||
const SCREEN_WIDTH = Dimensions.get('window').width;
|
||||
let profileNames = [];
|
||||
|
||||
class Footer extends Component {
|
||||
export default class Footer extends Component {
|
||||
/**
|
||||
* Component Will Mount
|
||||
**/
|
||||
componentWillMount() {
|
||||
this.props.profileFetch();
|
||||
//this.props.profileFetch();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,14 +81,14 @@ class Footer extends Component {
|
||||
* Navigates to the profile home screen for the given profile
|
||||
**/
|
||||
processProfileSelection(idx) {
|
||||
const resetAction = NavigationActions.reset({
|
||||
index: 0,
|
||||
actions: [
|
||||
NavigationActions.navigate({ routeName: 'mainOptionsMenu', params: { profileIndex: idx, profileName: this.props.profiles[idx].profileName } })
|
||||
]
|
||||
});
|
||||
// const resetAction = NavigationActions.reset({
|
||||
// index: 0,
|
||||
// actions: [
|
||||
// NavigationActions.navigate({ routeName: 'mainOptionsMenu', params: { profileIndex: idx, profileName: this.props.profiles[idx].profileName } })
|
||||
// ]
|
||||
// });
|
||||
|
||||
this.props.navigation.dispatch(resetAction);
|
||||
// this.props.navigation.dispatch(resetAction);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -307,17 +304,3 @@ const styles = {
|
||||
borderRadius: 15
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Map State to Props
|
||||
**/
|
||||
const mapStateToProps = state => {
|
||||
// converts Profile objects into profile arrays
|
||||
const profiles = _.map(state.profiles, (val, uid) => {
|
||||
return { ...val, uid };
|
||||
});
|
||||
|
||||
return { profiles };
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, { profileFetch })(Footer);
|
||||
|
||||
86
src/components/forms/ProfileForms/ProfileForm.js
Normal file
86
src/components/forms/ProfileForms/ProfileForm.js
Normal file
@ -0,0 +1,86 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Animated, View } from 'react-native';
|
||||
import ProfileViewForm from './ProfileViewForm';
|
||||
import { PROFILE_FORM } from '../../FormTypes';
|
||||
import { SCREEN_WIDTH } from './styles';
|
||||
|
||||
const DOTS_SIZE = ['first', 'second'];
|
||||
const scrollX = new Animated.Value(0);
|
||||
|
||||
export default class ProfileForm extends Component {
|
||||
render() {
|
||||
switch (this.props.profileFormMode) {
|
||||
case 'view':
|
||||
return (
|
||||
<View>
|
||||
<ProfileViewForm
|
||||
defaultProfile={/*this.props.defaultProfile*/
|
||||
{
|
||||
keywords: ['webdev', 'music', 'freelance'],
|
||||
profileName: 'Business Profile',
|
||||
tagferId: 'jdshgbjdhbf',
|
||||
fullName: 'testName',
|
||||
headline: 'Software Engineer at Company',
|
||||
titleAndCompany: 'Title and Company',
|
||||
location: 'Some Location',
|
||||
isPublicProfile: true,
|
||||
about: 'about txt',
|
||||
bizCardImg: null,
|
||||
avatarImg: null,
|
||||
firstName: null,
|
||||
lastName: 'Lastynameson',
|
||||
primaryPhone: '4435465434',
|
||||
secondaryPhone: '4434532432',
|
||||
extension: 'nice-extension',
|
||||
howIHelp: 'i help alot i think...',
|
||||
whatINeed: 'i need more needs',
|
||||
workPhone: '4435243746',
|
||||
fax: '7654635432',
|
||||
email: 'some@example.com',
|
||||
website: 'examplesofexam.com',
|
||||
street: 'street road',
|
||||
address2: '443 agreat dres',
|
||||
city: 'cityville',
|
||||
region: 'DC',
|
||||
postalCode: '20001',
|
||||
country: 'USA',
|
||||
referralId: '',
|
||||
addedExperience: [{
|
||||
jobTitle: 'Engineer',
|
||||
jobCompany: 'Some Company',
|
||||
jobDates: '01/01/19 - 01/15/19',
|
||||
jobLocation: 'USA',
|
||||
jobSummary: 'My great job summary'
|
||||
}],
|
||||
addedEducation: [{
|
||||
school: 'UMD',
|
||||
degree: 'B.S.',
|
||||
fieldOfStudy: 'Computer Engineering',
|
||||
schoolDates: '01/11/18 - 01/19/19',
|
||||
educationSummary: 'Some cool education'
|
||||
}]
|
||||
}
|
||||
}
|
||||
profiles={this.props.profiles}
|
||||
formMode={PROFILE_FORM}
|
||||
DOTS_SIZE={DOTS_SIZE}
|
||||
scrollX={scrollX}
|
||||
position={Animated.divide(scrollX, SCREEN_WIDTH)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
case 'edit':
|
||||
return (
|
||||
<View />
|
||||
);
|
||||
case 'create':
|
||||
return (
|
||||
<View />
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<View />
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,13 +2,13 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Alert, Animated, Dimensions, ScrollView, Text, View } from 'react-native';
|
||||
import { Button, Card, CheckBox, Divider, FormInput, Icon } from 'react-native-elements';
|
||||
import ProfileAvatar from '../ProfileAvatar';
|
||||
import BizCard from '../BizCard';
|
||||
import { Confirm, FormLabel, FormMessage, Keyword, Spacer, TextButton } from '../common';
|
||||
import { PROFILE_FORM } from '../FormTypes';
|
||||
import colors from '../../config/colors.json';
|
||||
import { strings } from '../../locales/i18n';
|
||||
import { toQueryString } from '../../utils/aux';
|
||||
import ProfileAvatar from '../../ProfileAvatar';
|
||||
import BizCard from '../../BizCard';
|
||||
import { Confirm, FormLabel, FormMessage, Keyword, Spacer, TextButton } from '../../common';
|
||||
import { PROFILE_FORM } from '../../FormTypes';
|
||||
import colors from '../../../config/colors.json';
|
||||
import { strings } from '../../../locales/i18n';
|
||||
import { toQueryString } from '../../../utils/aux';
|
||||
|
||||
const SCREEN_WIDTH = Dimensions.get('window').width;
|
||||
const DOTS_SIZE = ['first', 'second'];
|
||||
@ -100,59 +100,6 @@ class ProfileForm extends Component {
|
||||
this.props.profileUpdate({ prop: 'keywords', value: newKeywordsArr });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a webview for the user to login to LinkedIn
|
||||
**/
|
||||
loginWithAuth0LinkedIn = async () => {
|
||||
const redirectUrl = AuthSession.getRedirectUrl();
|
||||
|
||||
const result = await AuthSession.startAsync({
|
||||
authUrl: `${privateKeys.auth0.domain}/authorize` + toQueryString({
|
||||
connection: 'linkedin',
|
||||
client_id: privateKeys.auth0.clientId,
|
||||
response_type: 'token',
|
||||
scope: 'openid profile',
|
||||
audience: 'https://tagfer.com/gettwitteruser', //TODO CREATE AN APP FOR LINKEDIN
|
||||
redirect_uri: redirectUrl
|
||||
}),
|
||||
});
|
||||
|
||||
if (result.type === 'success') {
|
||||
this.handleParams(result.params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the login response to get the LinkedIn data
|
||||
**/
|
||||
handleParams = async (responseObj) => {
|
||||
if (responseObj.error) {
|
||||
Alert.alert('Error', responseObj.error_description || strings('common.error.loginFailed'));
|
||||
return;
|
||||
}
|
||||
let nickname = '';
|
||||
const userInfo = await fetch(`${privateKeys.auth0.domain}/userinfo?access_token=${responseObj.access_token}`);
|
||||
if (userInfo.status === 200) {
|
||||
const parsedUserInfo = await userInfo.json();
|
||||
nickname = parsedUserInfo.nickname;
|
||||
} else {
|
||||
console.log('Something went wrong. ErrorCode: ', userInfo.status);
|
||||
}
|
||||
nickname = nickname.replace(/"/g, '');
|
||||
nickname = nickname.replace(/ /g, '+');
|
||||
|
||||
const userSearchResponse = await fetch(`${privateKeys.auth0.domain}/api/v2/users?q=nickname%3A%22${nickname}%22'`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
authorization: `Bearer ${privateKeys.auth0.managementToken}`
|
||||
}
|
||||
});
|
||||
|
||||
const userSearchParsed = await userSearchResponse.json();
|
||||
|
||||
this.extractLinkedInData(userSearchParsed);
|
||||
}
|
||||
|
||||
/**
|
||||
* The search brings back an array and we need to find the user's LinkedIn data
|
||||
**/
|
||||
329
src/components/forms/ProfileForms/ProfileViewForm.js
Normal file
329
src/components/forms/ProfileForms/ProfileViewForm.js
Normal file
@ -0,0 +1,329 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Animated, ScrollView, Text, View } from 'react-native';
|
||||
import { Card, CheckBox, Divider, Icon } from 'react-native-elements';
|
||||
import { FormLabel, Spacer } from '../../common';
|
||||
import { PROFILE_FORM } from '../../FormTypes';
|
||||
import BizCardView from '../../../components/BizCard/BizCardView';
|
||||
import styles from './styles';
|
||||
import { Keyword } from './../../common/Keyword';
|
||||
import { strings } from '../../../locales/i18n';
|
||||
|
||||
export default class ProfileViewForm extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.renderKeywords = this.renderKeywords.bind(this);
|
||||
}
|
||||
|
||||
renderAboutSection() {
|
||||
const defaultProfile = this.props.defaultProfile;
|
||||
return (
|
||||
<Card>
|
||||
<FormLabel bold labelText={strings('common.contactFields.about_labelText')} />
|
||||
<FormLabel labelText={defaultProfile.about} />
|
||||
|
||||
<FormLabel bold labelText={strings('common.contactFields.howIHelp_labelText_profile')} />
|
||||
<FormLabel labelText={defaultProfile.howIHelp} />
|
||||
|
||||
<FormLabel bold labelText={strings('common.contactFields.whatINeed_labelText_profile')} />
|
||||
<FormLabel labelText={defaultProfile.whatINeed} />
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
renderDetailsSection() {
|
||||
const defaultProfile = this.props.defaultProfile;
|
||||
return (
|
||||
<View style={{ flex: 1, flexDirection: 'column', alignItems: 'center', marginLeft: -10 }}>
|
||||
<FormLabel bold labelText={`@${defaultProfile.tagferId}`} textStyle={{ color: styles.colors.darkGreen, fontSize: 18 }} />
|
||||
<FormLabel bold labelText={defaultProfile.fullName} textStyle={{ fontSize: 22, marginHorizontal: 20, color: styles.colors.darkGrey }} />
|
||||
<FormLabel bold labelText={defaultProfile.headline} textStyle={{ fontSize: 15, marginHorizontal: 20, color: styles.colors.labelBlue }} />
|
||||
<FormLabel bold labelText={defaultProfile.titleAndCompany} textStyle={{ fontSize: 15, marginHorizontal: 20 }} />
|
||||
<FormLabel bold labelText={defaultProfile.location} textStyle={{ fontSize: 15, marginHorizontal: 20, color: styles.colors.middleGrey }} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
renderExperienceSection() {
|
||||
const defaultProfile = this.props.defaultProfile;
|
||||
// NORMAL - VIEW MODE
|
||||
let isAddedExperienceEmpty = true;
|
||||
console.log(`addedExperience: ${defaultProfile.addedExperience}`);
|
||||
for (let i = 0; i < defaultProfile.addedExperience.length; i++) {
|
||||
if (!isAddedExperienceEmpty) {
|
||||
break;
|
||||
}
|
||||
// for (const property in defaultProfile.addedExperience[i]) {
|
||||
// if (defaultProfile.addedExperience[i][property].length > 0) {
|
||||
// isAddedExperienceEmpty = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
if (!isAddedExperienceEmpty) {
|
||||
const experienceList = defaultProfile.addedExperience.map((data, index) => {
|
||||
if (index > 0) {
|
||||
return (
|
||||
<View key={index}>
|
||||
<Divider style={styles.dividerStyle} />
|
||||
<FormLabel labelText={data.jobTitle} />
|
||||
<FormLabel labelText={data.jobCompany} />
|
||||
<FormLabel labelText={data.jobDates} />
|
||||
<FormLabel labelText={data.jobLocation} />
|
||||
<FormLabel labelText={data.jobSummary} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View key={index}>
|
||||
<FormLabel labelText={data.jobTitle} />
|
||||
<FormLabel labelText={data.jobCompany} />
|
||||
<FormLabel labelText={data.jobDates} />
|
||||
<FormLabel labelText={data.jobLocation} />
|
||||
<FormLabel labelText={data.jobSummary} />
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<FormLabel bold labelText={strings('common.contactFields.experience_labelText')} />
|
||||
{experienceList}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
renderEducationSection() {
|
||||
const defaultProfile = this.props.defaultProfile;
|
||||
let isAddedEducationEmpty = true;
|
||||
console.log(`addedEducation: ${defaultProfile.addedEducation}`);
|
||||
for (let i = 0; i < defaultProfile.addedEducation.length; i++) {
|
||||
if (!isAddedEducationEmpty) {
|
||||
break;
|
||||
}
|
||||
// for (const property in defaultProfile.addedEducation[i]) {
|
||||
// if (defaultProfile.addedEducation[i][property].length > 0) {
|
||||
// isAddedEducationEmpty = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
if (!isAddedEducationEmpty) {
|
||||
const educationList = defaultProfile.addedEducation.map((data, index) => {
|
||||
if (index > 0) {
|
||||
return (
|
||||
<View key={index}>
|
||||
<Divider style={styles.dividerStyle} />
|
||||
<FormLabel labelText={data.school} />
|
||||
<FormLabel labelText={data.degree} />
|
||||
<FormLabel labelText={data.fieldOfStudy} />
|
||||
<FormLabel labelText={data.schoolDates} />
|
||||
<FormLabel labelText={data.educationSummary} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View key={index}>
|
||||
<FormLabel labelText={data.school} />
|
||||
<FormLabel labelText={data.degree} />
|
||||
<FormLabel labelText={data.fieldOfStudy} />
|
||||
<FormLabel labelText={data.schoolDates} />
|
||||
<FormLabel labelText={data.educationSummary} />
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<FormLabel bold labelText={strings('common.contactFields.education_labelText')} />
|
||||
{educationList}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
renderKeywordsSection() {
|
||||
const defaultProfile = this.props.defaultProfile;
|
||||
if (defaultProfile.keywords.length > 0) {
|
||||
return (
|
||||
<Card>
|
||||
<View style={styles.keywordViewStyle}>
|
||||
{this.renderKeywords()}
|
||||
</View>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
renderPhoneSection(phone, phoneLabel) {
|
||||
if (!phone) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<FormLabel bold labelText={phoneLabel} />
|
||||
<FormLabel labelText={phone} />
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
renderWorkPhoneSection() {
|
||||
const { workPhone, extension } = this.props.defaultProfile;
|
||||
console.log(`Work Phone: ${workPhone}`);
|
||||
console.log(`Extension: ${extension}`);
|
||||
if (!workPhone && !extension) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<FormLabel bold labelText={strings('common.contactFields.phone_work_labelText')} />
|
||||
<FormLabel labelText={workPhone} />
|
||||
|
||||
<FormLabel bold labelText={strings('common.contactFields.extension_labelText')} />
|
||||
<FormLabel labelText={extension} />
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders each keyword onto the screen
|
||||
**/
|
||||
renderKeywords() {
|
||||
const keywords = this.props.defaultProfile.keywords;
|
||||
return keywords.map((data, index) =>
|
||||
(
|
||||
<Keyword
|
||||
key={index}
|
||||
title={data}
|
||||
onPressX={() => this.removeKeyword(index)}
|
||||
displayX={this.props.isEditMode}
|
||||
index={index}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
renderAvatarBizCardSlider() {
|
||||
return (
|
||||
<View style={styles.detailsSectionStyle}>
|
||||
<ScrollView
|
||||
horizontal
|
||||
pagingEnabled
|
||||
showsHorizontalScrollIndicator={false}
|
||||
onScroll={Animated.event(
|
||||
[{ nativeEvent: { contentOffset: { x: this.props.scrollX } } }]
|
||||
)}
|
||||
scrollEventThrottle={16}
|
||||
>
|
||||
<View style={styles.slideStyle}>
|
||||
{/* <ProfileAvatar
|
||||
{...this.props}
|
||||
formType={PROFILE_FORM}
|
||||
isEditMode={this.props.profileFormMode}
|
||||
/> */}
|
||||
{this.renderDetailsSection()}
|
||||
</View>
|
||||
|
||||
<View style={styles.slideStyle}>
|
||||
<BizCardView
|
||||
formType={PROFILE_FORM}
|
||||
formMode={this.props.formMode}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
{/* <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center' }}>
|
||||
{this.props.DOTS_SIZE.map((_, i) => {
|
||||
const opacity = this.props.position.interpolate({
|
||||
inputRange: [i - 1, i, i + 1],
|
||||
outputRange: [0.3, 1, 0.3],
|
||||
extrapolate: 'clamp'
|
||||
});
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
key={i}
|
||||
style={{ opacity, height: 10, width: 10, backgroundColor: '#595959', margin: 8, borderRadius: 5 }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
</View> */}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
renderEmailSection() {
|
||||
const { email } = this.props.defaultProfile;
|
||||
if (!email) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<FormLabel bold labelText={strings('common.contactFields.email_labelText')} />
|
||||
<FormLabel labelText={email} />
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
renderWebsiteSection() {
|
||||
const { website } = this.props.defaultProfile;
|
||||
if (!website) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<FormLabel bold labelText={strings('common.contactFields.website_labelText')} />
|
||||
<FormLabel labelText={website} />
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
renderAddressSection() {
|
||||
const { street, address2, city, region, postalCode, country } = this.props.defaultProfile;
|
||||
if (!street && !address2 && !city && !region && !postalCode && !country) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<FormLabel bold labelText={strings('common.contactFields.address_labelText')} />
|
||||
<FormLabel labelText={street} />
|
||||
<FormLabel labelText={address2} />
|
||||
<FormLabel labelText={city} />
|
||||
<FormLabel labelText={region} />
|
||||
<FormLabel labelText={postalCode} />
|
||||
<FormLabel labelText={country} />
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
{this.renderAvatarBizCardSlider()}
|
||||
{this.renderAboutSection()}
|
||||
{this.renderExperienceSection()}
|
||||
|
||||
{this.renderEducationSection()}
|
||||
|
||||
{this.renderWebsiteSection()}
|
||||
{this.renderAddressSection()}
|
||||
{this.renderPhoneSection(this.props.defaultProfile.primaryPhone, strings('common.contactFields.phone_primary_labelText'))}
|
||||
{this.renderPhoneSection(this.props.defaultProfile.secondaryPhone, strings('common.contactFields.phone_secondary_labelText'))}
|
||||
{this.renderWorkPhoneSection()}
|
||||
{this.renderPhoneSection(this.props.defaultProfile.fax, strings('common.contactFields.fax_labelText'))}
|
||||
|
||||
{this.renderEmailSection()}
|
||||
{this.renderKeywordsSection()}
|
||||
<Spacer />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
93
src/components/forms/ProfileForms/styles.js
Normal file
93
src/components/forms/ProfileForms/styles.js
Normal file
@ -0,0 +1,93 @@
|
||||
import { SCREEN_WIDTH, colors } from '../../styleVars';
|
||||
|
||||
const styles = {
|
||||
slideStyle: {
|
||||
width: SCREEN_WIDTH,
|
||||
},
|
||||
detailsSectionStyle: {
|
||||
backgroundColor: colors.white,
|
||||
borderBottomWidth: 1,
|
||||
borderColor: colors.middleGrey
|
||||
},
|
||||
dividerStyle: {
|
||||
backgroundColor: colors.middleGrey,
|
||||
marginTop: 10,
|
||||
marginBottom: 15
|
||||
},
|
||||
textBoxStyles: {
|
||||
flex: 1,
|
||||
width: '100%',
|
||||
color: colors.black
|
||||
},
|
||||
inputAndButtonRow: {
|
||||
flex: 2,
|
||||
marginTop: 15,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
halfInputStyle: {
|
||||
flex: 1
|
||||
},
|
||||
keywordInputTextStyle: {
|
||||
width: '100%',
|
||||
},
|
||||
halfButtonStyle: {
|
||||
backgroundColor: colors.buttonBlue,
|
||||
flex: 1,
|
||||
borderRadius: 5
|
||||
},
|
||||
centeredInputContainerStyle: {
|
||||
borderBottomWidth: 0,
|
||||
marginLeft: 15,
|
||||
marginRight: 0
|
||||
},
|
||||
centeredInputTextStyle: {
|
||||
textAlign: 'center',
|
||||
color: colors.black
|
||||
},
|
||||
centeredTextBoxStyles: {
|
||||
textAlign: 'center',
|
||||
flex: 1,
|
||||
width: '100%',
|
||||
color: colors.black
|
||||
},
|
||||
inputTextStyle: {
|
||||
width: '100%',
|
||||
color: colors.black
|
||||
},
|
||||
nameTextStyle: {
|
||||
fontSize: 22,
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
keywordViewStyle: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap'
|
||||
},
|
||||
keywordStyle: {
|
||||
borderWidth: 1,
|
||||
borderColor: colors.middleGrey,
|
||||
borderRadius: 15,
|
||||
},
|
||||
checkboxRowStyle: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-start'
|
||||
},
|
||||
helpIconStyle: {
|
||||
paddingLeft: 15,
|
||||
marginRight: -10
|
||||
},
|
||||
educationNumberTextStyle: {
|
||||
color: colors.orange,
|
||||
fontSize: 15,
|
||||
fontWeight: 'bold',
|
||||
marginHorizontal: 10,
|
||||
alignSelf: 'center'
|
||||
},
|
||||
colors,
|
||||
SCREEN_WIDTH
|
||||
};
|
||||
|
||||
export default styles;
|
||||
6
src/components/styleVars.js
Normal file
6
src/components/styleVars.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { Dimensions } from 'react-native';
|
||||
import colors from '../config/colors.json';
|
||||
|
||||
const SCREEN_WIDTH = Dimensions.get('window').width;
|
||||
|
||||
module.exports = { SCREEN_WIDTH, colors, Dimensions };
|
||||
@ -51,7 +51,11 @@ const endpoints = {
|
||||
linkedInLogin: {
|
||||
method: 'GET',
|
||||
url: `${baseurl}/auth/linkedin/login`
|
||||
}
|
||||
},
|
||||
getUserProfile: (profileNumber) => ({
|
||||
method: 'GET',
|
||||
url: `${baseurl}/profiles/${profileNumber}`
|
||||
})
|
||||
};
|
||||
|
||||
export default endpoints;
|
||||
|
||||
@ -15,8 +15,10 @@ import ForgotPasswordScreen from '../screens/auth/ForgotPasswordScreen';
|
||||
// PROFILE IMPORTS
|
||||
import ProfileQRCodeScanner from '../screens/profile/ProfileQRCodeScanner';
|
||||
import ProfileSearchScreen from '../screens/profile/ProfileSearchScreen';
|
||||
import ProfileHomeScreen from '../screens/profile/ProfileHomeScreen';
|
||||
|
||||
const MainNavigator = createStackNavigator({
|
||||
profileHome: ProfileHomeScreen,
|
||||
welcome: WelcomeScreen,
|
||||
login: LoginScreen,
|
||||
forgotPassword: ForgotPasswordScreen,
|
||||
|
||||
111
src/screens/profile/ProfileHomeScreen.js
Normal file
111
src/screens/profile/ProfileHomeScreen.js
Normal file
@ -0,0 +1,111 @@
|
||||
/** Main screen for viewing profiles **/
|
||||
import React, { Component } from 'react';
|
||||
import { KeyboardAvoidingView, Platform, ScrollView, View } from 'react-native';
|
||||
import { Button } from 'react-native-elements';
|
||||
import Footer from '../../components/common/Footer';
|
||||
import HeaderRight from '../../components/common/HeaderRight';
|
||||
import { Spacer } from '../../components/common';
|
||||
import ProfileForm from '../../components/forms/ProfileForms/ProfileForm';
|
||||
import { getUserProfiles } from '../../utils/profile';
|
||||
import { showFlashErrorMessage } from '../../utils/errorHandler';
|
||||
import styles from './styles';
|
||||
|
||||
export default class ProfileHomeScreen extends Component {
|
||||
static navigationOptions = ({ navigation }) =>
|
||||
({
|
||||
title: 'Business Profile',
|
||||
headerLeft: (
|
||||
<Button
|
||||
icon={{
|
||||
name: 'settings',
|
||||
type: 'simple-line-icon',
|
||||
color: styles.colors.middleGrey,
|
||||
size: 30
|
||||
}}
|
||||
onPress={() => navigation.navigate('DrawerOpen')}
|
||||
backgroundColor={styles.colors.transparent}
|
||||
/>
|
||||
),
|
||||
headerRight: <HeaderRight navigation={navigation} />
|
||||
});
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
profiles: [],
|
||||
loading: false,
|
||||
profileFormMode: 'view'//props.profileFormMode
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getUserProfiles();
|
||||
}
|
||||
|
||||
getUserProfiles() {
|
||||
if (!this.state.profiles.length === 0) {
|
||||
this.setState({
|
||||
loading: true
|
||||
}, async () => {
|
||||
try {
|
||||
const { profiles, defaultProfile } = await getUserProfiles();
|
||||
this.setState({
|
||||
loading: false,
|
||||
profiles, //these two states will be replaced with calls to realm to save the state in the apps memory db
|
||||
defaultProfile
|
||||
});
|
||||
} catch (error) {
|
||||
showFlashErrorMessage(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the main content for the screen
|
||||
**/
|
||||
renderContent() {
|
||||
return (
|
||||
<View style={styles.mainScreenViewStyle}>
|
||||
<View>
|
||||
<ScrollView>
|
||||
<ProfileForm
|
||||
profileFormMode={this.state.profileFormMode}
|
||||
profiles={this.state.profiles}
|
||||
defaultProfile={this.props.defaultProfile}
|
||||
/>
|
||||
<Spacer space={80} />
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
<View style={styles.mainFooterStyle}>
|
||||
<Footer
|
||||
{...this.props}
|
||||
index={4}
|
||||
profileIndex={this.props.profileIndex}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render method
|
||||
**/
|
||||
render() {
|
||||
if (Platform.OS === 'android') {
|
||||
return this.renderContent();
|
||||
}
|
||||
|
||||
//iOS
|
||||
return (
|
||||
<KeyboardAvoidingView
|
||||
style={{ flex: 1 }}
|
||||
keyboardVerticalOffset={90}
|
||||
behavior="padding"
|
||||
>
|
||||
{this.renderContent()}
|
||||
</KeyboardAvoidingView>
|
||||
);
|
||||
}
|
||||
}
|
||||
19
src/screens/profile/styles.js
Normal file
19
src/screens/profile/styles.js
Normal file
@ -0,0 +1,19 @@
|
||||
import { colors } from './../../components/styleVars';
|
||||
|
||||
const styles = {
|
||||
mainScreenViewStyle: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
mainFooterStyle: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: 60
|
||||
},
|
||||
colors
|
||||
};
|
||||
|
||||
export default styles;
|
||||
@ -1,10 +1,11 @@
|
||||
import appConfig from '../config/appConfig.json';
|
||||
|
||||
export function fetchAuth(endpoint, body) {
|
||||
//should only be used during signup and login flow to authenticate user
|
||||
export function fetchAuth(endpoint, body, userAuthToken) {
|
||||
const request = {
|
||||
method: endpoint.method,
|
||||
headers: {
|
||||
Authorization: appConfig.appSecret,
|
||||
Authorization: (!userAuthToken ? appConfig.appSecret : userAuthToken),
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
@ -12,3 +13,8 @@ export function fetchAuth(endpoint, body) {
|
||||
|
||||
return fetch(endpoint.url, request).then(res => res.json());
|
||||
}
|
||||
|
||||
//should be called after user has been authenticated inorder to access rest of applications api services on the baclend
|
||||
export function fetchGeneric(endpoint, body) {
|
||||
return fetchAuth(endpoint, body, 'realm-user-auth-token');
|
||||
}
|
||||
|
||||
18
src/utils/profile.js
Normal file
18
src/utils/profile.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { fetchGeneric } from '../utils/fetch';
|
||||
import endpoints from '../config/apiEndpoints';
|
||||
|
||||
export const getUserProfiles = async () => {
|
||||
try {
|
||||
let i;
|
||||
const profiles = [];
|
||||
let defaultProfile;
|
||||
for (i = 1; i <= 4; i++) {
|
||||
profiles[i] = await fetchGeneric(endpoints.getUserProfile(i), {});
|
||||
if (profiles[i].isPublicProfile) { defaultProfile = profiles[i]; }
|
||||
}
|
||||
return { profiles, defaultProfile };
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user