- Linting... Prettier...

This commit is contained in:
2019-08-07 01:59:10 -04:00
parent 3dc8589fb4
commit 847c9b192a
102 changed files with 2161 additions and 2109 deletions

View File

@@ -1,4 +1,81 @@
module.exports = { module.exports = {
root: true, root: true,
extends: '@react-native-community', extends: '@react-native-community',
env: {
mocha: true,
browser: true,
},
// parser: 'babel-eslint',
// plugins: ['babel', 'immutablejs'],
plugins: ['immutablejs'],
rules: {
'comma-dangle': 'off',
'func-call-spacing': 'off',
'import/prefer-default-export': 'off',
'max-len': ['error', 150, { ignoreComments: true, ignoreTemplateLiterals: true }],
'no-confusing-arrow': 'off',
'no-mixed-operators': 'off',
'no-restricted-properties': [
2,
{
object: 'describe',
property: 'only',
message:
'Please remove any instance of .only from unit tests. If .only is required outside of a unit test, feel free to add an eslint override to ignore this instance of this error.',
},
{
object: 'it',
property: 'only',
message:
'Please remove any instance of .only from unit tests. If .only is required outside of a unit test, feel free to add an eslint override to ignore this instance of this error.',
},
{
object: 'context',
property: 'only',
message:
'Please remove any instance of .only from unit tests. If .only is required outside of a unit test, feel free to add an eslint override to ignore this instance of this error.',
},
{
object: 'tape',
property: 'only',
message:
'Please remove any instance of .only from unit tests. If .only is required outside of a unit test, feel free to add an eslint override to ignore this instance of this error.',
},
{
object: 'test',
property: 'only',
message:
'Please remove any instance of .only from unit tests. If .only is required outside of a unit test, feel free to add an eslint override to ignore this instance of this error.',
},
{
object: 'fixture',
property: 'only',
message:
'Please remove any instance of .only from unit tests. If .only is required outside of a unit test, feel free to add an eslint override to ignore this instance of this error.',
},
],
'no-spaced-func': 'off',
'react/jsx-closing-bracket-location': 'off',
'react/jsx-first-prop-new-line': 'off',
'react/jsx-no-literals': ['error', { noStrings: true }],
'react/jsx-no-target-blank': 'off',
'react/no-danger': 'off',
'space-before-function-paren': 'off',
indent: 'off',
'indent-legacy': 'off',
'immutablejs/no-native-map-set': 'error',
'no-invalid-this': 'off',
// 'babel/no-invalid-this': 'error',
},
overrides: [
{
files: ['lib/fixtures/**/*.js', '**/testHelper.js'],
rules: {
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
},
globals: {
expect: false,
},
},
],
}; };

8
.prettierrc Normal file
View File

@@ -0,0 +1,8 @@
{
"arrowParens": "always",
"jsxBracketSameLine": false,
"singleQuote": true,
"tabWidth": 4,
"printWidth": 100,
"trailingComma": "all"
}

View File

@@ -1,12 +1,3 @@
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React from 'react';
import { createAppContainer } from 'react-navigation'; import { createAppContainer } from 'react-navigation';
import { Tabs } from './router.js'; import { Tabs } from './router.js';

View File

@@ -0,0 +1,6 @@
import { SET_ACTIVE_EVENT } from '../constants/actionTypes.js';
export const setActiveEvent = (eventId) => ({
type: SET_ACTIVE_EVENT,
payload: eventId,
});

View File

