Merge branch 'master' of honey.fitz.guru:eventment-app

# Conflicts:
#	app/components/Login/LocalLogin.js
#	app/screens/Register.js
This commit is contained in:
Mike Fitzpatrick
2019-08-07 10:23:40 -04:00
102 changed files with 2111 additions and 2054 deletions

View File

@@ -5,7 +5,10 @@ import { fetchEvents } from '../../actions/events.js';
import AppHeader from './AppHeader.js';
const matchDispatchToProps = (dispatch) => ({
fetchEvents: () => dispatch(fetchEvents()),
fetchEvents: () => dispatch(fetchEvents()),
});
export default connect(null, matchDispatchToProps)(AppHeader);
export default connect(
null,
matchDispatchToProps,
)(AppHeader);

View File

@@ -10,27 +10,26 @@ import HeaderContentRight from './HeaderContentRight.container.js';
import styles from './AppHeader.styles.js';
export default class AppHeader extends Component {
static get propTypes() {
return {
fetchEvents: PropTypes.func.isRequired,
};
}
static get propTypes() {
return {
fetchEvents: PropTypes.func.isRequired,
};
}
componentDidMount() {
this.props.fetchEvents();
}
componentDidMount() {
this.props.fetchEvents();
}
render() {
const { navigation } = this.props;
render () {
const { navigation } = this.props;
return (
<Header
placement="left"
leftComponent={<HeaderContentRight navigation={navigation} />}
centerComponent={<HeaderTitle navigation={navigation} />}
rightComponent={<HeaderContentLeft navigation={navigation} />}
/>
);
}
return (
<Header
placement="left"
leftComponent={<HeaderContentRight navigation={navigation} />}
centerComponent={<HeaderTitle navigation={navigation} />}
rightComponent={<HeaderContentLeft navigation={navigation} />}
/>
);
}
}

View File

@@ -5,12 +5,15 @@ import { hasMultipleEvents } from '../../selectors/events.js';
import HeaderContentLeft from './HeaderContentLeft.js';
const matchStateToProps = (state, ownProps) => {
const { routeName } = ownProps.navigation.state;
const { routeName } = ownProps.navigation.state;
return {
activeRoute: routeName,
hasMultipleEvents: hasMultipleEvents(state),
};
return {
activeRoute: routeName,
hasMultipleEvents: hasMultipleEvents(state),
};
};
export default connect(matchStateToProps, null)(HeaderContentLeft);
export default connect(
matchStateToProps,
null,
)(HeaderContentLeft);

View File

