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:
Okechi Onyeje 2019-01-16 20:33:35 -05:00
parent a01d5345cf
commit 9b2b3c3402
18 changed files with 9810 additions and 94 deletions

2
.gitignore vendored
View File

@ -37,6 +37,8 @@ node_modules/
npm-debug.log
yarn-error.log
.envrc
.vscode/
storybook/
# BUCK
buck-out/

BIN
assets/GreenCheck.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

9022
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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",

View 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>
);
}
}

View 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;

View File

@ -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);

View 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 />
);
}
}
}

View File

@ -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
**/

View 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>
);
}
}

View 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;

View 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 };

View File

@ -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;

View File

@ -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,

View 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>
);
}
}

View 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;

View File

@ -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
View 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;
}
};