Merge branch 'master' of honey.fitz.guru:eventment-app
# Conflicts: # app/components/Login/LocalLogin.js # app/screens/Register.js
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -54,5 +54,5 @@ export default function LocalLogin({ doLoginAction }) {
|
||||
}
|
||||
|
||||
LocalLogin.propTypes = {
|
||||
doLoginAction: PropTypes.func.isRequired,
|
||||
doLoginAction: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user