@@ -1,53 +1,43 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Text,
TouchableOpacity,
View,
} from 'react-native';
import { Text, TouchableOpacity, View } from 'react-native';
import BackIcon from './IconButtons/BackIcon.js';
import EventsIcon from './IconButtons/EventsIcon.js';
export default function HeaderContentLeft({
activeRoute,
hasMultipleEvents,
navigation,
}) {
export default function HeaderContentLeft({ activeRoute, hasMultipleEvents, navigation }) {
const _goBack = () => {
if (hasActiveEvent) {
navigation.goBack();
return false;
}
const _goBack = () => {
if (hasActiveEvent) {
navigation.goBack();
return false;
console.log('nowhere to go...');
};
const _showEvents = () => {
navigation.navigate('Events');
return false;
};
if (activeRoute === 'Events') {
return <EventsIcon action={_goBack} />;
}
console.log('nowhere to go...');
};
if (activeRoute === 'Profile') {
return <BackIcon action={_goBack} />;
}
const _showEvents = () => {
navigation.navigate('Events');
return false;
};
if (activeRoute === 'Events') {
return <EventsIcon action={_goBack} />;
}
if (activeRoute === 'Profile') {
return <BackIcon action={_goBack} />;
}
return <EventsIcon action={hasMultipleEvents ? _showEvents : null} />
return <EventsIcon action={hasMultipleEvents ? _showEvents : null} />;
}
HeaderContentLeft.propTypes = {
activeRoute: PropTypes.string.isRequired,
hasActiveEvent: PropTypes.bool,
navigation: PropTypes.func.isRequired,
activeRoute: PropTypes.string.isRequired,
hasActiveEvent: PropTypes.bool,
navigation: PropTypes.func.isRequired,
};
HeaderContentLeft.defaultProps = {
hasActiveEvent: false,
hasActiveEvent: false,
};

View File

@@ -5,8 +5,11 @@ import { getProfileAvatarUrl } from '../../selectors/profile.js';
import HeaderContentRight from './HeaderContentRight.js';
const matchStateToProps = (state, ownProps) => ({
avatarUrl: getProfileAvatarUrl(state),
hideUserProfileButton: ownProps.navigation.state.routeName === 'Profile',
avatarUrl: getProfileAvatarUrl(state),
hideUserProfileButton: ownProps.navigation.state.routeName === 'Profile',
});
export default connect(matchStateToProps, null)(HeaderContentRight);
export default connect(
matchStateToProps,
null,
)(HeaderContentRight);

View File

@@ -4,14 +4,13 @@ import PropTypes from 'prop-types';
import UserProfileButton from './UserProfileButton/UserProfileButton.container.js';
export default function HeaderContentRight({ hideUserProfileButton, navigation }) {
if (hideUserProfileButton) {
return null;
}
if (hideUserProfileButton) {
return null;
}
return <UserProfileButton />;
return <UserProfileButton />;
}
HeaderContentRight.propTypes = {
hideUserProfileButton: PropTypes.bool.isRequired,
hideUserProfileButton: PropTypes.bool.isRequired,
};

View File

@@ -5,14 +5,17 @@ import { getActiveEvent, getDefaultEvent } from '../../../../selectors/events.js
import EventTitle from './EventTitle.js';
const matchStateToProps = (state) => {
const event = hasActiveEvent(state) ? getActiveEvent(state) : getDefaultEvent(state);
const event = hasActiveEvent(state) ? getActiveEvent(state) : getDefaultEvent(state);
return {
date: event.get('date'),
end: event.get('end'),
name: event.get('name'),
start: event.get('start'),
};
return {
date: event.get('date'),
end: event.get('end'),
name: event.get('name'),
start: event.get('start'),
};
};
export default connect(matchStateToProps, null)(EventTitle);
export default connect(
matchStateToProps,
null,
)(EventTitle);

View File

@@ -1,43 +1,33 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Text,
TouchableOpacity,
View,
} from 'react-native';
import { Text, TouchableOpacity, View } from 'react-native';
import styles from './EventTitle.styles.js';
export default function EventTitle({
action,
date,
end,
name,
start,
}) {
const _generateEventTitle = () => (
<View style={styles.eventInfo}>
<Text style={styles.eventName}>{name}</Text>
<Text style={styles.eventDate}>{`${date} | ${start} - ${end}`}</Text>
</View>
);
export default function EventTitle({ action, date, end, name, start }) {
const _generateEventTitle = () => (
<View style={styles.eventInfo}>
<Text style={styles.eventName}>{name}</Text>
<Text style={styles.eventDate}>{`${date} | ${start} - ${end}`}</Text>
</View>
);
if (action) {
return <TouchableOpacity onPress={action}>{_generateEventTitle()}</TouchableOpacity>;
}
if (action) {
return <TouchableOpacity onPress={action}>{_generateEventTitle()}</TouchableOpacity>;
}
return _generateEventTitle();
return _generateEventTitle();
}
EventTitle.propTypes = {
action: PropTypes.func,
date: PropTypes.string.isRequired,
end: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
start: PropTypes.string.isRequired,
action: PropTypes.func,
date: PropTypes.string.isRequired,
end: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
start: PropTypes.string.isRequired,
};
EventTitle.defaultProps = {
action: null,
action: null,
};

View File

@@ -1,14 +1,14 @@
import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
eventInfo: {
flexDirection: 'row',
},
eventName: {
flex: 1,
fontWeight: 'bold',
},
eventDate: {
flex: 1,
},
});
export default (styles = StyleSheet.create({
eventInfo: {
flexDirection: 'row',
},
eventName: {
flex: 1,
fontWeight: 'bold',
},
eventDate: {
flex: 1,
},
}));