@@ -1,5 +1,4 @@
import { blockUI, unblockUI } from './index.js'; import { placeBid as placeBidApi } from '../api/bid.js';
import { import {
BID_FAILURE, BID_FAILURE,
BID_SUCCESS, BID_SUCCESS,
@@ -7,17 +6,33 @@ import {
SET_AUCTION_FILTER, SET_AUCTION_FILTER,
SET_AUCTION_VIEW_MODE, SET_AUCTION_VIEW_MODE,
} from '../constants/actionTypes.js'; } from '../constants/actionTypes.js';
import { getActiveEventId } from '../selectors/activeEvent.js';
import { getAuthToken } from '../selectors/auth.js';
const placeBidFailure = (bid, dispatch) => { const placeBidFailure = (payload) => ({
dispatch({ type: BID_FAILURE, bid }); type: BID_FAILURE,
dispatch(unblockUI); payload,
});
const placeBidSuccess = (payload) => ({
type: BID_SUCCESS,
payload,
});
const handleBidFailure = (error) => (dispatch) => {
console.error('[postBid]', error);
dispatch(placeBidFailure(error));
}; };
const placeBidSuccess = (bid, dispatch) => { const handleBidSuccess = (result) => (dispatch) => {
dispatch({ type: BID_SUCCESS, bid }); dispatch(placeBidSuccess(result));
dispatch(unblockUI);
}; };
const startPlacingBid = (itemId) => ({
type: PLACE_BID,
payload: itemId,
});
export const changeFilterMode = (payload) => ({ export const changeFilterMode = (payload) => ({
type: SET_AUCTION_FILTER, type: SET_AUCTION_FILTER,
payload, payload,
@@ -28,25 +43,12 @@ export const changeViewMode = (payload) => ({
payload, payload,
}); });
export const placeBid = (payload) => ({ export const placeBid = ({ bidAmount, itemId, maxAmount }) => (dispatch, getState) => {
type: PLACE_BID, const authToken = getAuthToken(getState());
payload, const eventId = getActiveEventId(getState());
});
export const postBid = () => (dispatch, getState) => { dispatch(startPlacingBid(itemId));
const state = getState(); placeBidApi({ bidAmount, eventId, itemId, maxAmount }, authToken)
const activeEvent = state.get('activeEvent'); .then((payload) => dispatch(handleBidSuccess(payload)))
.catch((err) => dispatch(handleBidFailure(err)));
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));
}; };

View File

@@ -1,39 +1,27 @@
import { List } from 'immutable'; import { List } from 'immutable';
import { getEndpointUrl } from '../api/index.js'; import { fetchAuctionStatus as fetchActionStatusApi } from '../api/actionStatus.js';
import { AUCTIONS_UPDATED } from '../constants/actionTypes.js';
import { import { getActiveEventId } from '../selectors/activeEvent.js';
AUCTIONS_UPDATED, import { getAuthToken } from '../selectors/auth.js';
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'; import Auction from '../domain/Auction.js';
const auctionsUpdated = (payload) => ({
type: AUCTIONS_UPDATED,
payload,
});
const autionStatusLoadSuccess = (auctions, dispatch) => { const autionStatusLoadSuccess = (auctions) => (dispatch) => {
const payload = List(auctions).map((i) => Auction.fromJS(i)); const payload = List(auctions).map((i) => Auction.fromJS(i));
dispatch({ type: AUCTIONS_UPDATED, payload }); dispatch(auctionsUpdated(payload));
dispatch(unblockUI);
}; };
export const fetchAuctionStatus = () => (dispatch, getState) => { export const fetchAuctionStatus = () => (dispatch, getState) => {
const state = getState(); const authToken = getAuthToken(getState());
const activeEvent = state.get('activeEvent'); const eventId = getActiveEventId(getState());
let apiUrl = getEndpointUrl(API_ENDPOINTS.GET_STATUS); return fetchActionStatusApi(eventId, authToken)
apiUrl = apiUrl.replace(/:event_id$/, ''); .then((payload) => dispatch(autionStatusLoadSuccess(payload)))
if (activeEvent) { .catch((err) => console.error('[actions::getStatus]', err));
apiUrl = `${apiUrl}${activeEvent}`;
}
dispatch(blockUI());
return fetch(apiUrl)
.then(response => response.json())
.then(payload => autionStatusLoadSuccess(payload, dispatch))
.catch(err => console.error('[actions::getStatus]', err));
}; };

View File

@@ -1,36 +1,31 @@
import { List } from 'immutable'; import { List } from 'immutable';
import { blockUI, unblockUI } from './index.js';
import { fetchEvents as fetchEventsApi } from '../api/events.js'; import { fetchEvents as fetchEventsApi } from '../api/events.js';
import { import { EVENTS_LOAD_FAILED, EVENTS_LOADED, GET_EVENTS } from '../constants/actionTypes.js';
EVENTS_LOAD_FAILED,
EVENTS_LOADED,
GET_EVENTS,
} from '../constants/actionTypes.js';
import Event from '../domain/Event.js'; import Event from '../domain/Event.js';
import { getAuthToken } from '../selectors/auth.js'; import { getAuthToken } from '../selectors/auth.js';
const beginFetchEvents = () => ({ type: GET_EVENTS });
const eventsLoaded = (payload) => ({ type: EVENTS_LOADED, payload }); const eventsLoaded = (payload) => ({ type: EVENTS_LOADED, payload });
const eventsLoadError = (payload) => ({ type: EVENTS_LOAD_FAILED, payload }); const eventsLoadError = (payload) => ({ type: EVENTS_LOAD_FAILED, payload });
const eventsFetchSuccess = (items) => (dispatch) => { const eventsFetchSuccess = (items) => (dispatch) => {
const payload = List(items).map((i) => Event.fromJS(i)); const payload = List(items).map((i) => Event.fromJS(i));
dispatch(eventsLoaded(payload)); dispatch(eventsLoaded(payload));
dispatch(unblockUI);
}; };
const eventsFetchFailure = (error) => (dispatch) => { const eventsFetchFailure = (error) => (dispatch) => {
console.error('[actions::events::eventsFetchFailure]', error); console.error('[actions::events::eventsFetchFailure]', error);
dispatch(eventsLoadError(error)); dispatch(eventsLoadError(error));
dispatch(unblockUI);
}; };
export const fetchEvents = () => (dispatch, getState) => { export const fetchEvents = () => (dispatch, getState) => {
const authToken = getAuthToken(getState()); const authToken = getAuthToken(getState());
dispatch(beginFetchEvents());
fetchEventsApi(authToken) fetchEventsApi(authToken)
.then(payload => dispatch(eventsFetchSuccess(payload))) .then((payload) => dispatch(eventsFetchSuccess(payload)))
.catch(err => dispatch(eventsFetchFailure(err))); .catch((err) => dispatch(eventsFetchFailure(err)));
}; };

View File

@@ -1,7 +1,4 @@
import { import { BLOCK_UI, UNBLOCK_UI } from '../constants/actionTypes.js';
BLOCK_UI,
UNBLOCK_UI,
} from '../constants/actionTypes.js';
export const blockUI = () => ({ export const blockUI = () => ({
type: BLOCK_UI, type: BLOCK_UI,

View File

@@ -1,39 +1,34 @@
import { List } from 'immutable'; import { List } from 'immutable';
import { fetchItems as fetchItemsApi } from '../api/items.js'; import { fetchItems as fetchItemsApi } from '../api/items.js';
import { import { GET_ITEMS, ITEMS_LOAD_FAILED, ITEMS_LOADED } from '../constants/actionTypes.js';
GET_ITEMS,
ITEMS_LOADED,
} from '../constants/actionTypes.js';
import { getActiveEventId } from '../selectors/activeEvent.js'; import { getActiveEventId } from '../selectors/activeEvent.js';
import { getAuthToken } from '../selectors/auth.js'; import { getAuthToken } from '../selectors/auth.js';
import { blockUI, unblockUI } from './index.js';
import Item from '../domain/Item.js'; import Item from '../domain/Item.js';
const beginItemLoad = () => ({ type: GET_ITEMS });
const itemsLoaded = (payload) => ({ type: ITEMS_LOADED, payload }); const itemsLoaded = (payload) => ({ type: ITEMS_LOADED, payload });
const itemsLoadError = (payload) => ({ type: ITEMS_LOAD_FAILED, payload }); const itemsLoadFailure = (payload) => ({ type: ITEMS_LOAD_FAILED, payload });
const itemsFetchSuccess = (items) => (dispatch) => { const itemsFetchSuccess = (items) => (dispatch) => {
const payload = List(items).map((i) => Item.fromJS(i)); const payload = List(items).map((i) => Item.fromJS(i));
dispatch(itemsLoaded(payload)); dispatch(itemsLoaded(payload));
dispatch(unblockUI);
}; };
const itemsFetchFailure = (error) => (dispatch) => { const itemsFetchFailure = (error) => (dispatch) => {
console.error('[actions::items::itemsFetchFailure]', error); console.error('[actions::items::itemsFetchFailure]', error);
dispatch(itemsLoadFailure(error)); dispatch(itemsLoadFailure(error));
dispatch(unblockUI);
}; };
export const fetchItems = () => (dispatch, getState) => { export const fetchItems = () => (dispatch, getState) => {
const eventId = getActiveEventId(getState());
const authToken = getAuthToken(getState()); const authToken = getAuthToken(getState());
const eventId = getActiveEventId(getState());
fetchItemsApi(activeEvent, authToken) dispatch(beginItemLoad());
.then(payload => dispatch(itemsFetchSuccess(payload))) fetchItemsApi(eventId, authToken)
.catch(err => dispatch(itemsFetchFailure(err))); .then((payload) => dispatch(itemsFetchSuccess(payload)))
.catch((err) => dispatch(itemsFetchFailure(err)));
}; };

View File

@@ -13,6 +13,8 @@ import {
LOGIN_SUCCESS, LOGIN_SUCCESS,
PROFILE_EMAIL_AVAILABLE, PROFILE_EMAIL_AVAILABLE,
PROFILE_NOM_AVAILABLE, PROFILE_NOM_AVAILABLE,
REGISTRATION_FAILURE,
REGISTRATION_SUCCESS,
UNSET_AUTH, UNSET_AUTH,
UNSET_PROFILE, UNSET_PROFILE,
UPDATE_PROFILE, UPDATE_PROFILE,
@@ -65,21 +67,17 @@ const updateProfile = (profile) => ({
payload: profile, payload: profile,
}); });
export const checkEmailAvailability = (email) => (dispatch) => { export const checkEmailAvailability = (email) => (dispatch) => {};
}; export const checkNomAvailability = (nomDeBid) => (dispatch) => {};
export const checkNomAvailability = (nomDeBid) => (dispatch) => {
};
export const login = (username, password) => (dispatch) => { export const login = (username, password) => (dispatch) => {
dispatch(blockUI()); dispatch(blockUI());
loginUser(username, password) loginUser(username, password)
.then(result => { .then((result) => {
dispatch(loginSuccess(result)) dispatch(loginSuccess(result));
}) })
.catch(err => dispatch(loginFailure(err))); .catch((err) => dispatch(loginFailure(err)));
}; };
export const logout = () => (dispatch) => { export const logout = () => (dispatch) => {
@@ -103,8 +101,8 @@ const handleRegistrationFailure = (error) => (dispatch) => {
export const registerUser = (user) => (dispatch) => { export const registerUser = (user) => (dispatch) => {
dispatch(blockUI()); dispatch(blockUI());
registerNewUser(user) registerNewUser(user)
.then(user => dispatch(handleRegistrationSuccess(user))) .then((user) => dispatch(handleRegistrationSuccess(user)))
.catch(err => dispatch(handleRegistrationFailure(err))); .catch((err) => dispatch(handleRegistrationFailure(err)));
}; };
// FACEBOOK // FACEBOOK
@@ -113,12 +111,7 @@ export const facebookLoginSuccess = (result) => (dispatch) => {
dispatch(facebookLoginSuccess(result)); dispatch(facebookLoginSuccess(result));
}; };
// LOGIN SERVICES COMMON ACTIONS // LOGIN SERVICES COMMON ACTIONS
export const serviceRegistrationError = (error) => (dispatch) => { export const serviceRegistrationError = (error) => (dispatch) => {};
}; export const serviceRegistrationCanceled = () => (dispatch) => {};
export const serviceRegistrationCanceled = () => (dispatch) => {
};

7
app/api/auctionStatus.js Normal file
View File

@@ -0,0 +1,7 @@
import { API_ENDPOINTS, requestGet } from './index.js';
export const fetchAuctionStatus = (eventId, auth) => {
const path = `${API_ENDPOINTS.GET_STATUS})/${eventId}`;
const opts = { Authorization: auth ? `Bearer ${auth}` : null };
return requestGet(path, null, opts);
};

10
app/api/bid.js Normal file
View File

@@ -0,0 +1,10 @@
import { API_ENDPOINTS, requestPost } from './index.js';
export const placeBid = ({ bidAmount, bidderId, eventId, itemId, maxAmount }, auth) => {
const requestOptions = { Authorization: auth ? `Bearer ${auth}` : null };
return requestPost({
path: `${API_ENDPOINTS.PLACE_BID}/${itemId}`,
body: { bidAmount, bidderId, eventId, maxAmount },
requestOptions,
});
};

View File

@@ -1,8 +1,10 @@
import { API_URL } from '../constants/constants.js'; import { API_URL } from '../constants/constants.js';
export const constructUrl = (path, params, host = API_URL) => { export const constructUrl = (path, params, host = API_URL) => {
if (!(/^\//g).test(path)) { if (!/^\//g.test(path)) {
throw new Error(`Invalid path! Expecting a valid relative path (path needs to start with /)(${path})`); throw new Error(
`Invalid path! Expecting a valid relative path (path needs to start with /)(${path})`,
);
} }
let url = path; let url = path;
@@ -27,7 +29,7 @@ export const constructUrl = (path, params, host = API_URL) => {
*/ */
export const formatPostData = (body) => { export const formatPostData = (body) => {
const postData = new FormData(); const postData = new FormData();
Object.keys(body).forEach(key => postData.append(key, body[key])); Object.keys(body).forEach((key) => postData.append(key, body[key]));
return postData; return postData;
}; };
@@ -44,8 +46,7 @@ const parseQueryParamsObject = (queryParams) => {
return null; return null;
} }
return Object return Object.keys(queryParams)
.keys(queryParams)
.map((key) => { .map((key) => {
const value = queryParams[key]; const value = queryParams[key];
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
@@ -66,12 +67,11 @@ const parseQueryParamsArray = (queryParams) => {
.join('&'); .join('&');
}; };
export const parseQueryParams = queryParams => ( export const parseQueryParams = (queryParams) =>
parseQueryParamsString(queryParams) || parseQueryParamsString(queryParams) ||
parseQueryParamsObject(queryParams) || parseQueryParamsObject(queryParams) ||
parseQueryParamsArray(queryParams) || parseQueryParamsArray(queryParams) ||
'' '';
);
export const request = (url, options) => { export const request = (url, options) => {
try { try {

View File

@@ -11,7 +11,7 @@ import { API_URL } from '../constants/constants.js';
const DefaultRequestOptions = {}; const DefaultRequestOptions = {};
const endpoints = { export const API_ENDPOINTS = {
// Events and Items // Events and Items
GET_EVENTS: '/events', GET_EVENTS: '/events',
// GET_ITEMS: '/items?eventId=:event_id', // GET_ITEMS: '/items?eventId=:event_id',
@@ -20,7 +20,7 @@ const endpoints = {
// Auction Interactions // Auction Interactions
// GET_STATUS: '/auction/:event_id', // GET_STATUS: '/auction/:event_id',
GET_STATUS: '/auction', GET_STATUS: '/auction',
PLACE_BID: '/bids/:item_id', PLACE_BID: '/bids',
PURCHASE_ITEM: '/sales', PURCHASE_ITEM: '/sales',
// User/Profile // User/Profile
@@ -61,7 +61,7 @@ export const requestGet = (path, queryParams = [], requestOptions = {}) => {
return request(constructUrl(path, params), { return request(constructUrl(path, params), {
...DefaultRequestOptions, ...DefaultRequestOptions,
...requestOptions ...requestOptions,
}) })
.then(validateResponse) .then(validateResponse)
.then(unwrapJson); .then(unwrapJson);
@@ -73,7 +73,7 @@ export const requestPost = (options) => {
body = {}, body = {},
queryParams = [], queryParams = [],
requestOptions = {}, requestOptions = {},
isFormattedPostData = false isFormattedPostData = false,
} = options; } = options;
const params = parseQueryParams(queryParams || []); const params = parseQueryParams(queryParams || []);
@@ -88,7 +88,7 @@ export const requestPost = (options) => {
...DefaultRequestOptions, ...DefaultRequestOptions,
...requestOptions, ...requestOptions,
method: 'POST', method: 'POST',
body: isFormattedPostData ? body : formatPostData(body) body: isFormattedPostData ? body : formatPostData(body),
}) })
.then(validateResponse) .then(validateResponse)
.then(unwrapJson); .then(unwrapJson);

View File

@@ -1,15 +1,19 @@
import { API_ENDPOINTS, requestGet } from './index.js'; import { API_ENDPOINTS, requestGet } from './index.js';
export const getEmailAvailability = (email) => requestGet(`${API_ENDPOINTS.VALIDATE_SIGNUP_EMAIL}/&{encodeURI(email)}`); export const getEmailAvailability = (email) =>
requestGet(`${API_ENDPOINTS.VALIDATE_SIGNUP_EMAIL}/&{encodeURI(email)}`);
export const getNomAvailaibility = (nomDeBid) => requestGet(`${API_ENDPOINTS.VALIDATE_SIGNUP_NOM}/${encodeURI(nomDeBid)}`); export const getNomAvailaibility = (nomDeBid) =>
requestGet(`${API_ENDPOINTS.VALIDATE_SIGNUP_NOM}/${encodeURI(nomDeBid)}`);
export const loginUser = (username, password) => requestPost({ export const loginUser = (username, password) =>
requestPost({
path: API_ENDPOINTS.LOGIN, path: API_ENDPOINTS.LOGIN,
body: { username, password }, body: { username, password },
}); });
export const registerNewUser = (user) => requestPost({ export const registerNewUser = (user) =>
requestPost({
path: API_ENDPOINTS.USER_SIGNUP, path: API_ENDPOINTS.USER_SIGNUP,
body: { user }, body: { user },
}); });

View File

@@ -8,4 +8,7 @@ const matchDispatchToProps = (dispatch) => ({
fetchEvents: () => dispatch(fetchEvents()), fetchEvents: () => dispatch(fetchEvents()),
}); });
export default connect(null, matchDispatchToProps)(AppHeader); export default connect(
null,
matchDispatchToProps,
)(AppHeader);

View File

@@ -10,7 +10,6 @@ import HeaderContentRight from './HeaderContentRight.container.js';
import styles from './AppHeader.styles.js'; import styles from './AppHeader.styles.js';
export default class AppHeader extends Component { export default class AppHeader extends Component {
static get propTypes() { static get propTypes() {
return { return {
fetchEvents: PropTypes.func.isRequired, fetchEvents: PropTypes.func.isRequired,

View File

@@ -13,4 +13,7 @@ const matchStateToProps = (state, ownProps) => {
}; };
}; };
export default connect(matchStateToProps, null)(HeaderContentLeft); export default connect(
matchStateToProps,
null,
)(HeaderContentLeft);

View File

@@ -1,21 +1,12 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { Text, TouchableOpacity, View } from 'react-native';
Text,
TouchableOpacity,
View,
} from 'react-native';
import BackIcon from './IconButtons/BackIcon.js'; import BackIcon from './IconButtons/BackIcon.js';
import EventsIcon from './IconButtons/EventsIcon.js'; import EventsIcon from './IconButtons/EventsIcon.js';
export default function HeaderContentLeft({ export default function HeaderContentLeft({ activeRoute, hasMultipleEvents, navigation }) {
activeRoute,
hasMultipleEvents,
navigation,
}) {
const _goBack = () => { const _goBack = () => {
if (hasActiveEvent) { if (hasActiveEvent) {
navigation.goBack(); navigation.goBack();
@@ -30,7 +21,6 @@ export default function HeaderContentLeft({
return false; return false;
}; };
if (activeRoute === 'Events') { if (activeRoute === 'Events') {
return <EventsIcon action={_goBack} />; return <EventsIcon action={_goBack} />;
} }
@@ -39,7 +29,7 @@ export default function HeaderContentLeft({
return <BackIcon action={_goBack} />; return <BackIcon action={_goBack} />;
} }
return <EventsIcon action={hasMultipleEvents ? _showEvents : null} /> return <EventsIcon action={hasMultipleEvents ? _showEvents : null} />;
} }
HeaderContentLeft.propTypes = { HeaderContentLeft.propTypes = {

View File

@@ -9,4 +9,7 @@ const matchStateToProps = (state, ownProps) => ({
hideUserProfileButton: ownProps.navigation.state.routeName === 'Profile', hideUserProfileButton: ownProps.navigation.state.routeName === 'Profile',
}); });
export default connect(matchStateToProps, null)(HeaderContentRight); export default connect(
matchStateToProps,
null,
)(HeaderContentRight);

View File

@@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import UserProfileButton from './UserProfileButton/UserProfileButton.container.js'; import UserProfileButton from './UserProfileButton/UserProfileButton.container.js';
export default function HeaderContentRight({ hideUserProfileButton, navigation }) { export default function HeaderContentRight({ hideUserProfileButton, navigation }) {
if (hideUserProfileButton) { if (hideUserProfileButton) {
return null; return null;
} }

View File

@@ -15,4 +15,7 @@ const matchStateToProps = (state) => {
}; };
}; };
export default connect(matchStateToProps, null)(EventTitle); export default connect(
matchStateToProps,
null,
)(EventTitle);

View File

@@ -1,21 +1,11 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { Text, TouchableOpacity, View } from 'react-native';
Text,
TouchableOpacity,
View,
} from 'react-native';
import styles from './EventTitle.styles.js'; import styles from './EventTitle.styles.js';
export default function EventTitle({ export default function EventTitle({ action, date, end, name, start }) {
action,
date,
end,
name,
start,
}) {
const _generateEventTitle = () => ( const _generateEventTitle = () => (
<View style={styles.eventInfo}> <View style={styles.eventInfo}>
<Text style={styles.eventName}>{name}</Text> <Text style={styles.eventName}>{name}</Text>

View File

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

View File

@@ -15,4 +15,7 @@ const matchStateToProps = (state, ownProps) => {
}; };
}; };
export default connect(matchStateToProps, null)(HeaderTitle); export default connect(
matchStateToProps,
null,
)(HeaderTitle);

View File

@@ -1,11 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { Text, TouchableOpacity, View } from 'react-native';
Text,
TouchableOpacity,
View,
} from 'react-native';
import EventTitle from './EventTitle/EventTitle.container.js'; import EventTitle from './EventTitle/EventTitle.container.js';
@@ -17,7 +13,6 @@ export default function HeaderTitle({
hasMultipleEvents, hasMultipleEvents,
navigation, navigation,
}) { }) {
const _goBack = () => { const _goBack = () => {
if (hasActiveEvent) { if (hasActiveEvent) {
navigation.goBack(); navigation.goBack();
@@ -32,7 +27,6 @@ export default function HeaderTitle({
return false; return false;
}; };
if (activeRoute === 'Events') { if (activeRoute === 'Events') {
return ( return (
<TouchableOpacity onPress={_goBack}> <TouchableOpacity onPress={_goBack}>
@@ -45,7 +39,7 @@ export default function HeaderTitle({
return <Text style={styles.screenHeader}>Profile</Text>; return <Text style={styles.screenHeader}>Profile</Text>;
} }
return <EventTitle action={hasMultipleEvents ? _showEvents : null} /> return <EventTitle action={hasMultipleEvents ? _showEvents : null} />;
} }
HeaderTitle.propTypes = { HeaderTitle.propTypes = {

View File

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

View File

@@ -5,7 +5,6 @@ import { TouchableOpacity } from 'react-native';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
export default function EventsIcon({ action }) { 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) { if (action) {

View File

@@ -8,4 +8,7 @@ const matchStateToProps = (state) => ({
avatarUrl: getProfileAvatarUrl(state), avatarUrl: getProfileAvatarUrl(state),
}); });
export default connect(matchStateToProps, null)(UserProfileButton); export default connect(
matchStateToProps,
null,
)(UserProfileButton);

View File

@@ -7,7 +7,6 @@ import { Icon } from 'react-native-elements';
import styles from './UserProfileButton.styles.js'; import styles from './UserProfileButton.styles.js';
export default function UserProfileButton({ avatarUrl, navigation }) { export default function UserProfileButton({ avatarUrl, navigation }) {
const _goToProfile = () => { const _goToProfile = () => {
navigation.navigate('Profile'); navigation.navigate('Profile');
return false; return false;

View File

@@ -1,13 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { StyleSheet, TouchableOpacity, Text, Image, View } from 'react-native';
StyleSheet,
TouchableOpacity,
Text,
Image,
View
} from 'react-native';
import GallerySwiper from 'react-native-gallery-swiper'; import GallerySwiper from 'react-native-gallery-swiper';
@@ -53,12 +47,12 @@ export default class AuctionListItem extends Component {
_getBidTime = () => { _getBidTime = () => {
const { end, start } = this.props; const { end, start } = this.props;
return getAuctionTime({ end, start }); return getAuctionTime({ end, start });
} };
_viewItemDetail = () => { _viewItemDetail = () => {
const { _id: id } = this.props.details; const { _id: id } = this.props.details;
this.props.navigation.navigate('Item', { id }); this.props.navigation.navigate('Item', { id });
} };
render() { render() {
const { const {
@@ -158,7 +152,7 @@ const styles = StyleSheet.create({
shadowColor: '#CCC', shadowColor: '#CCC',
shadowOffset: { shadowOffset: {
width: 1, width: 1,
height: 1 height: 1,
}, },
shadowOpacity: 1.0, shadowOpacity: 1.0,
shadowRadius: 1, shadowRadius: 1,

View File

@@ -3,10 +3,7 @@ import PropTypes from 'prop-types';
import { formatPrice } from '../../library/helpers.js'; import { formatPrice } from '../../library/helpers.js';
import { import { StyleSheet, Text } from 'react-native';
StyleSheet,
Text,
} from 'react-native';
const AuctionPriceAndBidCount = ({ bidCount, currentPrice }) => { const AuctionPriceAndBidCount = ({ bidCount, currentPrice }) => {
return ( return (

View File

@@ -1,10 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { StyleSheet, Text } from 'react-native';
StyleSheet,
Text,
} from 'react-native';
const BidStatus = ({ isBidding, isWinning }) => { const BidStatus = ({ isBidding, isWinning }) => {
if (!isBidding) { if (!isBidding) {
@@ -17,8 +14,8 @@ const BidStatus = ({ isBidding, isWinning }) => {
return ( return (
<Text style={statusBarStyle} numberOfLines={1}> <Text style={statusBarStyle} numberOfLines={1}>
{isWinning && `Oh no! You have been outbid!`} {isWinning && 'Oh no! You have been outbid!'}
{!isWinning && isBidding && `You have the winning bid! (for now...)`} {!isWinning && isBidding && 'You have the winning bid! (for now...)'}
</Text> </Text>
); );
}; };

View File

@@ -1,11 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { StyleSheet, Text, View } from 'react-native';
StyleSheet,
Text,
View,
} from 'react-native';
const FilterBar = ({ changeFilterer, changeViewMode, filterMode, viewMode }) => ( const FilterBar = ({ changeFilterer, changeViewMode, filterMode, viewMode }) => (
<View style={styles.filterBar}> <View style={styles.filterBar}>

View File

@@ -1,33 +1,24 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { StyleSheet, TouchableOpacity, Text, Image, View } from 'react-native';
StyleSheet,
TouchableOpacity,
Text,
Image,
View
} from 'react-native';
export default class EventListItem extends Component { export default class EventListItem extends Component {
static get propTypes() { static get propTypes() {
return { return {
description: PropTypes.string.isRequired, end: PropTypes.string.isRequired,
endTime: PropTypes.string.isRequired,
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,
images: PropTypes.arrayOf( images: PropTypes.arrayOf(
PropTypes.shape({ PropTypes.shape({
url: PropTypes.string, url: PropTypes.string,
}), }),
), ),
isTicketed: PropTypes.bool,
postCount: PropTypes.number,
setActiveEvent: PropTypes.func.isRequired, setActiveEvent: PropTypes.func.isRequired,
showFrom: PropTypes.string.isRequired, showFrom: PropTypes.string.isRequired,
showUntil: PropTypes.string.isRequired, showUntil: PropTypes.string.isRequired,
startTime: PropTypes.string.isRequired, start: PropTypes.string.isRequired,
tagline: PropTypes.string, tagline: PropTypes.string,
title: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
}; };
} }
@@ -45,18 +36,22 @@ export default class EventListItem extends Component {
} }
_viewEventDetail = () => { _viewEventDetail = () => {
const { id } = this.props.details; this.props.setActiveEvent(this.props.id);
this.props.setActiveEvent(id);
this.props.navigation.navigate('Event'); this.props.navigation.navigate('Event');
} };
render() { render() {
const { const { date, description, end, name, start } = this.props;
} = this.props;
return ( return (
<TouchableOpacity onPress={this._viewEventDetail}> <TouchableOpacity onPress={this._viewEventDetail}>
<View style={styles.rowContainer}> <View style={styles.rowContainer}>
<Text>{name}</Text>
<Text>{date}</Text>
<Text>
{start} - {end}
</Text>
<Text>{description}</Text>
</View> </View>
</TouchableOpacity> </TouchableOpacity>
); );
@@ -76,7 +71,7 @@ const styles = StyleSheet.create({
shadowColor: '#CCC', shadowColor: '#CCC',
shadowOffset: { shadowOffset: {
width: 1, width: 1,
height: 1 height: 1,
}, },
shadowOpacity: 1.0, shadowOpacity: 1.0,
shadowRadius: 1, shadowRadius: 1,

View File

@@ -16,4 +16,7 @@ const mapDispatchToProps = (dispatch) => ({
doSuccessAction: (result) => dispatch(facebookLoginSuccess(result)), doSuccessAction: (result) => dispatch(facebookLoginSuccess(result)),
}); });
export default connect(null, mapDispatchToProps)(FacebookLogin); export default connect(
null,
mapDispatchToProps,
)(FacebookLogin);

View File

@@ -11,13 +11,11 @@ export default function FacebookLogin({
doLogoutAction, doLogoutAction,
doSuccessAction, doSuccessAction,
}) { }) {
return ( return (
<View> <View>
<LoginButton <LoginButton
publishPermissions={PERMISSIONS.FACEBOOK} publishPermissions={PERMISSIONS.FACEBOOK}
onLoginFinished={ onLoginFinished={(error, result) => {
(error, result) => {
if (error) { if (error) {
doErrorAction(error); doErrorAction(error);
} else if (result.isCancelled) { } else if (result.isCancelled) {
@@ -25,8 +23,7 @@ export default function FacebookLogin({
} else { } else {
doSuccessAction(result); doSuccessAction(result);
} }
} }}
}
onLogoutFinished={doLogoutAction} onLogoutFinished={doLogoutAction}
/> />
</View> </View>

View File

@@ -8,4 +8,7 @@ const mapDispatchToProps = (dispatch) => ({
doLoginAction: (username, password) => dispatch(login(username, password)), doLoginAction: (username, password) => dispatch(login(username, password)),
}); });
export default connect(null, mapDispatchToProps)(LocalLogin); export default connect(
null,
mapDispatchToProps,
)(LocalLogin);

View File

@@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import { Button, TextInput, View } from 'react-native'; import { Button, TextInput, View } from 'react-native';
export default function LocalLogin({ doLoginAction }) { export default function LocalLogin({ doLoginAction }) {
const [enabled, setEnableSubmit] = useState(false); const [enabled, setEnableSubmit] = useState(false);
const [password, setPassword] = useState(null); const [password, setPassword] = useState(null);
const [username, setUsername] = useState(null); const [username, setUsername] = useState(null);
@@ -41,11 +40,7 @@ export default function LocalLogin({ doLoginAction }) {
onChangeText={(text) => _updateState('password', text)} onChangeText={(text) => _updateState('password', text)}
value={password} value={password}
/> />
<Button <Button disabled={!enabled} onPress={_handleLoginSubmit} title="Login" />
disabled={!enabled}
onPress={_handleLoginSubmit}
title="Login"
/>
</View> </View>
); );
} }

View File

@@ -25,5 +25,7 @@ const mapDispatchToProps = (dispatch) => ({
placeBid: (data) => dispatch(placeBid(data)), placeBid: (data) => dispatch(placeBid(data)),
}); });
export default connect(mapStateToProps, null)(AuctionListItem); export default connect(
mapStateToProps,
null,
)(AuctionListItem);

View File

@@ -13,4 +13,7 @@ function mapStateToProps(state, ownProps) {
}; };
} }
export default connect(mapStateToProps, null)(AuctionPriceAndBidCount); export default connect(
mapStateToProps,
null,
)(AuctionPriceAndBidCount);

View File

@@ -13,4 +13,7 @@ function mapStateToProps(state, ownProps) {
}; };
} }
export default connect(mapStateToProps, null)(AuctionPriceAndBidCount); export default connect(
mapStateToProps,
null,
)(AuctionPriceAndBidCount);

View File

@@ -16,4 +16,7 @@ const mapDispatchToProps = (dispatch) => ({
fetchEvents: () => dispatch(fetchEvents(dispatch)), fetchEvents: () => dispatch(fetchEvents(dispatch)),
}); });
export default connect(matchStateToProps, mapDispatchToProps)(Events); export default connect(
matchStateToProps,
mapDispatchToProps,
)(Events);

View File

@@ -25,5 +25,7 @@ const mapDispatchToProps = (dispatch) => ({
setActiveEvent: (eventId) => dispatch(setActiveEvent(eventId)), setActiveEvent: (eventId) => dispatch(setActiveEvent(eventId)),
}); });
export default connect(mapStateToProps, null)(AuctionListItem); export default connect(
mapStateToProps,
null,
)(AuctionListItem);

View File

@@ -24,7 +24,7 @@ export default class Event extends Record({
return false; return false;
} }
return this.ticketClasses.find(t => t.available > 0) || false; return this.ticketClasses.find((t) => t.available > 0) || false;
} }
} }
@@ -33,7 +33,7 @@ Event.fromJS = (data = {}) => {
id: data._id, id: data._id,
...data, ...data,
images: new List(data.images), images: new List(data.images),
posts: new List(data.posts.map(p => Post.fromJS(p))), posts: new List(data.posts.map((p) => Post.fromJS(p))),
ticketClasses: new List(data.ticketClasses.map(t => TicketClass.fromJS(t))), ticketClasses: new List(data.ticketClasses.map((t) => TicketClass.fromJS(t))),
}); });
}; };

View File

@@ -9,8 +9,7 @@ export default class Post extends Record({
sendNotification: false, sendNotification: false,
timestamp: null, timestamp: null,
title: null, title: null,
}) {}; }) {}
Post.fromJS = (data = {}) => { Post.fromJS = (data = {}) => {
return new Post({ return new Post({

View File

@@ -29,8 +29,12 @@ export default class Profile extends Record({
} }
get isRegisteredAccount() { get isRegisteredAccount() {
return this.hasLinkedApple || return (
this.hasLinkedFacebook || this.hasLinkedGoogle || this.hasLocalAccount; this.hasLinkedApple ||
this.hasLinkedFacebook ||
this.hasLinkedGoogle ||
this.hasLocalAccount
);
} }
} }

View File

@@ -11,7 +11,7 @@ export default class TicketClass extends Record({
startSale: null, startSale: null,
}) { }) {
get isAlmostGone() { get isAlmostGone() {
return this.available < (this.capacity * 0.20); return this.available < this.capacity * 0.2;
} }
get isSoldOut() { get isSoldOut() {

View File

@@ -1,7 +1,9 @@
import { SET_ACTIVE_EVENT, UNSET_ACTIVE_EVENT } from '../constants/actionTypes.js'; import { EVENTS_LOADED, SET_ACTIVE_EVENT, UNSET_ACTIVE_EVENT } from '../constants/actionTypes.js';
export const activeEvent = (state = null, action) => { export const activeEvent = (state = null, action) => {
switch (action.type) { switch (action.type) {
case EVENTS_LOADED:
return action.payload.size === 1 ? action.payload.get(0).get('id') : null;
case SET_ACTIVE_EVENT: case SET_ACTIVE_EVENT:
return action.payload; return action.payload;
case UNSET_ACTIVE_EVENT: case UNSET_ACTIVE_EVENT:

View File

@@ -1,9 +1,6 @@
import { Map } from 'immutable'; import { Map } from 'immutable';
import { import { GET_ITEMS, ITEMS_LOADED } from '../constants/actionTypes.js';
GET_ITEMS,
ITEMS_LOADED,
} from '../constants/actionTypes.js';
export const items = (state = new Map(), action) => { export const items = (state = new Map(), action) => {
switch (action.type) { switch (action.type) {

View File

@@ -16,37 +16,6 @@ import Profile from './screens/Profile.container.js';
import Register from './screens/Register.js'; import Register from './screens/Register.js';
import SignInOrRegister from './screens/SignInOrRegister.js'; import SignInOrRegister from './screens/SignInOrRegister.js';
export const Tabs = createBottomTabNavigator({
'Event': {
screen: Event,
navigationOptions: {
tabBarLabel: 'Event',
tabBarIcon: ({ tintColor }) => <Icon name="black-tie" type="font-awesome" size={28} color={tintColor} />,
},
},
'Auction': {
screen: Auction,
navigationOptions: {
tabBarLabel: 'Silent Auction',
tabBarIcon: ({ tintColor }) => <Icon name="gavel" type="font-awesome" size={28} color={tintColor} />,
},
},
'Bazaar': {
screen: Marketplace,
navigationOptions: {
tabBarLabel: 'Bazaar',
tabBarIcon: ({ tintColor }) => <Icon name="store" type="fontisto" size={28} color={tintColor} />,
},
},
'Profile': {
screen: Profile,
navigationOptions: {
tabBarLabel: 'Profile',
tabBarIcon: ({ tintColor }) => <Icon name="ios-person" type="font-awesome" size={28} color={tintColor} />,
},
},
});
export const SignInOrRegisterStack = createStackNavigator({ export const SignInOrRegisterStack = createStackNavigator({
SignInOrRegister: { SignInOrRegister: {
screen: SignInOrRegister, screen: SignInOrRegister,
@@ -132,7 +101,54 @@ export const EventsStack = createStackNavigator({
tabBarVisible: false, tabBarVisible: false,
gesturesEnabled: false, gesturesEnabled: false,
}), }),
} },
Event: {
screen: Event,
navigationOptions: ({ navigation }) => ({
header: <AppHeader navigation={navigation} />,
tabBarVisible: false,
gesturesEnabled: false,
}),
},
});
export const Tabs = createBottomTabNavigator({
Event: {
screen: EventsStack,
navigationOptions: {
tabBarLabel: 'Event',
tabBarIcon: ({ tintColor }) => (
<Icon name="black-tie" type="font-awesome" size={28} color={tintColor} />
),
},
},
Auction: {
screen: AuctionStack,
navigationOptions: {
tabBarLabel: 'Silent Auction',
tabBarIcon: ({ tintColor }) => (
<Icon name="gavel" type="font-awesome" size={28} color={tintColor} />
),
},
},
Bazaar: {
screen: BazaarStack,
navigationOptions: {
tabBarLabel: 'Bazaar',
tabBarIcon: ({ tintColor }) => (
<Icon name="store" type="fontisto" size={28} color={tintColor} />
),
},
},
Profile: {
screen: Profile,
navigationOptions: {
tabBarLabel: 'Profile',
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-person" type="font-awesome" size={28} color={tintColor} />
),
},
},
}); });
export const createRootNavigator = () => { export const createRootNavigator = () => {
@@ -142,29 +158,35 @@ export const createRootNavigator = () => {
screen: AuctionStack, screen: AuctionStack,
navigationOptions: { navigationOptions: {
gesturesEnabled: false, gesturesEnabled: false,
} },
}, },
BazaarStack: { BazaarStack: {
screen: BazaarStack, screen: BazaarStack,
navigationOptions: { navigationOptions: {
gesturesEnabled: false, gesturesEnabled: false,
} },
}, },
EventsStack: { EventsStack: {
screen: EventsStack, screen: EventsStack,
navigationOptions: { navigationOptions: {
gesturesEnabled: false, gesturesEnabled: false,
} },
},
SignInOrRegisterStack: {
screen: SignInOrRegister,
navigationOptions: {
gesturesEnabled: false,
},
}, },
Tabs: { Tabs: {
screen: Tabs, screen: Tabs,
navigationOptions: { navigationOptions: {
gesturesEnabled: false, gesturesEnabled: false,
} },
} },
}, },
{ {
mode: "modal", mode: 'modal',
} },
); );
}; };

View File

@@ -20,4 +20,7 @@ const mapDispatchToProps = (dispatch) => ({
fetchStatus: () => dispatch(fetchAuctionStatus(dispatch)), fetchStatus: () => dispatch(fetchAuctionStatus(dispatch)),
}); });
export default connect(matchStateToProps, mapDispatchToProps)(Auction); export default connect(
matchStateToProps,
mapDispatchToProps,
)(Auction);

View File

@@ -2,11 +2,7 @@ import { List } from 'immutable';
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { FlatList, Text, View } from 'react-native';
FlatList,
Text,
View,
} from 'react-native';
import { SORT_MODES, AUCTION_VIEW_MODES } from '../constants/constants.js'; import { SORT_MODES, AUCTION_VIEW_MODES } from '../constants/constants.js';
@@ -22,16 +18,15 @@ export default class Auction extends Component {
changeViewMode: PropTypes.func.isRequired, changeViewMode: PropTypes.func.isRequired,
fetchItems: PropTypes.func.isRequired, fetchItems: PropTypes.func.isRequired,
fetchStatus: PropTypes.func.isRequired, fetchStatus: PropTypes.func.isRequired,
items: PropTypes.oneOfType([ items: PropTypes.oneOfType([PropTypes.array, PropTypes.instanceOf(List)]),
PropTypes.array,
PropTypes.instanceOf(List),
]),
}; };
} }
static get defaultProps() { static get defaultProps() {
return { return {
changeFilter: () => { console.log('Change Filter Default Prop', arguments); }, changeFilter: () => {
console.log('Change Filter Default Prop', arguments);
},
items: [], items: [],
}; };
} }
@@ -57,7 +52,11 @@ export default class Auction extends Component {
this.props.changeFilter('auction', filter); this.props.changeFilter('auction', filter);
} }
_keyExtractor = (item, index) => `${item._id}_${index}`; changeViewMode(viewMode) {
this.props.changeViewMode(viewMode);
}
_keyExtractor = (item, index) => `${item.id}_${index}`;
_renderAuctionListItem = ({ item }) => <AuctionListItem item={item} />; _renderAuctionListItem = ({ item }) => <AuctionListItem item={item} />;
@@ -69,6 +68,7 @@ export default class Auction extends Component {
<View style={styles.container}> <View style={styles.container}>
<FilterBar <FilterBar
changeFilterer={this.changeFilter} changeFilterer={this.changeFilter}
changeViewMode={this.changeViewMode}
/> />
{items.size > 0 && ( {items.size > 0 && (
<FlatList <FlatList

View File

@@ -1,6 +1,6 @@
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({ export default (styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
@@ -14,4 +14,4 @@ export const styles = StyleSheet.create({
alignItems: 'stretch', alignItems: 'stretch',
justifyContent: 'flex-start', justifyContent: 'flex-start',
}, },
}); }));

View File

@@ -1,17 +1,11 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { import { StyleSheet, Text, View } from 'react-native';
StyleSheet,
Text,
View,
} from 'react-native';
export default class Checkout extends Component { export default class Checkout extends Component {
render() { render() {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.title}> <Text style={styles.title}>Checkout</Text>
Checkout
</Text>
</View> </View>
); );
} }
@@ -28,5 +22,5 @@ const styles = StyleSheet.create({
fontSize: 20, fontSize: 20,
textAlign: 'center', textAlign: 'center',
margin: 10, margin: 10,
} },
}); });

View File

@@ -33,4 +33,7 @@ const matchStateToProps = (state) => {
const mapDispatchToProps = (dispatch) => ({}); const mapDispatchToProps = (dispatch) => ({});
export default connect(matchStateToProps, mapDispatchToProps)(Event); export default connect(
matchStateToProps,
mapDispatchToProps,
)(Event);

View File

@@ -33,11 +33,7 @@ export default class Event extends Component {
showUntil: PropTypes.string, showUntil: PropTypes.string,
startTime: PropTypes.string, startTime: PropTypes.string,
tagline: PropTypes.string, tagline: PropTypes.string,
ticketClasses: PropTypes.arrayOf( ticketClasses: PropTypes.arrayOf(PropTypes.shape({})),
PropTypes.shape({
}),
),
title: PropTypes.string, title: PropTypes.string,
url: PropTypes.string, url: PropTypes.string,
}; };
@@ -77,9 +73,7 @@ export default class Event extends Component {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.title}> <Text style={styles.title}>Event</Text>
Event
</Text>
</View> </View>
); );
} }

View File

@@ -1,6 +1,6 @@
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({ export default (styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
@@ -11,7 +11,5 @@ const styles = StyleSheet.create({
fontSize: 20, fontSize: 20,
textAlign: 'center', textAlign: 'center',
margin: 10, margin: 10,
} },
}); }));
export default styles;

View File

@@ -1,5 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { setActiveEvent } from '../actions/activeEvent.js';
import { fetchEvents } from '../actions/events.js'; import { fetchEvents } from '../actions/events.js';
import { getEventsAsList } from '../selectors/events.js'; import { getEventsAsList } from '../selectors/events.js';
@@ -7,13 +8,15 @@ import Events from './Events.js';
const matchStateToProps = (state) => { const matchStateToProps = (state) => {
const events = getEventsAsList(state); const events = getEventsAsList(state);
console.log('events:', events);
return { events }; return { events };
}; };
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
fetchEvents: () => dispatch(fetchEvents(dispatch)), fetchEvents: () => dispatch(fetchEvents()),
setActiveEvent: (eventId) => dispatch(setActiveEvent(eventId)),
}); });
export default connect(matchStateToProps, mapDispatchToProps)(Events); export default connect(
matchStateToProps,
mapDispatchToProps,
)(Events);

View File

@@ -1,31 +1,45 @@
import { List } from 'immutable';
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { FlatList, StyleSheet, Text, View } from 'react-native';
StyleSheet,
Text, import EventListItem from '../components/Events/EventListItem.js';
View,
} from 'react-native';
export default class Events extends Component { export default class Events extends Component {
static get propTypes() { static get propTypes() {
return { return {
events: PropTypes.array.isRequired, events: PropTypes.instanceOf(List),
fetchEvents: PropTypes.func.isRequired, fetchEvents: PropTypes.func.isRequired,
setActiveEvent: PropTypes.func.isRequired,
};
}
static get defaultProps() {
return {
events: new List(),
}; };
} }
constructor(props) { constructor(props) {
super(props); super(props);
this._setActiveEvent = this.setActiveEvent.bind(this);
} }
componentDidMount() { componentDidMount() {
this.props.fetchEvents(); this.props.fetchEvents();
} }
_keyExtractor = (event, index) => `${event._id}_${index}`; setActiveEvent(eventId) {
this.props.setActiveEvent(eventId);
}
_renderEventListItem = ({ event }) => <EventListItem event={event} />; _keyExtractor = (event, index) => `${event.id}_${index}`;
_renderEventListItem = ({ event }) => (
<EventListItem {...event} setActiveEvent={this.setActiveEvent} />
);
render() { render() {
const { events } = this.props; const { events } = this.props;
@@ -53,6 +67,5 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
backgroundColor: '#F5FCFF', backgroundColor: '#F5FCFF',
}, },
eventListContentContainer: { eventListContentContainer: {},
},
}); });

View File

@@ -1,17 +1,11 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { import { StyleSheet, Text, View } from 'react-native';
StyleSheet,
Text,
View,
} from 'react-native';
export default class ImageDetail extends Component { export default class ImageDetail extends Component {
render() { render() {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.title}> <Text style={styles.title}>Item</Text>
Item
</Text>
</View> </View>
); );
} }
@@ -28,5 +22,5 @@ const styles = StyleSheet.create({
fontSize: 20, fontSize: 20,
textAlign: 'center', textAlign: 'center',
margin: 10, margin: 10,
} },
}); });

View File

@@ -1,17 +1,11 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { import { StyleSheet, Text, View } from 'react-native';
StyleSheet,
Text,
View,
} from 'react-native';
export default class Item extends Component { export default class Item extends Component {
render() { render() {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.title}> <Text style={styles.title}>Item</Text>
Item
</Text>
</View> </View>
); );
} }
@@ -28,5 +22,5 @@ const styles = StyleSheet.create({
fontSize: 20, fontSize: 20,
textAlign: 'center', textAlign: 'center',
margin: 10, margin: 10,
} },
}); });

