diff --git a/app/actions/auction.js b/app/actions/auction.js
new file mode 100644
index 0000000..4864494
--- /dev/null
+++ b/app/actions/auction.js
@@ -0,0 +1,15 @@
+import {
+ SET_AUCTION_FILTER,
+ SET_AUCTION_VIEW_MODE,
+} from '../constants/actionTypes.js';
+
+export const changeFilterMode = (payload) => ({
+ type: SET_AUCTION_FILTER,
+ payload,
+});
+
+export const changeViewMode = (payload) => ({
+ type: SET_AUCTION_VIEW_MODE,
+ payload,
+});
+
diff --git a/app/actions/auctionStatus.js b/app/actions/auctionStatus.js
new file mode 100644
index 0000000..e939d04
--- /dev/null
+++ b/app/actions/auctionStatus.js
@@ -0,0 +1,39 @@
+import { List } from 'immutable';
+
+import { getEndpointUrl } from '../api/index.js';
+
+import {
+ AUCTIONS_UPDATED,
+ ITEMS_LOADED,
+} from '../constants/actionTypes.js';
+
+import { blockUI, unblockUI } from './index.js';
+import { API_ENDPOINTS } from '../constants/constants.js';
+
+import Auction from '../domain/Auction.js';
+
+
+const autionStatusLoadSuccess = (auctions, dispatch) => {
+ const payload = List(auctions).map((i) => Auction.fromJS(i));
+ dispatch({ type: AUCTIONS_UPDATED, payload });
+ dispatch(unblockUI);
+};
+
+export const fetchAuctionStatus = () => (dispatch, getState) => {
+ const state = getState();
+ const activeEvent = state.get('activeEvent');
+
+ let apiUrl = getEndpointUrl(API_ENDPOINTS.GET_STATUS);
+ apiUrl = apiUrl.replace(/:event_id$/, '');
+ if (activeEvent) {
+ apiUrl = `${apiUrl}${activeEvent}`;
+ }
+
+ dispatch(blockUI());
+
+ return fetch(apiUrl)
+ .then(response => response.json())
+ .then(payload => autionStatusLoadSuccess(payload, dispatch))
+ .catch(err => console.error('[actions::getStatus]', err));
+};
+
diff --git a/app/actions/events.js b/app/actions/events.js
new file mode 100644
index 0000000..4f69670
--- /dev/null
+++ b/app/actions/events.js
@@ -0,0 +1,28 @@
+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 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));
+};
diff --git a/app/actions/index.js b/app/actions/index.js
index 716381c..2b7aac3 100644
--- a/app/actions/index.js
+++ b/app/actions/index.js
@@ -1,78 +1,8 @@
-import { List } from 'immutable';
-
-import { getEndpointUrl } from '../api/index.js';
-
-import Auction from '../domain/Auction.js';
-import Event from '../domain/Event.js';
-import Item from '../domain/Item.js';
-
import {
- AUCTIONS_UPDATED,
BLOCK_UI,
- EVENTS_LOADED,
- GET_EVENTS,
- GET_ITEMS,
- ITEMS_LOADED,
UNBLOCK_UI,
} from '../constants/actionTypes.js';
-import { API_ENDPOINTS } from '../constants/constants.js';
-
-export const getEvents = () => (dispatch) => {
- dispatch(blockUI());
- fetch(getEndpointUr(API_ENDPOINTS.GET_EVENTS))
- .then(response => response.json())
- .then((payload) => {
- const events = List(payload).map((i) => Event.fromJS(i));
- dispatch({ type: EVENTS_LOADED, payload: events });
- dispatch(unblockUI);
- });
-};
-
-export const getItems = () => (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 => {
- const items = List(payload).map(i => Item.fromJS(i));
- dispatch({ type: ITEMS_LOADED, payload: items });
- dispatch(unblockUI());
- })
- .catch(err => console.error('[actions::getItems]', err));
-};
-
-export const getStatus = () => (dispatch, getState) => {
- const state = getState();
- const activeEvent = state.get('activeEvent');
-
- let apiUrl = getEndpointUrl(API_ENDPOINTS.GET_STATUS);
- apiUrl = apiUrl.replace(/:event_id$/, '');
- if (activeEvent) {
- apiUrl = `${apiUrl}${activeEvent}`;
- }
-
- dispatch(blockUI());
-
- return fetch(apiUrl)
- .then(response => response.json())
- .then(payload => {
- const auctions = List(payload).map(i => Auction.fromJS(i));
- dispatch(unblockUI());
- dispatch({ type: AUCTIONS_UPDATED, payload: auctions });
- })
- .catch(err => console.error('[actions::getStatus]', err));
-};
-
export const blockUI = () => ({
type: BLOCK_UI,
});
diff --git a/app/actions/items.js b/app/actions/items.js
new file mode 100644
index 0000000..01c9ccd
--- /dev/null
+++ b/app/actions/items.js
@@ -0,0 +1,38 @@
+import { List } from 'immutable';
+
+import { getEndpointUrl } from '../api/index.js';
+
+import {
+ GET_ITEMS,
+ ITEMS_LOADED,
+} from '../constants/actionTypes.js';
+
+import { blockUI, unblockUI } from './index.js';
+import { API_ENDPOINTS } from '../constants/constants.js';
+
+import Item from '../domain/Item.js';
+
+
+const itemsLoadSuccess = (items, dispatch) => {
+ const payload = List(items).map((i) => Item.fromJS(i));
+ dispatch({ type: ITEMS_LOADED, payload });
+ dispatch(unblockUI);
+};
+
+export const fetchItems = () => (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));
+};
diff --git a/app/constants/actionTypes.js b/app/constants/actionTypes.js
index bb1958e..a74b001 100644
--- a/app/constants/actionTypes.js
+++ b/app/constants/actionTypes.js
@@ -49,3 +49,9 @@ export const UNBLOCK_UI = 'UNBLOCK_UI';
export const SET_ACTIVE_EVENT = 'SET_ACTIVE_EVENT';
export const UNSET_ACTIVE_EVENT = 'UNSET_ACTIVE_EVENT';
+
+export const SET_ACTIVE_ITEM = 'SET_ACTIVE_ITEM';
+export const UNSET_ACTIVE_ITEM = 'UNSET_ACTIVE_ITEM';
+
+export const SET_AUCTION_FILTER = 'SET_AUCTION_FILTER';
+export const SET_AUCTION_VIEW_MODE = 'SET_AUCTION_VIEW_MODE';
diff --git a/app/constants/constants.js b/app/constants/constants.js
index 9ff806b..271a04d 100644
--- a/app/constants/constants.js
+++ b/app/constants/constants.js
@@ -1,3 +1,7 @@
+export const ITEM_FILTERS = {
+ ALL: 'ALL',
+};
+
export const ITEM_TYPES = {
AUCTION: 'auction',
DONATION: 'donation',
@@ -19,9 +23,11 @@ export const SORT_MODES = {
TITLE_DSC: 'TITLE_DSC',
};
-export const VIEW_MODES = {
- LIST: 'LIST',
- GRID: 'GRID',
+export const AUCTION_VIEW_MODES = {
+ ALL: 'ALL',
+ BIDDING: 'BIDDING',
+ NO_BIDS: 'NO_BIDS',
+ WINNING: 'WINNING',
};
export const API_ENDPOINTS = {
diff --git a/app/containers/Auction.js b/app/containers/Auction.js
index 368f407..3e58c36 100644
--- a/app/containers/Auction.js
+++ b/app/containers/Auction.js
@@ -1,18 +1,23 @@
import { connect } from 'react-redux';
-import { getItems, getStatus } from '../actions/index.js';
+import { fetchItems } from '../actions/items.js';
+import { fetchAuctionStatus } from '../actions/auctionStatus.js';
import { getAuctionItemsAsList } from '../selectors/items.js';
import Auction from '../screens/Auction.js';
-const matchStateToProps = (state) => ({
- items: getAuctionItemsAsList(state),
-});
+const matchStateToProps = (state) => {
+ const items = getAuctionItemsAsList(state);
+ console.log('items:', items);
+
+ return { items };
+};
const mapDispatchToProps = (dispatch) => ({
- fetchItems: () => dispatch(getItems(dispatch)),
- fetchStatus: () => dispatch(getStatus(dispatch)),
+ changeViewMode: (mode) => dispatch(changeViewMode(mode)),
+ fetchItems: () => dispatch(fetchItems(dispatch)),
+ fetchStatus: () => dispatch(fetchAuctionStatus(dispatch)),
});
export default connect(matchStateToProps, mapDispatchToProps)(Auction);
diff --git a/app/containers/Event.js b/app/containers/Event.js
new file mode 100644
index 0000000..6716cc8
--- /dev/null
+++ b/app/containers/Event.js
@@ -0,0 +1,34 @@
+import { connect } from 'react-redux';
+
+import { fetchEvent } from '../actions/events.js';
+import { getEventById } from '../selectors/events.js';
+
+import Event from '../screens/Event.js';
+
+const matchStateToProps = (state) => {
+ const eventId = state.get('activeEvent');
+ const event = getEventById(state, eventId);
+
+ return {
+ description: event.get('description'),
+ endTime: event.get('endTime'),
+ id: event.get('id'),
+ images: event.get('images'),
+ isTicketed: event.get('isTicketed'),
+ posts: event.get('posts'),
+ requireLoginToSeeAuction: event.get('requireLoginToSeeAuction'),
+ showFrom: event.get('showFrom'),
+ showUntil: event.get('showUntil'),
+ startTime: event.get('startTime'),
+ tagline: event.get('tagline'),
+ ticketClasses: event.get('ticketClasses'),
+ title: event.get('title'),
+ url: event.get('url'),
+ };
+};
+
+const mapDispatchToProps = (dispatch) => ({
+ fetchEvent: () => dispatch(fetchEvent(dispatch)),
+});
+
+export default connect(matchStateToProps, mapDispatchToProps)(Event);
diff --git a/app/containers/Events.js b/app/containers/Events.js
new file mode 100644
index 0000000..f5124d4
--- /dev/null
+++ b/app/containers/Events.js
@@ -0,0 +1,19 @@
+import { connect } from 'react-redux';
+
+import { fetchEvents } from '../actions/events.js';
+import { getEventsAsList } from '../selectors/events.js';
+
+import Events from '../screens/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);
diff --git a/app/containers/Item/Grid.js b/app/containers/Item/Grid.js
new file mode 100644
index 0000000..e69de29
diff --git a/app/containers/Item/Item.js b/app/containers/Item/Item.js
new file mode 100644
index 0000000..c03d330
--- /dev/null
+++ b/app/containers/Item/Item.js
@@ -0,0 +1,16 @@
+export const matchStateToProps = (state, ownProps) => {
+ const { item } = ownProps;
+
+ return {
+ description: item.get('description'),
+ donor: item.get('donor'),
+ end: item.get('end'),
+ id: item.get('id'),
+ images: item.get('images').toArray(),
+ start: item.get('start'),
+ startingPrice: item.get('startingPrice'),
+ subtitle: item.get('subtitle'),
+ title: item.get('title'),
+ type: item.get('type'),
+ };
+};
diff --git a/app/containers/Item/List.js b/app/containers/Item/List.js
new file mode 100644
index 0000000..57e009d
--- /dev/null
+++ b/app/containers/Item/List.js
@@ -0,0 +1,6 @@
+import { connect } from 'react-redux';
+
+import { mapStateToProps } from './Item.js';
+import ItemRow from '../../components/Item/List.js';
+
+export default connect(mapStateToProps, null)(ItemRow);
diff --git a/app/reducers/activeItem.js b/app/reducers/activeItem.js
new file mode 100644
index 0000000..27d92ed
--- /dev/null
+++ b/app/reducers/activeItem.js
@@ -0,0 +1,12 @@
+import { SET_ACTIVE_ITEM, UNSET_ACTIVE_ITEM } from '../constants/actionTypes.js';
+
+export const activeItem = (state = null, action) => {
+ switch (action.type) {
+ case SET_ACTIVE_ITEM:
+ return action.payload;
+ case UNSET_ACTIVE_ITEM:
+ return null;
+ default:
+ return state;
+ }
+};
diff --git a/app/reducers/auctionFilter.js b/app/reducers/auctionFilter.js
new file mode 100644
index 0000000..cfb90d4
--- /dev/null
+++ b/app/reducers/auctionFilter.js
@@ -0,0 +1,11 @@
+import { SET_ITEM_FILTER } from '../constants/actionTypes.js';
+import { ITEM_FILTERS } from '../constants/constants.js';
+
+export const itemFilter = (state = ITEM_FILTERS.ALL, action) => {
+ switch (action.type) {
+ case SET_AUCTION_FILTER:
+ return action.payload;
+ default:
+ return state;
+ }
+};
diff --git a/app/reducers/auctionView.js b/app/reducers/auctionView.js
new file mode 100644
index 0000000..87777d8
--- /dev/null
+++ b/app/reducers/auctionView.js
@@ -0,0 +1,11 @@
+import { SET_AUCTION_VIEW_MODE } from '../constants/actionTypes.js';
+import { AUCTION_VIEW_MODES } from '../constants/constants.js';
+
+export const auctionView = (state = AUCTION_VIEW_MODES.ALL, action) => {
+ switch (action.type) {
+ case SET_AUCTION_VIEW_MODE:
+ return action.payload;
+ default:
+ return state;
+ }
+};
diff --git a/app/reducers/index.js b/app/reducers/index.js
index 6d4a27f..58e24ee 100644
--- a/app/reducers/index.js
+++ b/app/reducers/index.js
@@ -1,14 +1,20 @@
import { combineReducers } from 'redux-immutable';
import { activeEvent } from './activeEvent.js';
+import { activeItem } from './activeItem.js';
+import { auctionFilter } from './auctionFilter.js';
import { auctions } from './auctions.js';
+import { auctionView } from './auctionView.js';
import { blockUI } from './blockUI.js';
import { events } from './events.js';
import { items } from './items.js';
const rootReducer = combineReducers({
activeEvent,
+ activeItem,
+ auctionFilter,
auctions,
+ auctionView,
blockUI,
events,
items,
diff --git a/app/screens/Auction.js b/app/screens/Auction.js
index 8c00674..2afe008 100644
--- a/app/screens/Auction.js
+++ b/app/screens/Auction.js
@@ -1,3 +1,4 @@
+import { List } from 'immutable';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
@@ -8,11 +9,10 @@ import {
View,
} from 'react-native';
-import { SORT_MODES, VIEW_MODES } from '../constants/constants.js';
+import { SORT_MODES, AUCTION_VIEW_MODES } from '../constants/constants.js';
import FilterBar from '../components/Auction/FilterBar.js';
-import GridItem from '../components/Item/Grid.js';
-import ListItem from '../components/Item/List.js';
+import ListItem from '../containers/Item/List.js';
export default class Auction extends Component {
static get propTypes() {
@@ -20,7 +20,10 @@ export default class Auction extends Component {
changeFilter: PropTypes.func,
fetchItems: PropTypes.func.isRequired,
fetchStatus: PropTypes.func.isRequired,
- items: PropTypes.array,
+ items: PropTypes.oneOfType([
+ PropTypes.array,
+ PropTypes.instanceOf(List),
+ ]),
};
}
@@ -39,7 +42,7 @@ export default class Auction extends Component {
this.state = {
sort: SORT_MODES.TITLE_ASC,
- view: VIEW_MODES.LIST,
+ view: AUCTION_VIEW_MODES.ALL,
};
}
@@ -58,14 +61,7 @@ export default class Auction extends Component {
_keyExtractor = (item, index) => `${item._id}_${index}`;
- _renderItem = (view) => ({ item }) => {
- console.log('_renderItem', item);
- if (view === VIEW_MODES.GRID) {
- return ;
- }
-
- return ;
- }
+ _renderItem = ({ item }) => ;
render() {
const { items } = this.props;
diff --git a/app/selectors/auctions.js b/app/selectors/auctions.js
index cb90519..81d7ea7 100644
--- a/app/selectors/auctions.js
+++ b/app/selectors/auctions.js
@@ -1,7 +1,5 @@
import { createSelector } from 'reselect';
-//import { getItemsIdsWithNoBids, getMyBidItemIds, getMyWinningItemIds } from './auctions.js';
-
const getState = (state) => state;
export const getItemBidCount = (state, itemId) => state.getIn(['auctions', itemId, 'bidCount'], 0);
@@ -11,3 +9,25 @@ export const getItemPrice = (state, itemId) => state.getIn(['auctions', itemId,
export const isBiddingItem = (state, itemId) => state.getIn(['auctions', itemId, 'isBidding'], false);
export const isWinningItem = (state, itemId) => state.getIn(['auctions', itemId, 'isWinning'], false);
+
+export const getAuctionStatus = (state, itemId) => state.getIn(['actions', itemId], false);
+
+export const getAuctionStatuses = createSelector(
+ [getState],
+ (state) => state.get('actions') || new Map(),
+);
+
+export const getItemsIdsWithNoBids = createSelector(
+ [getAuctionStatuses],
+ (auctions) => auctions.filter(auction => auction.bidCount === 0);
+);
+
+export const getMyBidItemIds = createSelector(
+ [getAuctionStatuses],
+ (auctions) => auctions.filter(auction => auction.isBidding);
+);
+
+export const getMyWinningItemIds = createSelector(
+ [getAuctionStatuses],
+ (auctions) => auctions.filter(auction => auction.isWinning);
+);
diff --git a/app/selectors/events.js b/app/selectors/events.js
new file mode 100644
index 0000000..26c7560
--- /dev/null
+++ b/app/selectors/events.js
@@ -0,0 +1,21 @@
+import { Map } from 'immutable';
+import { createSelector } from 'reselect';
+
+const getState = (state) => state;
+
+export const getActiveEvent = (state) => {
+ const eventId = state.get('activeEvent');
+ return state.getIn(['events', eventId], false)
+};
+
+export const getEventById = (state, eventId) => state.getIn(['events', eventId], false);
+
+export const getEvents = createSelector(
+ [getState],
+ (state) => state.get('events') || new Map(),
+);
+
+export const getEventsAsList = createSelector(
+ [getEvents],
+ (eventsAsMap) => eventsAsMap.toList(),
+);
diff --git a/app/selectors/items.js b/app/selectors/items.js
index 340cad3..29bba08 100644
--- a/app/selectors/items.js
+++ b/app/selectors/items.js
@@ -1,6 +1,7 @@
+import { Map } from 'immutable';
import { createSelector } from 'reselect';
-//import { getItemsIdsWithNoBids, getMyBidItemIds, getMyWinningItemIds } from './auctions.js';
+import { getItemsIdsWithNoBids, getMyBidItemIds, getMyWinningItemIds } from './auctions.js';
const getState = (state) => state;
@@ -26,6 +27,36 @@ export const getAuctionItemsAsList = createSelector(
(auctionItemsAsMap) => auctionItemsAsMap.toList(),
);
+export const getAuctionItemsUserIsBidding = createSelector(
+ [getAuctionItems, getMyBidItemIds],
+ (items, myBids) => items.filter(i => myBids.indexOf(i.id)) || new Map(),
+);
+
+export const getAuctionItemsUserIsBiddingAsList = createSelector(
+ [getAuctionItemsUserIsBidding],
+ (auctionItemsAsMap) => auctionItemsAsMap.toList(),
+);
+
+export const getAuctionItemsUserIsWinning = createSelector(
+ [getAuctionItemsUserIsBidding, getMyWinningItemIds],
+ (items, myWins) => items.filter(i => myWins.indexOf(i.id)) || new Map(),
+);
+
+export const getAuctionItemsUserIsWinningAsList = createSelector(
+ [getAuctionItemsUserIsWinning],
+ (auctionItemsAsMap) => auctionItemsAsMap.toList(),
+);
+
+export const getAuctionItemsWithNoBids = createSelector(
+ [getAuctionItems, getItemsIdsWithNoBids],
+ (items, noBids) => items.filter(i => noBids.indexOf(i.id)) || new Map(),
+);
+
+export const getAuctionItemsWithNoBidsAsList = createSelector(
+ [getAuctionItemsWithNoBids],
+ (auctionItemsAsMap) => auctionItemsAsMap.toList(),
+);
+
export const getTicketItems = createSelector(
[getState],
(state) => state.get('items').filter(i => i.type === 'ticket') || new Map(),
@@ -35,8 +66,3 @@ export const getTicketItemsAsList = createSelector(
[getTicketItems],
(ticketItemsAsMap) => ticketItemsAsMap.toList(),
);
-
-export const getAuctionItemsWithNoBids = createSelector(
- [getAuctionItems],
- (auctionItemsAsMap) => auctionItemsAsMap.filter(i => i.bidCount),
-);