View File

@@ -6,13 +6,16 @@ import { hasMultipleEvents } from '../../../selectors/events.js';
import HeaderTitle from './HeaderTitle.js';
const matchStateToProps = (state, ownProps) => {
const { routeName } = ownProps.navigation.state;
const { routeName } = ownProps.navigation.state;
return {
activeRoute: routeName,
hasActiveEvent: hasActiveEvent(state),
hasMultipleEvents: hasMultipleEvents(state),
};
return {
activeRoute: routeName,
hasActiveEvent: hasActiveEvent(state),
hasMultipleEvents: hasMultipleEvents(state),
};
};
export default connect(matchStateToProps, null)(HeaderTitle);
export default connect(
matchStateToProps,
null,
)(HeaderTitle);

View File

@@ -1,60 +1,54 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Text,
TouchableOpacity,
View,
} from 'react-native';
import { Text, TouchableOpacity, View } from 'react-native';
import EventTitle from './EventTitle/EventTitle.container.js';
import styles from './HeaderTitle.styles.js';
export default function HeaderTitle({
activeRoute,
hasActiveEvent,
hasMultipleEvents,
navigation,
activeRoute,
hasActiveEvent,
hasMultipleEvents,
navigation,
}) {
const _goBack = () => {
if (hasActiveEvent) {
navigation.goBack();
return false;
}
const _goBack = () => {
if (hasActiveEvent) {
navigation.goBack();
return false;
console.log('nowhere to go...');
};
const _showEvents = () => {
navigation.navigate('Events');
return false;
};
if (activeRoute === 'Events') {
return (
<TouchableOpacity onPress={_goBack}>
<Text style={styles.screenHeader}>Profile</Text>
</TouchableOpacity>
);
}
console.log('nowhere to go...');
};
if (activeRoute === 'Profile') {
return <Text style={styles.screenHeader}>Profile</Text>;
}
const _showEvents = () => {
navigation.navigate('Events');
return false;
};
if (activeRoute === 'Events') {
return (
<TouchableOpacity onPress={_goBack}>
<Text style={styles.screenHeader}>Profile</Text>
</TouchableOpacity>
);
}
if (activeRoute === 'Profile') {
return <Text style={styles.screenHeader}>Profile</Text>;
}
return <EventTitle action={hasMultipleEvents ? _showEvents : null} />
return <EventTitle action={hasMultipleEvents ? _showEvents : null} />;
}
HeaderTitle.propTypes = {
activeRoute: PropTypes.string.isRequired,
hasActiveEvent: PropTypes.bool,
hasMultipleEvents: PropTypes.bool.isRequired,
navigation: PropTypes.func.isRequired,
activeRoute: PropTypes.string.isRequired,
hasActiveEvent: PropTypes.bool,
hasMultipleEvents: PropTypes.bool.isRequired,
navigation: PropTypes.func.isRequired,
};
HeaderTitle.defaultProps = {
hasActiveEvent: false,
hasActiveEvent: false,
};

View File

@@ -1,15 +1,14 @@
import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
filterBar: {
backgroundColor: '#0F0',
flexDirection: 'row',
},
filter: {
flex: 2,
},
view: {
flex: 2,
},
});
export default (styles = StyleSheet.create({
filterBar: {
backgroundColor: '#0F0',
flexDirection: 'row',
},
filter: {
flex: 2,
},
view: {
flex: 2,
},
}));

View File

@@ -5,13 +5,13 @@ import { TouchableOpacity } from 'react-native';
import { Icon } from 'react-native-elements';
export default function BackIcon({ action }) {
return (
<TouchableOpacity onPress={action}>
<Icon name="ei-chevron-left" type="evilicons" size={28} />;
</TouchableOpacity>
);
return (
<TouchableOpacity onPress={action}>
<Icon name="ei-chevron-left" type="evilicons" size={28} />;
</TouchableOpacity>
);
}
BackIcon.propTypes = {
action: PropTypes.func.isRequired,
action: PropTypes.func.isRequired,
};

View File