View File

@@ -1,17 +1,11 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { import { StyleSheet, Text, View } from 'react-native';
StyleSheet,
Text,
View,
} from 'react-native';
export default class Login extends Component { export default class Login extends Component {
render() { render() {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.title}> <Text style={styles.title}>Login</Text>
Login
</Text>
</View> </View>
); );
} }
@@ -28,5 +22,5 @@ const styles = StyleSheet.create({
fontSize: 20, fontSize: 20,
textAlign: 'center', textAlign: 'center',
margin: 10, margin: 10,
} },
}); });

View File

@@ -2,11 +2,7 @@ import { List } from 'immutable';
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { FlatList, Text, View } from 'react-native';
FlatList,
Text,
View,
} from 'react-native';
import { SORT_MODES, AUCTION_VIEW_MODES } from '../constants/constants.js'; import { SORT_MODES, AUCTION_VIEW_MODES } from '../constants/constants.js';
@@ -22,16 +18,15 @@ export default class Marketplace extends Component {
changeViewMode: PropTypes.func.isRequired, changeViewMode: PropTypes.func.isRequired,
fetchItems: PropTypes.func.isRequired, fetchItems: PropTypes.func.isRequired,
fetchStatus: PropTypes.func.isRequired, fetchStatus: PropTypes.func.isRequired,
items: PropTypes.oneOfType([ items: PropTypes.oneOfType([PropTypes.array, PropTypes.instanceOf(List)]),
PropTypes.array,
PropTypes.instanceOf(List),
]),
}; };
} }
static get defaultProps() { static get defaultProps() {
return { return {
changeFilter: () => { console.log('Change Filter Default Prop', arguments); }, changeFilter: () => {
console.log('Change Filter Default Prop', arguments);
},
items: [], items: [],
}; };
} }
@@ -67,9 +62,7 @@ export default class Marketplace extends Component {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<FilterBar <FilterBar changeFilterer={this.changeFilter} />
changeFilterer={this.changeFilter}
/>
{items.size > 0 && ( {items.size > 0 && (
<FlatList <FlatList
data={items} data={items}

View File

@@ -29,4 +29,7 @@ const mapDispatchToProps = (dispatch) => ({
updateProfile: () => dispatch(updateProfile(dispatch)), updateProfile: () => dispatch(updateProfile(dispatch)),
}); });
export default connect(matchStateToProps, mapDispatchToProps)(Profile); export default connect(
matchStateToProps,
mapDispatchToProps,
)(Profile);

View File

@@ -1,17 +1,11 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { import { StyleSheet, Text, View } from 'react-native';
StyleSheet,
Text,
View,
} from 'react-native';
export default class Profile extends Component { export default class Profile extends Component {
render() { render() {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.title}> <Text style={styles.title}>Profile</Text>
Profile
</Text>
</View> </View>
); );
} }
@@ -28,5 +22,5 @@ const styles = StyleSheet.create({
fontSize: 20, fontSize: 20,
textAlign: 'center', textAlign: 'center',
margin: 10, margin: 10,
} },
}); });

