Skip to content

Commit

Permalink
Add toast notifications for favoriting actions (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjoyce91 authored and burgwyn committed Mar 20, 2019
1 parent 5b698ad commit dd98443
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 17 deletions.
24 changes: 22 additions & 2 deletions src/Components/Favorite/Favorite.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,26 @@ class Favorite extends Component {
};
}

componentWillReceiveProps(nextProps) {
this.setState({ loading: nextProps.isLoading });
shouldComponentUpdate(nextProps, nextState) {
let isUpdate = true;

const { compareArray, refKey } = nextProps;
const oldState = this.getSavedState();
const newState = existsInArray(refKey, compareArray);

if (this.state.loading && !nextProps.isLoading) {
// Only update the loading state if current state.loading
// and prop change detected is turning it off
this.setState({
loading: nextProps.isLoading,
});
}

isUpdate = (oldState !== newState) ||
(this.state.loading !== nextState.isLoading) ||
nextProps.hasErrored;

return isUpdate;
}

getSavedState() {
Expand Down Expand Up @@ -177,6 +195,7 @@ Favorite.propTypes = {
hideText: PropTypes.bool,
compareArray: FAVORITE_POSITIONS_ARRAY.isRequired,
isLoading: PropTypes.bool,
hasErrored: PropTypes.bool,
hasBorder: PropTypes.bool,
useLongText: PropTypes.bool,
useButtonClass: PropTypes.bool,
Expand All @@ -190,6 +209,7 @@ Favorite.defaultProps = {
as: 'div',
hideText: false,
isLoading: false,
hasErrored: false,
compareArray: [],
hasBorder: false,
useLongText: false,
Expand Down
13 changes: 13 additions & 0 deletions src/Components/FavoriteMessages/Success.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { POSITION_DETAILS } from '../../Constants/PropTypes';

const Success = ({ pos }) => (
<span>{pos.title} ({pos.position_number}) has been successfully added to Favorites. <Link to="/profile/favorites/">Go to Favorites</Link>.</span>
);

Success.propTypes = {
pos: POSITION_DETAILS.isRequired,
};

export default Success;
11 changes: 11 additions & 0 deletions src/Components/FavoriteMessages/Success.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { shallow } from 'enzyme';
import React from 'react';
import Success from './Success';
import detailsObject from '../../__mocks__/detailsObject';

describe('Success', () => {
it('is defined', () => {
const wrapper = shallow(<Success pos={detailsObject} />);
expect(wrapper).toBeDefined();
});
});
10 changes: 10 additions & 0 deletions src/Constants/SystemMessages.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import FavoriteSuccess from '../Components/FavoriteMessages/Success';

export const DEFAULT_TEXT = 'None listed';

export const NO_ASSIGNMENT_DATE = DEFAULT_TEXT;
Expand Down Expand Up @@ -37,6 +39,14 @@ export const DELETE_BID_ITEM_ERROR = 'Error trying to delete this bid.';
export const ADD_BID_ITEM_SUCCESS = 'Bid successfully added.';
export const ADD_BID_ITEM_ERROR = 'Error trying to add this bid.';

export const ADD_FAVORITE_TITLE = 'Favorite Added';
export const DELETE_FAVORITE_TITLE = 'Favorite Removed';
export const ERROR_FAVORITE_TITLE = 'Favorite Error';
export const DELETE_FAVORITE_SUCCESS = pos => `${pos.title} (${pos.position_number}) has been successfully removed from favorites.`;
export const DELETE_FAVORITE_ERROR = () => "We're experiencing an error attemtping to remove this position to your Favorites. Please try again.";
export const ADD_FAVORITE_SUCCESS = pos => FavoriteSuccess({ pos });
export const ADD_FAVORITE_ERROR = () => "We're experiencing an error attemtping to add this position to your Favorites. Please try again.";

export const ACCEPT_BID_SUCCESS = 'Bid successfully accepted.';
export const ACCEPT_BID_ERROR = 'Error trying to accept this bid.';
export const DECLINE_BID_SUCCESS = 'Bid successfully declined.';
Expand Down
14 changes: 8 additions & 6 deletions src/Containers/Toast/Toast.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ export class Toast extends Component {
}
}

notify({ type = 'success', message = 'Message' }) { // eslint-disable-line
let title;
if (type === 'success') { title = 'Success'; }
if (type === 'error') { title = 'Error'; }
notify({ type = 'success', message = 'Message', title = '' }) { // eslint-disable-line
let title$;
if (type === 'success') { title$ = 'Success'; }
if (type === 'error') { title$ = 'Error'; }
if (title) { title$ = title; }
toast[type](
<Alert type={type} title={title} messages={[{ body: message }]} />,
<Alert type={type} title={title$} messages={[{ body: message }]} />,
);
}

Expand All @@ -36,7 +37,8 @@ export class Toast extends Component {
Toast.propTypes = {
toastData: PropTypes.shape({
type: PropTypes.string,
message: PropTypes.string,
message: PropTypes.node,
title: PropTypes.string,
}),
};

Expand Down
6 changes: 4 additions & 2 deletions src/actions/toast.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
export function toastSuccess(toast) {
export function toastSuccess(toast, title) {
return {
type: 'TOAST_NOTIFICATION_SUCCESS',
toast,
title,
};
}

export function toastError(toast) {
export function toastError(toast, title) {
return {
type: 'TOAST_NOTIFICATION_ERROR',
toast,
title,
};
}
29 changes: 25 additions & 4 deletions src/actions/userProfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { indexOf } from 'lodash';

import api from '../api';
import { favoritePositionsFetchData } from './favoritePositions';
import { toastSuccess, toastError } from './toast';
import * as SystemMessages from '../Constants/SystemMessages';

export function userProfileHasErrored(bool) {
return {
Expand Down Expand Up @@ -110,21 +112,40 @@ export function userProfileToggleFavoritePosition(id, remove, refreshFavorites =
url: `/position/${idString}/favorite/`,
};

/**
* create functions for creating the action and fetching position data to supply to message
*/
// action
const getAction = () => api(config);

// position
const getPosition = () => api.get(`/position/${id}/`);

dispatch(userProfileFavoritePositionIsLoading(true, id));
dispatch(userProfileFavoritePositionHasErrored(false));

api(config)
.then(() => {
axios.all([getAction(), getPosition()])
.then(axios.spread((action, position) => {
const pos = position.data;
const message = remove ?
SystemMessages.DELETE_FAVORITE_SUCCESS(pos) : SystemMessages.ADD_FAVORITE_SUCCESS(pos);
const title = remove ? SystemMessages.DELETE_FAVORITE_TITLE
: SystemMessages.ADD_FAVORITE_TITLE;
const cb = () => userProfileFavoritePositionIsLoading(false, id);
dispatch(userProfileFetchData(true, cb));
dispatch(userProfileFavoritePositionHasErrored(false));
dispatch(toastSuccess(message, title));
if (refreshFavorites) {
dispatch(favoritePositionsFetchData());
}
})
}))
.catch(() => {
dispatch(userProfileFavoritePositionHasErrored(true));
const message = remove ?
SystemMessages.DELETE_FAVORITE_ERROR() : SystemMessages.ADD_FAVORITE_ERROR();
const title = SystemMessages.ERROR_FAVORITE_TITLE;
dispatch(userProfileFavoritePositionIsLoading(false, id));
dispatch(userProfileFavoritePositionHasErrored(true));
dispatch(toastError(message, title));
});
};
}
6 changes: 3 additions & 3 deletions src/reducers/toast/toast.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export default function toast(state = { type: 'success', message: '' }, action) {
export default function toast(state = { type: 'success', message: '', title: '' }, action) {
switch (action.type) {
case 'TOAST_NOTIFICATION_SUCCESS':
return { type: 'success', message: action.toast };
return { type: 'success', message: action.toast, title: action.title };
case 'TOAST_NOTIFICATION_ERROR':
return { type: 'error', message: action.toast };
return { type: 'error', message: action.toast, title: action.title };
default:
return state;
}
Expand Down

0 comments on commit dd98443

Please sign in to comment.