-More!
This commit is contained in:
@@ -1,8 +1,23 @@
|
||||
import { blockUI, unblockUI } from './index.js';
|
||||
|
||||
import {
|
||||
BID_FAILURE,
|
||||
BID_SUCCESS,
|
||||
PLACE_BID,
|
||||
SET_AUCTION_FILTER,
|
||||
SET_AUCTION_VIEW_MODE,
|
||||
} from '../constants/actionTypes.js';
|
||||
|
||||
const placeBidFailure = (bid, dispatch) => {
|
||||
dispatch({ type: BID_FAILURE, bid });
|
||||
dispatch(unblockUI);
|
||||
};
|
||||
|
||||
const placeBidSuccess = (bid, dispatch) => {
|
||||
dispatch({ type: BID_SUCCESS, bid });
|
||||
dispatch(unblockUI);
|
||||
};
|
||||
|
||||
export const changeFilterMode = (payload) => ({
|
||||
type: SET_AUCTION_FILTER,
|
||||
payload,
|
||||
@@ -13,3 +28,25 @@ export const changeViewMode = (payload) => ({
|
||||
payload,
|
||||
});
|
||||
|
||||
export const placeBid = (payload) => ({
|
||||
type: PLACE_BID,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const postBid = () => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const activeEvent = state.get('activeEvent');
|
||||
|
||||
let apiUrl = getEndpointUrl(API_ENDPOINTS.GET_ITEMS);
|
||||
apiUrl = apiUrl.replace(/:event_id$/, '');
|
||||
if (activeEvent) {
|
||||
apiUrl = `${apiUrl}${activeEvent}`;
|
||||
}
|
||||
|
||||
dispatch(blockUI());
|
||||
|
||||
fetch(apiUrl)
|
||||
.then(response => response.json())
|
||||
.then(payload => itemsLoadSuccess(payload, dispatch))
|
||||
.catch(err => console.error('[actions::getItems]', err));
|
||||
};
|
||||
|
||||
@@ -19,6 +19,11 @@ const eventsLoadSuccess = (events, dispatch) => {
|
||||
dispatch(unblockUI);
|
||||
};
|
||||
|
||||
export const setActiveEvent = (eventId) => ({
|
||||
type: SET_ACTIVE_EVENT,
|
||||
payload: eventId,
|
||||
});
|
||||
|
||||
export const fetchEvents = () => (dispatch) => {
|
||||
dispatch(blockUI());
|
||||
fetch(getEndpointUr(API_ENDPOINTS.GET_EVENTS))
|
||||
|
||||
33
app/actions/profile.js
Normal file
33
app/actions/profile.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { List } from 'immutable';
|
||||
|
||||
import { getEndpointUrl } from '../api/index.js';
|
||||
|
||||
import {
|
||||
EVENTS_LOADED,
|
||||
GET_EVENTS,
|
||||
} from '../constants/actionTypes.js';
|
||||
|
||||
import { blockUI, unblockUI } from './index.js';
|
||||
import { API_ENDPOINTS } from '../constants/constants.js';
|
||||
|
||||
import Event from '../domain/Event.js';
|
||||
|
||||
|
||||
const eventsLoadSuccess = (events, dispatch) => {
|
||||
const payload = List(events).map((i) => Event.fromJS(i));
|
||||
dispatch({ type: EVENTS_LOADED, payload });
|
||||
dispatch(unblockUI);
|
||||
};
|
||||
|
||||
export const setActiveEvent = (eventId) => ({
|
||||
type: SET_ACTIVE_EVENT,
|
||||
payload: eventId,
|
||||
});
|
||||
|
||||
export const fetchEvents = () => (dispatch) => {
|
||||
dispatch(blockUI());
|
||||
fetch(getEndpointUr(API_ENDPOINTS.GET_EVENTS))
|
||||
.then(response => response.json())
|
||||
.then(payload => eventsLoadSuccess(payload, dispatch))
|
||||
.catch(err => console.error('[actions::getEvents]', err));
|
||||
};
|
||||
23
app/components/AppHeader/AppHeader.js
Normal file
23
app/components/AppHeader/AppHeader.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Header } from 'react-native-elements';
|
||||
|
||||
import HeaderTitle from './HeaderTitle.container.js';
|
||||
import HeaderContentLeft from './HeaderContentLeft.container.js';
|
||||
import HeaderContentRight from './HeaderContentRight.container.js';
|
||||
|
||||
import styles from './AppHeader.styles.js';
|
||||
|
||||
export default function AppHeader({ navigation }) (
|
||||
<Header
|
||||
placement="left"
|
||||
leftComponent={<HeaderContentRight navigation={navigation} />}
|
||||
centerComponent={<HeaderTitle navigation={navigation} />}
|
||||
rightComponent={<HeaderContentLeft navigation={navigation} />}
|
||||
/>
|
||||
)
|
||||
|
||||
AppHeader.propTypes = {
|
||||
navigation: PropTypes.func.isRequired,
|
||||
};
|
||||
16
app/components/AppHeader/HeaderContentLeft.container.js
Normal file
16
app/components/AppHeader/HeaderContentLeft.container.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { hasMultipleEvents } from '../selectors/events.js';
|
||||
|
||||
import HeaderContentLeft from './HeaderContentLeft.js';
|
||||
|
||||
const matchStateToProps = (state, ownProps) => {
|
||||
const { routeName } = ownProps.navigation.state;
|
||||
|
||||
return {
|
||||
activeRoute: routeName,
|
||||
hasMultipleEvents: hasMultipleEvents(state),
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(matchStateToProps, null)(HeaderContentLeft);
|
||||
53
app/components/AppHeader/HeaderContentLeft.js
Normal file
53
app/components/AppHeader/HeaderContentLeft.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
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,
|
||||
}) {
|
||||
|
||||
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} />;
|
||||
}
|
||||
|
||||
if (activeRoute === 'Profile') {
|
||||
return <BackIcon action={_goBack} />;
|
||||
}
|
||||
|
||||
return <EventsIcon action={hasMultipleEvents ? _showEvents : null} />
|
||||
}
|
||||
|
||||
HeaderContentLeft.propTypes = {
|
||||
activeRoute: PropTypes.string.isRequired,
|
||||
hasActiveEvent: PropTypes.bool,
|
||||
navigation: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
HeaderContentLeft.defaultProps = {
|
||||
hasActiveEvent: false,
|
||||
};
|
||||
12
app/components/AppHeader/HeaderContentRight.container.js
Normal file
12
app/components/AppHeader/HeaderContentRight.container.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getProfileAvatarUrl } from '../selectors/profile.js';
|
||||
|
||||
import HeaderContentRight from './HeaderContentRight.js';
|
||||
|
||||
const matchStateToProps = (state, ownProps) => ({
|
||||
avatarUrl: getProfileAvatarUrl(state),
|
||||
hideUserProfileButton: ownProps.navigation.state.routeName === 'Profile',
|
||||
});
|
||||
|
||||
export default connect(matchStateToProps, null)(HeaderContentRight);
|
||||
17
app/components/AppHeader/HeaderContentRight.js
Normal file
17
app/components/AppHeader/HeaderContentRight.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import UserProfileButton from './UserProfileButton/UserProfileButton.container.js';
|
||||
|
||||
export default function HeaderContentRight({ hideUserProfileButton, navigation }) {
|
||||
|
||||
if (hideUserProfileButton) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <UserProfileButton />;
|
||||
}
|
||||
|
||||
HeaderContentRight.propTypes = {
|
||||
hideUserProfileButton: PropTypes.bool.isRequired,
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getActiveEvent, getDefaultEvent } from '../selectors/events.js';
|
||||
|
||||
import EventTitle from './EventTitle.js';
|
||||
|
||||
const matchStateToProps = (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'),
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(matchStateToProps, null)(EventTitle);
|
||||
@@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
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>
|
||||
);
|
||||
|
||||
if (action) {
|
||||
return <TouchableOpacity onPress={action}>{_generateEventTitle()}</TouchableOpacity>;
|
||||
}
|
||||
|
||||
return _generateEventTitle();
|
||||
}
|
||||
|
||||
EventTitle.propTypes = {
|
||||
action: PropTypes.func,
|
||||
date: PropTypes.string.isRequired,
|
||||
end: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
start: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
EventTitle.defaultProps = {
|
||||
action: null,
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export default const styles = StyleSheet.create({
|
||||
eventInfo: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
eventName: {
|
||||
flex: 1,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
eventDate: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { hasActiveEvent } from '../selectors/activeEvent.js';
|
||||
import { hasMultipleEvents } from '../selectors/events.js';
|
||||
|
||||
import HeaderTitle from './HeaderTitle.js';
|
||||
|
||||
const matchStateToProps = (state, ownProps) => {
|
||||
const { routeName } = ownProps.navigation.state;
|
||||
|
||||
return {
|
||||
activeRoute: routeName,
|
||||
hasActiveEvent: hasActiveEvent(state),
|
||||
hasMultipleEvents: hasMultipleEvents(state),
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(matchStateToProps, null)(HeaderTitle);
|
||||
60
app/components/AppHeader/HeaderTitle/HeaderTitle.js
Normal file
60
app/components/AppHeader/HeaderTitle/HeaderTitle.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
|
||||
import EventTitle from './EventTitle/EventTitle.container.js';
|
||||
|
||||
import styles from './TitleBar.styles.js';
|
||||
|
||||
export default function HeaderTitle({
|
||||
activeRoute,
|
||||
hasActiveEvent,
|
||||
hasMultipleEvents,
|
||||
navigation,
|
||||
}) {
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
||||
if (activeRoute === 'Profile') {
|
||||
return <Text style={styles.screenHeader}>Profile</Text>;
|
||||
}
|
||||
|
||||
return <EventTitle action={hasMultipleEvents ? _showEvents : null} />
|
||||
}
|
||||
|
||||
HeaderTitle.propTypes = {
|
||||
activeRoute: PropTypes.string.isRequired,
|
||||
hasActiveEvent: PropTypes.bool,
|
||||
hasMultipleEvents: PropTypes.bool.isRequired,
|
||||
navigation: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
HeaderTitle.defaultProps = {
|
||||
hasActiveEvent: false,
|
||||
};
|
||||
15
app/components/AppHeader/HeaderTitle/HeaderTitle.styles.js
Normal file
15
app/components/AppHeader/HeaderTitle/HeaderTitle.styles.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export default const styles = StyleSheet.create({
|
||||
filterBar: {
|
||||
backgroundColor: '#0F0',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
filter: {
|
||||
flex: 2,
|
||||
},
|
||||
view: {
|
||||
flex: 2,
|
||||
},
|
||||
});
|
||||
|
||||
15
app/components/AppHeader/IconButtons/BackIcon.js
Normal file
15
app/components/AppHeader/IconButtons/BackIcon.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { TouchableOpacity } from 'react-native';
|
||||
import { Icon } from 'react-native-elements';
|
||||
|
||||
export default function BackIcon({ action }) (
|
||||
<TouchableOpacity onPress={action}>
|
||||
<Icon name="ei-chevron-left" type="evilicons" size={28} />;
|
||||
</TouchableOpacity>
|
||||
)
|
||||
|
||||
BackIcon.propTypes = {
|
||||
action: PropTypes.func.isRequired,
|
||||
};
|
||||
24
app/components/AppHeader/IconButtons/EventsIcon.js
Normal file
24
app/components/AppHeader/IconButtons/EventsIcon.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
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} />;
|
||||
|
||||
if (action) {
|
||||
return <TouchableOpacity onPress={action}>{renderEventsIcon()}</TouchableOpacity>;
|
||||
}
|
||||
|
||||
return renderEventsIcon();
|
||||
}
|
||||
|
||||
EventsIcon.propTypes = {
|
||||
action: PropTypes.func,
|
||||
};
|
||||
|
||||
EventsIcon.defaultProps = {
|
||||
action: null,
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getProfileAvatarUrl } from '../selectors/profile.js';
|
||||
|
||||
import HeaderContentRight from './HeaderContentRight.js';
|
||||
|
||||
const matchStateToProps = (state) => ({
|
||||
avatarUrl: getProfileAvatarUrl(state),
|
||||
});
|
||||
|
||||
export default connect(matchStateToProps, null)(HeaderContentRight);
|
||||
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Image, TouchableOpacity, View } from 'react-native';
|
||||
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;
|
||||
};
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={_goToProfile}>
|
||||
{avatarUrl !== null ? (
|
||||
<View style={styles.avatarWrap}>
|
||||
<Image source={{ uri: avatarUrl }} />
|
||||
</View>
|
||||
) : (
|
||||
<Icon name="ei-user" type="evilicons" size={28} />;
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
HeaderContentRight.propTypes = {
|
||||
avatarUrl: PropTypes.string,
|
||||
};
|
||||
|
||||
HeaderContentRight.propTypes = {
|
||||
avatarUrl: null,
|
||||
};
|
||||
@@ -17,7 +17,7 @@ import BidStatus from '../../containers/Auction/BidStatus.js';
|
||||
import { ITEM_TYPES } from '../../constants/constants.js';
|
||||
import { formatPrice, getAuctionTime } from '../../library/helpers.js';
|
||||
|
||||
export default class ItemRow extends Component {
|
||||
export default class AuctionListItem extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
description: PropTypes.string,
|
||||
84
app/components/Events/EventListItem.js
Normal file
84
app/components/Events/EventListItem.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
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 defaultProps() {
|
||||
return {
|
||||
images: null,
|
||||
isTicketed: false,
|
||||
postCount: 0,
|
||||
tagline: null,
|
||||
};
|
||||
}
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
},
|
||||
shadowOpacity: 1.0,
|
||||
shadowRadius: 1,
|
||||
},
|
||||
});
|
||||
@@ -12,6 +12,8 @@ export const AUCTIONS_UPDATED = 'AUCTIONS_UPDATED';
|
||||
export const SET_TICKET_PURCHASE_FLOW = 'SET_TICKET_PURCHASE_FLOW';
|
||||
|
||||
export const PLACE_BID = 'PLACE_BID';
|
||||
export const BID_FAILURE = 'BID_FAILURE';
|
||||
export const BID_SUCCESS = 'BID_SUCCESS';
|
||||
|
||||
export const DO_LOGIN = 'DO_LOGIN';
|
||||
export const DO_LOGOUT = 'DO_LOOUT';
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
export const matchStateToProps = (state, ownProps) => {
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { placeBid } from '../../actions/auction.js';
|
||||
|
||||
import AuctionListItem from '../../components/Auction/AuctionListItem.js';
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const { item } = ownProps;
|
||||
|
||||
return {
|
||||
@@ -14,3 +20,10 @@ export const matchStateToProps = (state, ownProps) => {
|
||||
type: item.get('type'),
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
placeBid: (data) => dispatch(placeBid(data)),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(AuctionListItem);
|
||||
|
||||
29
app/containers/Events/EventListItem.js
Normal file
29
app/containers/Events/EventListItem.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { setActiveEvent } from '../../actions/events.js';
|
||||
import EventListItem from '../../components/Events/EventListItem.js';
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const { event } = ownProps;
|
||||
|
||||
return {
|
||||
description: event.get('description'),
|
||||
endTime: event.get('endTime'),
|
||||
id: event.get('id'),
|
||||
images: event.get('images').toArray(),
|
||||
isTicketed: event.get('isTicketed'),
|
||||
postCount: event.get('posts').size,
|
||||
showFrom: event.get('showFrom'),
|
||||
showUntil: event.get('showUntil'),
|
||||
startTime: event.get('startTime'),
|
||||
tagline: event.get('tagline'),
|
||||
title: event.get('title'),
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setActiveEvent: (eventId) => dispatch(setActiveEvent(eventId)),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(AuctionListItem);
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { mapStateToProps } from './Item.js';
|
||||
import ItemRow from '../../components/Item/List.js';
|
||||
|
||||
export default connect(mapStateToProps, null)(ItemRow);
|
||||
@@ -27,6 +27,11 @@ export default class Profile extends Record({
|
||||
get fullName() {
|
||||
return `${this.firstName} ${this.lastName}`;
|
||||
}
|
||||
|
||||
get isRegisteredAccount() {
|
||||
return this.hasLinkedApple ||
|
||||
this.hasLinkedFacebook || this.hasLinkedGoogle || this.hasLocalAccount;
|
||||
}
|
||||
}
|
||||
|
||||
Profile.fromJS = (data = {}) => {
|
||||
|
||||
@@ -3,16 +3,18 @@ import { Dimensions, Platform } from 'react-native';
|
||||
import { createBottomTabNavigator, createStackNavigator } from 'react-navigation';
|
||||
import { Icon } from 'react-native-elements';
|
||||
|
||||
import Auction from './containers/Auction.js';
|
||||
import AppHeader from './Components/AppHeader/AppHeader.js';
|
||||
|
||||
import Auction from './screen/Auction.container.js';
|
||||
import Checkout from './screens/Checkout.js';
|
||||
import Event from './screens/Event.js';
|
||||
import Events from './screens/Events.js';
|
||||
import Event from './screens/Event.container.js';
|
||||
import Events from './screens/Events.container.js';
|
||||
import ImageDetail from './screens/ImageDetail.js';
|
||||
import Item from './screens/Item.js';
|
||||
import Marketplace from './screens/Marketplace.js';
|
||||
import Profile from './screens/Profile.js';
|
||||
import Profile from './screens/Profile.container.js';
|
||||
|
||||
let screen = Dimensions.get('window');
|
||||
//let screen = Dimensions.get('window');
|
||||
|
||||
export const Tabs = createBottomTabNavigator({
|
||||
'Event': {
|
||||
@@ -49,7 +51,7 @@ export const AuctionStack = createStackNavigator({
|
||||
Auction: {
|
||||
screen: Auction,
|
||||
navigationOptions: ({navigation}) => ({
|
||||
header: null,
|
||||
header: <AppHeader navigation={navigation} />,
|
||||
}),
|
||||
},
|
||||
Item: {
|
||||
@@ -74,7 +76,7 @@ export const BazaarStack = createStackNavigator({
|
||||
Bazaar: {
|
||||
screen: Marketplace,
|
||||
navigationOptions: ({navigation}) => ({
|
||||
header: null,
|
||||
header: <AppHeader navigation={navigation} />,
|
||||
}),
|
||||
},
|
||||
Item: {
|
||||
@@ -107,7 +109,7 @@ export const EventsStack = createStackNavigator({
|
||||
Events: {
|
||||
screen: Events,
|
||||
navigationOptions: ({ navigation }) => ({
|
||||
header: null,
|
||||
header: <AppHeader navigation={navigation} />,
|
||||
tabBarVisible: false,
|
||||
gesturesEnabled: false
|
||||
}),
|
||||
@@ -129,6 +131,12 @@ export const createRootNavigator = () => {
|
||||
gesturesEnabled: false
|
||||
}
|
||||
},
|
||||
EventsStack: {
|
||||
screen: EventsStack,
|
||||
navigationOptions: {
|
||||
gesturesEnabled: false
|
||||
}
|
||||
},
|
||||
Tabs: {
|
||||
screen: Tabs,
|
||||
navigationOptions: {
|
||||
@@ -137,7 +145,6 @@ export const createRootNavigator = () => {
|
||||
}
|
||||
},
|
||||
{
|
||||
headerMode: "none",
|
||||
mode: "modal"
|
||||
}
|
||||
);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { fetchAuctionStatus } from '../actions/auctionStatus.js';
|
||||
|
||||
import { getAuctionItemsAsList } from '../selectors/items.js';
|
||||
|
||||
import Auction from '../screens/Auction.js';
|
||||
import Auction from './Auction.js';
|
||||
|
||||
const matchStateToProps = (state) => {
|
||||
const items = getAuctionItemsAsList(state);
|
||||
@@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
FlatList,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
@@ -12,12 +11,15 @@ import {
|
||||
import { SORT_MODES, AUCTION_VIEW_MODES } from '../constants/constants.js';
|
||||
|
||||
import FilterBar from '../components/Auction/FilterBar.js';
|
||||
import ListItem from '../containers/Item/List.js';
|
||||
import AuctionListItem from '../containers/Auction/AuctionListItem.js';
|
||||
|
||||
import styles from './Auction.styles.js';
|
||||
|
||||
export default class Auction extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
changeFilter: PropTypes.func,
|
||||
changeViewMode: PropTypes.func.isRequired,
|
||||
fetchItems: PropTypes.func.isRequired,
|
||||
fetchStatus: PropTypes.func.isRequired,
|
||||
items: PropTypes.oneOfType([
|
||||
@@ -55,13 +57,9 @@ export default class Auction extends Component {
|
||||
this.props.changeFilter('auction', filter);
|
||||
}
|
||||
|
||||
changeViewMode(mode) {
|
||||
this.setState({ view: mode });
|
||||
}
|
||||
|
||||
_keyExtractor = (item, index) => `${item._id}_${index}`;
|
||||
|
||||
_renderItem = ({ item }) => <ListItem item={item} />;
|
||||
_renderAuctionListItem = ({ item }) => <AuctionListItem item={item} />;
|
||||
|
||||
render() {
|
||||
const { items } = this.props;
|
||||
@@ -71,13 +69,12 @@ export default class Auction extends Component {
|
||||
<View style={styles.container}>
|
||||
<FilterBar
|
||||
changeFilterer={this.changeFilter}
|
||||
changeViewMode={this.changeViewMode}
|
||||
/>
|
||||
{items.size > 0 && (
|
||||
<FlatList
|
||||
data={items}
|
||||
keyExtractor={this._keyExtractor}
|
||||
renderItem={this._renderItem(view)}
|
||||
renderItem={this._renderAuctionListItem}
|
||||
contentContainerStyle={styles.itemListContentContainer}
|
||||
style={styles.itemList}
|
||||
/>
|
||||
@@ -86,19 +83,3 @@ export default class Auction extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
itemList: {
|
||||
width: '100%',
|
||||
},
|
||||
itemListContentContainer: {
|
||||
alignItems: 'stretch',
|
||||
justifyContent: 'flex-start',
|
||||
},
|
||||
});
|
||||
|
||||
17
app/screens/Auction.styles.js
Normal file
17
app/screens/Auction.styles.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
itemList: {
|
||||
width: '100%',
|
||||
},
|
||||
itemListContentContainer: {
|
||||
alignItems: 'stretch',
|
||||
justifyContent: 'flex-start',
|
||||
},
|
||||
});
|
||||
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
|
||||
import { fetchEvent } from '../actions/events.js';
|
||||
import { getEventById } from '../selectors/events.js';
|
||||
|
||||
import Event from '../screens/Event.js';
|
||||
import Event from './Event.js';
|
||||
|
||||
const matchStateToProps = (state) => {
|
||||
const eventId = state.get('activeEvent');
|
||||
@@ -1,21 +1,80 @@
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { Text, View } from 'react-native';
|
||||
|
||||
import styles from './Event.styles.js';
|
||||
|
||||
export default class Event extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
description: PropTypes.string.isRequired,
|
||||
endTime: PropTypes.string.isRequired,
|
||||
fetchEvent: PropTypes.func.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
images: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
url: PropTypes.string,
|
||||
}),
|
||||
),
|
||||
isTicketed: PropTypes.bool,
|
||||
posts: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
author: PropTypes.string.isRequired,
|
||||
content: PropTypes.string.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
isPublic: PropTypes.bool,
|
||||
scheduledPost: PropTypes.bool,
|
||||
sendNotification: PropTypes.bool,
|
||||
timestamp: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
}),
|
||||
),
|
||||
requireLoginToSeeAuction: PropTypes.bool.isRequired,
|
||||
showFrom: PropTypes.string.isRequired,
|
||||
showUntil: PropTypes.string.isRequired,
|
||||
startTime: PropTypes.string.isRequired,
|
||||
tagline: PropTypes.string,
|
||||
ticketClasses: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
event,
|
||||
}),
|
||||
)
|
||||
title: PropTypes.string.isRequired,
|
||||
url: PropTypes.string,
|
||||
};
|
||||
}
|
||||
|
||||
static get defaultProps() {
|
||||
return {
|
||||
images: null,
|
||||
isTicketed: false,
|
||||
posts: null,
|
||||
requireLoginToSeeAuction: false,
|
||||
tagline: null,
|
||||
ticketClasses: null,
|
||||
url: null,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
description,
|
||||
endTime,
|
||||
images,
|
||||
isTicketed,
|
||||
requireLoginToSeeAuction,
|
||||
showFrom,
|
||||
showUntil,
|
||||
startTime,
|
||||
tagline,
|
||||
ticketClasses,
|
||||
title,
|
||||
url,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>
|
||||
@@ -25,100 +84,3 @@ export default class Event extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
margin: 10,
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const event = {
|
||||
isTicketed: true,
|
||||
requireLoginToSeeAuction: false,
|
||||
_id: "5d1f0a9289511160ddd681f4",
|
||||
description: "Cumque rerum nihil sit libero in.. Excepturi molestiae dicta.. Ratione perspiciatis similique et sed corrupti excepturi ut consequatur in.. Impedit voluptate deleniti suscipit vero tenetur.. Aut ut saepe nesciunt voluptas quod nam laudantium unde.",
|
||||
endTime: "2020-01-02T05:39:39.957Z",
|
||||
images: [
|
||||
{
|
||||
_id: "5d1f0a9289511160ddd681f7",
|
||||
url: "https://lorempixel.com/640/480/cats?37458"
|
||||
},
|
||||
{
|
||||
_id: "5d1f0a9289511160ddd681f6",
|
||||
url: "https://lorempixel.com/640/480/cats?80772"
|
||||
},
|
||||
{
|
||||
_id: "5d1f0a9289511160ddd681f5",
|
||||
url: "https://lorempixel.com/640/480/cats?2451"
|
||||
}
|
||||
],
|
||||
posts: [
|
||||
{
|
||||
isPublic: true,
|
||||
scheduledPost: false,
|
||||
_id: "5d1f0a9289511160ddd681fb",
|
||||
author: "Dandre Leuschke",
|
||||
title: "Facere a atque.",
|
||||
content: "Reprehenderit minus ut. Quibusdam reiciendis rerum fugit est quis. Omnis architecto magni. Libero et nihil excepturi facere doloribus doloremque in error deleniti. Modi et id sint exercitationem esse tenetur iure. Occaecati aliquid maxime ratione asperiores repudiandae.\n \rQuia ipsam quia fuga pariatur odit sunt. Sed dicta earum officiis quo quo. Sunt maiores itaque ipsum eum. Quia repudiandae et. Asperiores et est. Et modi minus cupiditate voluptas quia maxime delectus voluptatum.\n \rDignissimos numquam non nulla aut ea a quis. Et consequuntur porro ut dolorem iure est voluptas. Autem ullam mollitia perferendis mollitia sequi voluptatem numquam voluptatum.\n \rIllum magnam consequatur iste ut libero tenetur aut eos quibusdam. Aut molestiae ullam maiores. Sapiente est sed.",
|
||||
sendNotification: null,
|
||||
timestamp: "2019-06-26T01:41:43.197Z"
|
||||
},
|
||||
{
|
||||
isPublic: false,
|
||||
scheduledPost: false,
|
||||
_id: "5d1f0a9289511160ddd681fa",
|
||||
author: "Kari Ullrich",
|
||||
title: "Iure ea est.",
|
||||
content: "Molestiae magni nisi. Sit est sed aliquid corrupti perferendis natus. Est dolore totam. Quis excepturi id id ipsa. Accusantium aliquam facere laboriosam quo mollitia voluptatum.\n \rEum nulla ratione. Quia fuga ipsum fuga est temporibus eligendi aut. Aperiam alias architecto molestias aut beatae ullam harum. Magni in numquam dolores.\n \rIpsum quod itaque vero iste. Architecto vero ut quia. Voluptas modi provident et consequatur consequatur ex quia.",
|
||||
sendNotification: null,
|
||||
timestamp: "2019-06-22T19:29:40.080Z"
|
||||
},
|
||||
{
|
||||
isPublic: false,
|
||||
scheduledPost: true,
|
||||
_id: "5d1f0a9289511160ddd681f9",
|
||||
author: "Maida Bednar",
|
||||
title: "Et dignissimos rem officiis non voluptas ea totam atque.",
|
||||
content: "Totam dolorum quia dolor. Tempore molestiae error eos qui rerum ipsa nihil voluptas est. Aut et adipisci voluptatibus. Consectetur vel sit est voluptatum fuga qui minima sit recusandae.\n \rProvident dolorem ut. In rerum hic porro odio illo praesentium qui quis animi. Cupiditate est tenetur magnam commodi. Id est temporibus itaque corporis voluptatum omnis repellat eius. Deserunt tempora cum facilis. Nesciunt blanditiis voluptas mollitia.\n \rVoluptate vero omnis non nesciunt officia. Ipsa perferendis soluta. Sed unde labore autem quae amet deleniti consequatur. Molestias ducimus iusto a ipsa. Repellat vero accusamus impedit quo. Molestias nam inventore aut quaerat error odio eius enim velit.",
|
||||
sendNotification: "2019-08-16T20:54:01.358Z",
|
||||
timestamp: "2019-06-27T23:24:40.677Z"
|
||||
},
|
||||
{
|
||||
isPublic: true,
|
||||
scheduledPost: false,
|
||||
_id: "5d1f0a9289511160ddd681f8",
|
||||
author: "Emory Ortiz II",
|
||||
title: "Ut doloribus quas impedit velit nostrum nemo facere nam.",
|
||||
content: "Et et ab sapiente voluptatibus. Modi aperiam ad mollitia sunt minima architecto. Soluta aliquid vero. Est non eum esse. Numquam rerum quod. Itaque quasi numquam dolor impedit ut sit.\n \rQuo sapiente optio ea labore non dolor. Et nemo recusandae ea. Laboriosam magnam commodi excepturi quis soluta et. Molestias pariatur et ullam nesciunt ullam.\n \rCulpa enim vitae modi non totam sit eius beatae. Quia autem atque veniam et at neque. Reprehenderit possimus esse a qui nobis et laborum rerum.\n \rEt odio totam adipisci autem. Qui at quo aliquid ut rerum. Iste enim voluptatibus ipsam distinctio doloribus laborum neque. Qui quia quis sint repellendus.",
|
||||
sendNotification: null,
|
||||
timestamp: "2019-07-02T22:27:11.838Z"
|
||||
}
|
||||
],
|
||||
showFrom: "2019-06-12T12:56:23.090Z",
|
||||
showUntil: "2020-01-02T05:39:39.000Z",
|
||||
startTime: "2019-06-26T12:56:23.090Z",
|
||||
tagline: "Voluptates reiciendis eos tempora placeat dolores eum omnis voluptatibus molestiae.",
|
||||
title: "et",
|
||||
url: "https://www.mfa.org/summer-party",
|
||||
ticketClasses: [
|
||||
{
|
||||
price: 171,
|
||||
_id: "5d1f0a9289511160ddd68225",
|
||||
available: 105,
|
||||
capacity: 226,
|
||||
endSale: "2020-01-02T05:39:39.957Z",
|
||||
itemId: "5d1f0a9289511160ddd681fc",
|
||||
name: "Magni vero voluptatem velit occaecati in fugit et dolor quas.",
|
||||
startSale: "2019-06-26T12:56:23.090Z"
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
15
app/screens/Event.styles.js
Normal file
15
app/screens/Event.styles.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export default const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
margin: 10,
|
||||
}
|
||||
});
|
||||
19
app/screens/Events.container.js
Normal file
19
app/screens/Events.container.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { fetchEvents } from '../actions/events.js';
|
||||
import { getEventsAsList } from '../selectors/events.js';
|
||||
|
||||
import Events from './Events.js';
|
||||
|
||||
const matchStateToProps = (state) => {
|
||||
const events = getEventsAsList(state);
|
||||
console.log('events:', events);
|
||||
|
||||
return { events };
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
fetchEvents: () => dispatch(fetchEvents(dispatch)),
|
||||
});
|
||||
|
||||
export default connect(matchStateToProps, mapDispatchToProps)(Events);
|
||||
@@ -20,15 +20,27 @@ export default class Events extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
this.props.fetchEvents();
|
||||
}
|
||||
|
||||
_keyExtractor = (event, index) => `${event._id}_${index}`;
|
||||
|
||||
_renderEventListItem = ({ event }) => <EventListItem event={event} />;
|
||||
|
||||
render() {
|
||||
const { events } = this.props;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>
|
||||
Events
|
||||
</Text>
|
||||
{events.size > 0 && (
|
||||
<FlatList
|
||||
data={events}
|
||||
keyExtractor={this._keyExtractor}
|
||||
renderItem={this._renderEventListItem}
|
||||
contentContainerStyle={styles.eventListContentContainer}
|
||||
style={styles.eventList}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -41,9 +53,6 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
margin: 10,
|
||||
}
|
||||
eventListContentContainer: {
|
||||
},
|
||||
});
|
||||
|
||||
32
app/screens/Profile.container.js
Normal file
32
app/screens/Profile.container.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { fetchProfile, updateProfile } from '../actions/profile.js';
|
||||
import { getNomDeBid, getProfile, isAllowedToBid } from '../selectors/profile.js';
|
||||
|
||||
import Profile from './Profile.js';
|
||||
|
||||
const matchStateToProps = (state) => {
|
||||
const profile = getProfile(state);
|
||||
|
||||
return {
|
||||
hasLinkedApple: profile.get('hasLinkedApple'),
|
||||
hasLinkedFacebook: profile.get('hasLinkedFacebook'),
|
||||
hasLinkedGoogle: profile.get('hasLinkedGoogle'),
|
||||
hasLocalAccount: profile.get('hasLocalAccount'),
|
||||
hasRegisteredAcccount: profile.get('hasRegisteredAcccount'),
|
||||
id: profile.get('id'),
|
||||
isAllowedToBid: isAllowedToBid(state),
|
||||
isVerified: profile.get('isVerified'),
|
||||
lastName: profile.get('lastName'),
|
||||
nomDeBid: getNomDeBid(state),
|
||||
organizationIdentifier: profile.get('organizationIdentifier'),
|
||||
paymentToken: profile.get('paymentToken'),
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
fetchProfile: () => dispatch(fetchProfile(dispatch)),
|
||||
updateProfile: () => dispatch(updateProfile(dispatch)),
|
||||
});
|
||||
|
||||
export default connect(matchStateToProps, mapDispatchToProps)(Profile);
|
||||
13
app/selectors/activeEvent.js
Normal file
13
app/selectors/activeEvent.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
const getState = (state) => state;
|
||||
|
||||
export const getActiveEventId = createSelector(
|
||||
[getState],
|
||||
(state) => state.get('activeEvent'),
|
||||
);
|
||||
|
||||
export const hasActiveEvent = createSelector(
|
||||
[getState],
|
||||
(state) => !!state.get('activeEvent'),
|
||||
);
|
||||
@@ -1,12 +1,9 @@
|
||||
import { Map } from 'immutable';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
const getState = (state) => state;
|
||||
import { getActiveEventId } from './activeEvent.js';
|
||||
|
||||
export const getActiveEvent = (state) => {
|
||||
const eventId = state.get('activeEvent');
|
||||
return state.getIn(['events', eventId], false)
|
||||
};
|
||||
const getState = (state) => state;
|
||||
|
||||
export const getEventById = (state, eventId) => state.getIn(['events', eventId], false);
|
||||
|
||||
@@ -15,7 +12,22 @@ export const getEvents = createSelector(
|
||||
(state) => state.get('events') || new Map(),
|
||||
);
|
||||
|
||||
export const getActiveEvent = createSelector(
|
||||
[getActiveEventId, getEvents],
|
||||
(eventId, eventsAsMap) => eventId ? eventsAsMap.get(eventId) : false,
|
||||
);
|
||||
|
||||
export const getDefaultEvent = createSelector(
|
||||
[getEvents],
|
||||
(eventsAsMap) => eventsAsMap.first(),
|
||||
);
|
||||
|
||||
export const getEventsAsList = createSelector(
|
||||
[getEvents],
|
||||
(eventsAsMap) => eventsAsMap.toList(),
|
||||
);
|
||||
|
||||
export const hasMultipleEvents = createSelector(
|
||||
[getEvents],
|
||||
(eventsAsMap) => eventsAsMap.size > 1,
|
||||
);
|
||||
|
||||
24
app/selectors/profile.js
Normal file
24
app/selectors/profile.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Map } from 'immutable';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
const getState = (state) => state;
|
||||
|
||||
export const getProfile = createSelector(
|
||||
[getState],
|
||||
(state) => state.get('profile'),
|
||||
);
|
||||
|
||||
export const getNomDeBid = createSelector(
|
||||
[getProfile],
|
||||
(profile) => profile.get('nomDeBid'),
|
||||
);
|
||||
|
||||
export const getProfileAvatarUrl = createSelector(
|
||||
[getProfile],
|
||||
(profile) => profile.get('avatar'),
|
||||
);
|
||||
|
||||
export const isAllowedToBid = createSelector(
|
||||
[getProfile],
|
||||
(profile) => profile.get('isAllowedToBid'),
|
||||
);
|
||||
Reference in New Issue
Block a user