@@ -5,20 +5,19 @@ import { TouchableOpacity } from 'react-native';
import { Icon } from 'react-native-elements';
export default function EventsIcon({ action }) {
const renderEventsIcon = () => <Icon name="ei-calendar" type="evilicons" size={28} />;
const renderEventsIcon = () => <Icon name="ei-calendar" type="evilicons" size={28} />;
if (action) {
return <TouchableOpacity onPress={action}>{renderEventsIcon()}</TouchableOpacity>;
}
if (action) {
return <TouchableOpacity onPress={action}>{renderEventsIcon()}</TouchableOpacity>;
}
return renderEventsIcon();
return renderEventsIcon();
}
EventsIcon.propTypes = {
action: PropTypes.func,
action: PropTypes.func,
};
EventsIcon.defaultProps = {
action: null,
action: null,
};

View File

@@ -5,7 +5,10 @@ import { getProfileAvatarUrl } from '../../../selectors/profile.js';
import UserProfileButton from './UserProfileButton.js';
const matchStateToProps = (state) => ({
avatarUrl: getProfileAvatarUrl(state),
avatarUrl: getProfileAvatarUrl(state),
});
export default connect(matchStateToProps, null)(UserProfileButton);
export default connect(
matchStateToProps,
null,
)(UserProfileButton);

View File

@@ -7,29 +7,28 @@ import { Icon } from 'react-native-elements';
import styles from './UserProfileButton.styles.js';
export default function UserProfileButton({ avatarUrl, navigation }) {
const _goToProfile = () => {
navigation.navigate('Profile');
return false;
};
const _goToProfile = () => {
navigation.navigate('Profile');
return false;
};
return (
<TouchableOpacity onPress={_goToProfile}>
{avatarUrl !== null ? (
<View style={styles.avatarWrap}>
<Image source={{ uri: avatarUrl }} />
</View>
) : (
<Icon name="ei-user" type="evilicons" size={28} />
)}
</TouchableOpacity>
);
return (
<TouchableOpacity onPress={_goToProfile}>
{avatarUrl !== null ? (
<View style={styles.avatarWrap}>
<Image source={{ uri: avatarUrl }} />
</View>
) : (
<Icon name="ei-user" type="evilicons" size={28} />
)}
</TouchableOpacity>
);
}
UserProfileButton.propTypes = {
avatarUrl: PropTypes.string,
avatarUrl: PropTypes.string,
};
UserProfileButton.propTypes = {
avatarUrl: null,
avatarUrl: null,
};

View File