View File

@@ -1,10 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import { checkEmailAvailability, checkNomAvailability, registerUser } from '../actions/profile.js';
checkEmailAvailability,
checkNomAvailability,
registerUser,
} from '../actions/profile.js';
import Register from './Register.js'; import Register from './Register.js';
@@ -14,4 +10,7 @@ const mapDispatchToProps = (dispatch) => ({
doRegistration: (user) => dispatch(registerUser(user)), doRegistration: (user) => dispatch(registerUser(user)),
}); });
export default connect(null, mapDispatchToProps)(Register); export default connect(
null,
mapDispatchToProps,
)(Register);

View File

@@ -4,7 +4,6 @@ import { Text, View } from 'react-native';
import styles from './Register.styles.js'; import styles from './Register.styles.js';
export default class Register extends Component { export default class Register extends Component {
static get propTypes() { static get propTypes() {
return { return {
checkEmail: PropTypes.func.isRequired, checkEmail: PropTypes.func.isRequired,
@@ -49,7 +48,9 @@ export default class Register extends Component {
} }
_validateNomDeBid() { _validateNomDeBid() {
this.props.checkNomDeBid(this.state.nomDeBid, (valid) => this.setState('invalidNomDeBid', valid)); this.props.checkNomDeBid(this.state.nomDeBid, (valid) =>
this.setState('invalidNomDeBid', valid),
);
} }
getUserRegistration() { getUserRegistration() {
@@ -66,9 +67,16 @@ export default class Register extends Component {
} }
isFormComplete() { isFormComplete() {
return !this.state.invalidEmail && !this.state.invalidNomDeBid && return (
!!this.state.firstName && !!this.state.lastName && !!this.state.email && !this.state.invalidEmail &&
!!this.state.nomDeBid && !!this.state.phones.length && !!this.state.password; !this.state.invalidNomDeBid &&
!!this.state.firstName &&
!!this.state.lastName &&
!!this.state.email &&
!!this.state.nomDeBid &&
!!this.state.phones.length &&
!!this.state.password
);
} }
render() { render() {

View File

@@ -1,16 +1,12 @@
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({ export default (styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
flexDirection: 'column', flexDirection: 'column',
}, },
title: { title: {},
}, localLogin: {},
localLogin: { services: {},
}, register: {},
services: { }));
},
register: {
},
});

View File

@@ -8,7 +8,6 @@ import LocalLogin from '../components/Login/LocalLogin.container.js';
import styles from './SignInOrRegister.styles.js'; import styles from './SignInOrRegister.styles.js';
export default class SignInOrRegister extends Component { export default class SignInOrRegister extends Component {
constructor() { constructor() {
super(props); super(props);

View File

@@ -1,6 +1,6 @@
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({ export default (styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
@@ -11,5 +11,5 @@ export const styles = StyleSheet.create({
fontSize: 20, fontSize: 20,
textAlign: 'center', textAlign: 'center',
margin: 10, margin: 10,
} },
}); }));

View File

@@ -1,17 +1,11 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { import { StyleSheet, Text, View } from 'react-native';
StyleSheet,
Text,
View,
} from 'react-native';
export default class Ticketing extends Component { export default class Ticketing extends Component {
render() { render() {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.title}> <Text style={styles.title}>Ticketing</Text>
Ticketing
</Text>
</View> </View>
); );
} }
@@ -28,6 +22,5 @@ const styles = StyleSheet.create({
fontSize: 20, fontSize: 20,
textAlign: 'center', textAlign: 'center',
margin: 10, margin: 10,
} },
}); });

View File

@@ -6,9 +6,11 @@ export const getItemBidCount = (state, itemId) => state.getIn(['auctions', itemI
export const getItemPrice = (state, itemId) => state.getIn(['auctions', itemId, 'currentPrice'], 0); export const getItemPrice = (state, itemId) => state.getIn(['auctions', itemId, 'currentPrice'], 0);
export const isBiddingItem = (state, itemId) => state.getIn(['auctions', itemId, 'isBidding'], false); export const isBiddingItem = (state, itemId) =>
state.getIn(['auctions', itemId, 'isBidding'], false);
export const isWinningItem = (state, itemId) => state.getIn(['auctions', itemId, 'isWinning'], false); export const isWinningItem = (state, itemId) =>
state.getIn(['auctions', itemId, 'isWinning'], false);
export const getAuctionStatus = (state, itemId) => state.getIn(['actions', itemId], false); export const getAuctionStatus = (state, itemId) => state.getIn(['actions', itemId], false);
@@ -19,15 +21,15 @@ export const getAuctionStatuses = createSelector(
export const getItemsIdsWithNoBids = createSelector( export const getItemsIdsWithNoBids = createSelector(
[getAuctionStatuses], [getAuctionStatuses],
(auctions) => auctions.filter(auction => auction.bidCount === 0), (auctions) => auctions.filter((auction) => auction.bidCount === 0),
); );
export const getMyBidItemIds = createSelector( export const getMyBidItemIds = createSelector(
[getAuctionStatuses], [getAuctionStatuses],
(auctions) => auctions.filter(auction => auction.isBidding), (auctions) => auctions.filter((auction) => auction.isBidding),
); );
export const getMyWinningItemIds = createSelector( export const getMyWinningItemIds = createSelector(
[getAuctionStatuses], [getAuctionStatuses],
(auctions) => auctions.filter(auction => auction.isWinning), (auctions) => auctions.filter((auction) => auction.isWinning),
); );

View File

@@ -14,7 +14,7 @@ export const getEvents = createSelector(
export const getActiveEvent = createSelector( export const getActiveEvent = createSelector(
[getActiveEventId, getEvents], [getActiveEventId, getEvents],
(eventId, eventsAsMap) => eventId ? eventsAsMap.get(eventId) : null, (eventId, eventsAsMap) => (eventId ? eventsAsMap.get(eventId) : null),
); );
export const getDefaultEvent = createSelector( export const getDefaultEvent = createSelector(

View File

@@ -19,7 +19,7 @@ export const getItemsAsList = createSelector(
export const getAuctionItems = createSelector( export const getAuctionItems = createSelector(
[getState], [getState],
(state) => state.get('items').filter(i => i.type === 'auction') || new Map(), (state) => state.get('items').filter((i) => i.type === 'auction') || new Map(),
); );
export const getAuctionItemsAsList = createSelector( export const getAuctionItemsAsList = createSelector(
@@ -29,7 +29,7 @@ export const getAuctionItemsAsList = createSelector(
export const getAuctionItemsUserIsBidding = createSelector( export const getAuctionItemsUserIsBidding = createSelector(
[getAuctionItems, getMyBidItemIds], [getAuctionItems, getMyBidItemIds],
(items, myBids) => items.filter(i => myBids.indexOf(i.id)) || new Map(), (items, myBids) => items.filter((i) => myBids.indexOf(i.id)) || new Map(),
); );
export const getAuctionItemsUserIsBiddingAsList = createSelector( export const getAuctionItemsUserIsBiddingAsList = createSelector(
@@ -39,7 +39,7 @@ export const getAuctionItemsUserIsBiddingAsList = createSelector(
export const getAuctionItemsUserIsWinning = createSelector( export const getAuctionItemsUserIsWinning = createSelector(
[getAuctionItemsUserIsBidding, getMyWinningItemIds], [getAuctionItemsUserIsBidding, getMyWinningItemIds],
(items, myWins) => items.filter(i => myWins.indexOf(i.id)) || new Map(), (items, myWins) => items.filter((i) => myWins.indexOf(i.id)) || new Map(),
); );
export const getAuctionItemsUserIsWinningAsList = createSelector( export const getAuctionItemsUserIsWinningAsList = createSelector(
@@ -49,7 +49,7 @@ export const getAuctionItemsUserIsWinningAsList = createSelector(
export const getAuctionItemsWithNoBids = createSelector( export const getAuctionItemsWithNoBids = createSelector(
[getAuctionItems, getItemsIdsWithNoBids], [getAuctionItems, getItemsIdsWithNoBids],
(items, noBids) => items.filter(i => noBids.indexOf(i.id)) || new Map(), (items, noBids) => items.filter((i) => noBids.indexOf(i.id)) || new Map(),
); );
export const getAuctionItemsWithNoBidsAsList = createSelector( export const getAuctionItemsWithNoBidsAsList = createSelector(
@@ -59,7 +59,7 @@ export const getAuctionItemsWithNoBidsAsList = createSelector(
export const getTicketItems = createSelector( export const getTicketItems = createSelector(
[getState], [getState],
(state) => state.get('items').filter(i => i.type === 'ticket') || new Map(), (state) => state.get('items').filter((i) => i.type === 'ticket') || new Map(),
); );
export const getTicketItemsAsList = createSelector( export const getTicketItemsAsList = createSelector(

View File

@@ -5,10 +5,10 @@ import thunk from 'redux-thunk';
import rootReducer from '../reducers/index.js'; import rootReducer from '../reducers/index.js';
const composeEnhancers = composeWithDevTools({ port: 8000, realtime: true, suppressConnectErrors: false }); const composeEnhancers = composeWithDevTools({
port: 8000,
realtime: true,
suppressConnectErrors: false,
});
export const store = createStore( export const store = createStore(rootReducer, Map(), composeEnhancers(applyMiddleware(thunk)));
rootReducer,
Map(),
composeEnhancers(applyMiddleware(thunk)),
);

View File

@@ -9,6 +9,7 @@
}, },
"dependencies": { "dependencies": {
"@react-native-community/async-storage": "^1.6.1", "@react-native-community/async-storage": "^1.6.1",
"eslint-plugin-immutablejs": "^0.1.3",
"immutable": "^4.0.0-rc.12", "immutable": "^4.0.0-rc.12",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",