@@ -1,13 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
StyleSheet,
TouchableOpacity,
Text,
Image,
View
} from 'react-native';
import { StyleSheet, TouchableOpacity, Text, Image, View } from 'react-native';
import GallerySwiper from 'react-native-gallery-swiper';
@@ -18,173 +12,173 @@ import { ITEM_TYPES } from '../../constants/constants.js';
import { formatPrice, getAuctionTime } from '../../library/helpers.js';
export default class AuctionListItem extends Component {
static get propTypes() {
return {
description: PropTypes.string,
donor: PropTypes.string,
end: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
images: PropTypes.arrayOf(
PropTypes.shape({
url: PropTypes.string,
}),
),
start: PropTypes.string.isRequired,
startingPrice: PropTypes.number.isRequired,
subtitle: PropTypes.string,
title: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
static get propTypes() {
return {
description: PropTypes.string,
donor: PropTypes.string,
end: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
images: PropTypes.arrayOf(
PropTypes.shape({
url: PropTypes.string,
}),
),
start: PropTypes.string.isRequired,
startingPrice: PropTypes.number.isRequired,
subtitle: PropTypes.string,
title: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
};
}
static get defaultProps() {
return {
description: null,
donor: null,
images: null,
subtitle: null,
};
}
constructor(props) {
super(props);
}
_getBidTime = () => {
const { end, start } = this.props;
return getAuctionTime({ end, start });
};
}
static get defaultProps() {
return {
description: null,
donor: null,
images: null,
subtitle: null,
_viewItemDetail = () => {
const { _id: id } = this.props.details;
this.props.navigation.navigate('Item', { id });
};
}
constructor(props) {
super(props);
}
render() {
const {
description,
donor,
end,
id,
images,
start,
startingPrice,
subtitle,
title,
type,
} = this.props;
_getBidTime = () => {
const { end, start } = this.props;
return getAuctionTime({ end, start });
}
_viewItemDetail = () => {
const { _id: id } = this.props.details;
this.props.navigation.navigate('Item', { id });
}
render() {
const {
description,
donor,
end,
id,
images,
start,
startingPrice,
subtitle,
title,
type,
} = this.props;
return(
<TouchableOpacity onPress={this._viewItemDetail}>
<View style={styles.rowContainer}>
{images !== null && images.length > 0 && (
<GallerySwiper
enableScale={false}
images={images}
initialNumToRender={2}
resizeMode="cover"
sensitiveScroll={false}
style={{height: 280}}
/>
)}
<View style={styles.rowText}>
{type === ITEM_TYPES.AUCTION && <BidStatus itemId={id} />}
<Text style={styles.title} numberOfLines={2} ellipsizeMode={'tail'}>
{title}
</Text>
<Text style={styles.subtitle} numberOfLines={1} ellipsizeMode={'tail'}>
{subtitle}
</Text>
{donor && (
<Text style={styles.donor} numberOfLines={1} ellipsizeMode={'tail'}>
{donor}
</Text>
)}
{type === ITEM_TYPES.AUCTION ? (
<AuctionPriceAndBidCount itemId={id} />
) : (
<Text style={styles.price} numberOfLines={1} ellipsizeMode={'tail'}>
{formatPrice(startingPrice)}
</Text>
)}
<Text style={styles.timeline} numberOfLines={1}>
{this._getBidTime()}
</Text>
<Text style={styles.description} numberOfLines={3} ellipsizeMode={'tail'}>
{description}
</Text>
</View>
</View>
</TouchableOpacity>
);
}
return (
<TouchableOpacity onPress={this._viewItemDetail}>
<View style={styles.rowContainer}>
{images !== null && images.length > 0 && (
<GallerySwiper
enableScale={false}
images={images}
initialNumToRender={2}
resizeMode="cover"
sensitiveScroll={false}
style={{ height: 280 }}
/>
)}
<View style={styles.rowText}>
{type === ITEM_TYPES.AUCTION && <BidStatus itemId={id} />}
<Text style={styles.title} numberOfLines={2} ellipsizeMode={'tail'}>
{title}
</Text>
<Text style={styles.subtitle} numberOfLines={1} ellipsizeMode={'tail'}>
{subtitle}
</Text>
{donor && (
<Text style={styles.donor} numberOfLines={1} ellipsizeMode={'tail'}>
{donor}
</Text>
)}
{type === ITEM_TYPES.AUCTION ? (
<AuctionPriceAndBidCount itemId={id} />
) : (
<Text style={styles.price} numberOfLines={1} ellipsizeMode={'tail'}>
{formatPrice(startingPrice)}
</Text>
)}
<Text style={styles.timeline} numberOfLines={1}>
{this._getBidTime()}
</Text>
<Text style={styles.description} numberOfLines={3} ellipsizeMode={'tail'}>
{description}
</Text>
</View>
</View>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
description: {
color: '#777',
fontSize: 14,
marginTop: 5,
paddingLeft: 10,
paddingRight: 10,
},
donor: {
color: '#777',
fontSize: 14,
marginTop: 5,
paddingLeft: 10,
},
image: {
flex: 1,
height: undefined,
width: undefined,
},
price: {
color: '#777',
fontSize: 16,
fontWeight: 'bold',
paddingLeft: 10,
paddingTop: 5,
},
rowContainer: {
backgroundColor: '#FFF',
borderRadius: 4,
flex: 1,
flexDirection: 'column',
marginRight: 10,
marginLeft: 10,
marginTop: 10,
padding: 10,
shadowColor: '#CCC',
shadowOffset: {
width: 1,
height: 1
description: {
color: '#777',
fontSize: 14,
marginTop: 5,
paddingLeft: 10,
paddingRight: 10,
},
donor: {
color: '#777',
fontSize: 14,
marginTop: 5,
paddingLeft: 10,
},
image: {
flex: 1,
height: undefined,
width: undefined,
},
price: {
color: '#777',
fontSize: 16,
fontWeight: 'bold',
paddingLeft: 10,
paddingTop: 5,
},
rowContainer: {
backgroundColor: '#FFF',
borderRadius: 4,
flex: 1,
flexDirection: 'column',
marginRight: 10,
marginLeft: 10,
marginTop: 10,
padding: 10,
shadowColor: '#CCC',
shadowOffset: {
width: 1,
height: 1,
},
shadowOpacity: 1.0,
shadowRadius: 1,
},
rowText: {
flex: 4,
flexDirection: 'column',
},
subtitle: {
color: '#777',
fontSize: 14,
marginTop: 5,
paddingLeft: 10,
},
timeline: {
color: '#777',
fontSize: 14,
marginTop: 5,
paddingLeft: 10,
paddingRight: 10,
},
title: {
color: '#777',
fontSize: 16,
fontWeight: 'bold',
paddingLeft: 10,
paddingTop: 5,
},
shadowOpacity: 1.0,
shadowRadius: 1,
},
rowText: {
flex: 4,
flexDirection: 'column',
},
subtitle: {
color: '#777',
fontSize: 14,
marginTop: 5,
paddingLeft: 10,
},
timeline: {
color: '#777',
fontSize: 14,
marginTop: 5,
paddingLeft: 10,
paddingRight: 10,
},
title: {
color: '#777',
fontSize: 16,
fontWeight: 'bold',
paddingLeft: 10,
paddingTop: 5,
},
});

View File

@@ -3,29 +3,26 @@ import PropTypes from 'prop-types';
import { formatPrice } from '../../library/helpers.js';
import {
StyleSheet,
Text,
} from 'react-native';
import { StyleSheet, Text } from 'react-native';
const AuctionPriceAndBidCount = ({ bidCount, currentPrice }) => {
return (
<Text style={styles.currentPriceAndBidCount} numberOfLines={1}>
{`${formatPrice(currentPrice)} (${bidCount} bids)`}
</Text>
);
return (
<Text style={styles.currentPriceAndBidCount} numberOfLines={1}>
{`${formatPrice(currentPrice)} (${bidCount} bids)`}
</Text>
);
};
AuctionPriceAndBidCount.propTypes = {
itemId: PropTypes.string.isRequired,
bidCount: PropTypes.number.isRequired,
currentPrice: PropTypes.number.isRequired,
itemId: PropTypes.string.isRequired,
bidCount: PropTypes.number.isRequired,
currentPrice: PropTypes.number.isRequired,
};
const styles = StyleSheet.create({
currentPriceAndBidCount: {
color: '#000',
},
currentPriceAndBidCount: {
color: '#000',
},
});
export default AuctionPriceAndBidCount;

View File

@@ -1,44 +1,41 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
StyleSheet,
Text,
} from 'react-native';
import { StyleSheet, Text } from 'react-native';
const BidStatus = ({ isBidding, isWinning }) => {
if (!isBidding) {
return null;
}
if (!isBidding) {
return null;
}
const statusBarStyle = isWinning
? [ styles.bidStatus, styes.isWinning ]
: [ styles.bidStatus, styles.isOutbid ];
const statusBarStyle = isWinning
? [styles.bidStatus, styes.isWinning]
: [styles.bidStatus, styles.isOutbid];
return (
<Text style={statusBarStyle} numberOfLines={1}>
{isWinning && `Oh no! You have been outbid!`}
{!isWinning && isBidding && `You have the winning bid! (for now...)`}
</Text>
);
return (
<Text style={statusBarStyle} numberOfLines={1}>
{isWinning && 'Oh no! You have been outbid!'}
{!isWinning && isBidding && 'You have the winning bid! (for now...)'}
</Text>
);
};
BidStatus.propTypes = {
isBidding: PropTypes.bool.isRequired,
isWinning: PropTypes.bool.isRequired,
itemId: PropTypes.string.isRequired,
isBidding: PropTypes.bool.isRequired,
isWinning: PropTypes.bool.isRequired,
itemId: PropTypes.string.isRequired,
};
const styles = StyleSheet.create({
bidStatus: {
color: '#fff',
},
isWinning: {
backgroundColor: '#F00',
},
isOutbid: {
backgroundColor: '#0F0',
},
bidStatus: {
color: '#fff',
},
isWinning: {
backgroundColor: '#F00',
},
isOutbid: {
backgroundColor: '#0F0',
},
});
export default BidStatus;

View File

@@ -1,42 +1,38 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
StyleSheet,
Text,
View,
} from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
const FilterBar = ({ changeFilterer, changeViewMode, filterMode, viewMode }) => (
<View style={styles.filterBar}>
<Text style={styles.filter}>Filter</Text>
<Text style={styles.view}>View</Text>
<Text style={styles.filter}>Filter</Text>
<Text style={styles.view}>View</Text>
</View>
);
FilterBar.propTypes = {
changeFilterer: PropTypes.func.isRequired,
changeViewMode: PropTypes.func.isRequired,
filterMode: PropTypes.string,
viewMode: PropTypes.string,
changeFilterer: PropTypes.func.isRequired,
changeViewMode: PropTypes.func.isRequired,
filterMode: PropTypes.string,
viewMode: PropTypes.string,
};
FilterBar.defaultProps = {
filterMode: null,
viewMode: null,
filterMode: null,
viewMode: null,
};
const styles = StyleSheet.create({
filterBar: {
backgroundColor: '#0F0',
flexDirection: 'row',
},
filter: {
flex: 2,
},
view: {
flex: 2,
},
filterBar: {
backgroundColor: '#0F0',
flexDirection: 'row',
},
filter: {
flex: 2,
},
view: {
flex: 2,
},
});
export default FilterBar;

View File

@@ -1,84 +1,79 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
StyleSheet,
TouchableOpacity,
Text,
Image,
View
} from 'react-native';
import { StyleSheet, TouchableOpacity, Text, Image, View } from 'react-native';
export default class EventListItem extends Component {
static get propTypes() {
return {
description: PropTypes.string.isRequired,
endTime: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
images: PropTypes.arrayOf(
PropTypes.shape({
url: PropTypes.string,
}),
),
isTicketed: PropTypes.bool,
postCount: PropTypes.number,
setActiveEvent: PropTypes.func.isRequired,
showFrom: PropTypes.string.isRequired,
showUntil: PropTypes.string.isRequired,
startTime: PropTypes.string.isRequired,
tagline: PropTypes.string,
title: PropTypes.string.isRequired,
static get propTypes() {
return {
end: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
images: PropTypes.arrayOf(
PropTypes.shape({
url: PropTypes.string,
}),
),
setActiveEvent: PropTypes.func.isRequired,
showFrom: PropTypes.string.isRequired,
showUntil: PropTypes.string.isRequired,
start: PropTypes.string.isRequired,
tagline: PropTypes.string,
name: PropTypes.string.isRequired,
};
}
static get defaultProps() {
return {
images: null,
isTicketed: false,
postCount: 0,
tagline: null,
};
}
constructor(props) {
super(props);
}
_viewEventDetail = () => {
this.props.setActiveEvent(this.props.id);
this.props.navigation.navigate('Event');
};
}
static get defaultProps() {
return {
images: null,
isTicketed: false,
postCount: 0,
tagline: null,
};
}
render() {
const { date, description, end, name, start } = this.props;
constructor(props) {
super(props);
}
_viewEventDetail = () => {
const { id } = this.props.details;
this.props.setActiveEvent(id);
this.props.navigation.navigate('Event');
}
render() {
const {
} = this.props;
return(
<TouchableOpacity onPress={this._viewEventDetail}>
<View style={styles.rowContainer}>
</View>
</TouchableOpacity>
);
}
return (
<TouchableOpacity onPress={this._viewEventDetail}>
<View style={styles.rowContainer}>
<Text>{name}</Text>
<Text>{date}</Text>
<Text>
{start} - {end}
</Text>
<Text>{description}</Text>
</View>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
rowContainer: {
backgroundColor: '#FFF',
borderRadius: 4,
flex: 1,
flexDirection: 'column',
marginRight: 10,
marginLeft: 10,
marginTop: 10,
padding: 10,
shadowColor: '#CCC',
shadowOffset: {
width: 1,
height: 1
rowContainer: {
backgroundColor: '#FFF',
borderRadius: 4,
flex: 1,
flexDirection: 'column',
marginRight: 10,
marginLeft: 10,
marginTop: 10,
padding: 10,
shadowColor: '#CCC',
shadowOffset: {
width: 1,
height: 1,
},
shadowOpacity: 1.0,
shadowRadius: 1,
},
shadowOpacity: 1.0,
shadowRadius: 1,
},
});

View File

@@ -1,19 +1,22 @@
import { connect } from 'react-redux';
import {
facebookLoginSuccess,
logout,
registrationServiceError,
userCanceledRegistration,
facebookLoginSuccess,
logout,
registrationServiceError,
userCanceledRegistration,
} from '../../actions/profile.js';
import FacebookLogin from './FacebookLogin.js';
const mapDispatchToProps = (dispatch) => ({
doCancelAction: () => dispatch(userCanceledRegistration()),
doErrorAction: (error) => dispatch(registrationServiceError(error)),
doLogoutAction: () => dispatch(logout()),
doSuccessAction: (result) => dispatch(facebookLoginSuccess(result)),
doCancelAction: () => dispatch(userCanceledRegistration()),
doErrorAction: (error) => dispatch(registrationServiceError(error)),
doLogoutAction: () => dispatch(logout()),
doSuccessAction: (result) => dispatch(facebookLoginSuccess(result)),
});
export default connect(null, mapDispatchToProps)(FacebookLogin);
export default connect(
null,
mapDispatchToProps,
)(FacebookLogin);

View File

@@ -6,36 +6,33 @@ import { LoginButton } from 'react-native-fbsdk';
import { PERMISSIONS } from '../../constants/constants.js';
export default function FacebookLogin({
doCancelAction,
doErrorAction,
doLogoutAction,
doSuccessAction,
doCancelAction,
doErrorAction,
doLogoutAction,
doSuccessAction,
}) {
return (
<View>
<LoginButton
publishPermissions={PERMISSIONS.FACEBOOK}
onLoginFinished={
(error, result) => {
if (error) {
doErrorAction(error);
} else if (result.isCancelled) {
doCancelAction();
} else {
doSuccessAction(result);
}
}
}
onLogoutFinished={doLogoutAction}
/>
</View>
);
return (
<View>
<LoginButton
publishPermissions={PERMISSIONS.FACEBOOK}
onLoginFinished={(error, result) => {
if (error) {
doErrorAction(error);
} else if (result.isCancelled) {
doCancelAction();
} else {
doSuccessAction(result);
}
}}
onLogoutFinished={doLogoutAction}
/>
</View>
);
}
FacebookLogin.propTypes = {
doCancelAction: PropTypes.func.isRequired,
doErrorAction: PropTypes.func.isRequired,
doLogoutAction: PropTypes.func.isRequired,
doSuccessAction: PropTypes.func.isRequired,
doCancelAction: PropTypes.func.isRequired,
doErrorAction: PropTypes.func.isRequired,
doLogoutAction: PropTypes.func.isRequired,
doSuccessAction: PropTypes.func.isRequired,
};

View File

@@ -5,7 +5,10 @@ import { login } from '../../actions/profile.js';
import LocalLogin from './LocalLogin.js';
const mapDispatchToProps = (dispatch) => ({
doLoginAction: (username, password) => dispatch(login(username, password)),
doLoginAction: (username, password) => dispatch(login(username, password)),
});
export default connect(null, mapDispatchToProps)(LocalLogin);
export default connect(
null,
mapDispatchToProps,
)(LocalLogin);

View File

@@ -54,5 +54,5 @@ export default function LocalLogin({ doLoginAction }) {
}
LocalLogin.propTypes = {
doLoginAction: PropTypes.func.isRequired,
doLoginAction: PropTypes.func.isRequired,
};