Skip to content

Commit

Permalink
[feature] Checkout Page Price Adjustments (#2366)
Browse files Browse the repository at this point in the history
* Initial

Signed-off-by: sirugh <[email protected]>

* Matches colump gap for coupon and gift card between input and button

Signed-off-by: sirugh <[email protected]>

* fix column css for mobile view

Signed-off-by: sirugh <[email protected]>

* Update styling to match new mock for gift card.
Makes input static and removes "add another" button.

* Updates tests

Signed-off-by: sirugh <[email protected]>

* Switch back to column - oops

Signed-off-by: sirugh <[email protected]>

* Cleanup tests and todos

Signed-off-by: sirugh <[email protected]>

* Add missing import

Signed-off-by: sirugh <[email protected]>

* Uses a more explicit error message when invalid coupon applied

* Removes hard coded color for coupon remove button

* Fix tests and snaps

Signed-off-by: sirugh <[email protected]>

* reset form after apply

Signed-off-by: sirugh <[email protected]>

* Add helpful comment

Signed-off-by: sirugh <[email protected]>

* Feedback

Signed-off-by: sirugh <[email protected]>

* fix test

Signed-off-by: sirugh <[email protected]>

* Fix lint

Signed-off-by: sirugh <[email protected]>

Co-authored-by: Devagouda <[email protected]>
  • Loading branch information
sirugh and dpatil-magento committed May 5, 2020
1 parent 46ca284 commit c1bc7a6
Show file tree
Hide file tree
Showing 18 changed files with 174 additions and 349 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const props = {
},
queries: {
cardBalanceQuery: 'mock balance',
cartQuery: 'mock cart'
appliedCardsQuery: 'mock cart'
}
};

Expand All @@ -105,7 +105,6 @@ test('it returns the proper shape', () => {
// Assert.
expect(log).toHaveBeenCalledWith({
applyGiftCard: expect.any(Function),
canTogglePromptState: expect.any(Boolean),
checkBalanceData: expect.any(Object),
checkGiftCardBalance: expect.any(Function),
errorLoadingGiftCards: expect.any(Boolean),
Expand All @@ -118,9 +117,7 @@ test('it returns the proper shape', () => {
removeGiftCard: expect.any(Function),
setFormApi: expect.any(Function),
shouldDisplayCardBalance: expect.any(Boolean),
shouldDisplayCardEntry: expect.any(Boolean),
shouldDisplayCardError: expect.any(Boolean),
submitForm: expect.any(Function),
togglePromptState: expect.any(Function)
submitForm: expect.any(Function)
});
});
101 changes: 27 additions & 74 deletions packages/peregrine/lib/talons/CartPage/GiftCards/useGiftCards.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,27 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useLazyQuery, useMutation } from '@apollo/react-hooks';

import { useCartContext } from '@magento/peregrine/lib/context/cart';

// The prompt is either actually showing the entry form or
// showing an "add" call to action button.
const promptStates = {
ADD: 'add',
ENTERING: 'entering'
};

// To keep track of the most recent action taken.
const actions = {
APPLY: 'apply',
CHECK_BALANCE: 'check',
REMOVE: 'remove',
TOGGLE: 'toggle'
REMOVE: 'remove'
};

const getPromptStateForNumCards = numCards =>
numCards === 0 ? promptStates.ENTERING : promptStates.ADD;

/**
* The useGiftCards talon handles effects for GiftCards and returns props necessary for rendering
* the GiftCards component.
*
* @param {Object} props
* @param {GraphQLAST} props.applyCardMutation - The mutation used to apply a gift card to the cart.
* @param {GraphQLAST} props.cardBalanceQuery - The query used to get the balance of a gift card.
* @param {GraphQLAST} props.cartQuery - The query used to get the gift cards currently applied to the cart.
* @param {GraphQLAST} props.appliedCardsQuery - The query used to get the gift cards currently applied to the cart.
* @param {GraphQLAST} props.removeCardMutation - The mutation used to remove a gift card from the cart.
*
* @returns {Object} result
* @returns {Function} result.applyGiftCard - A callback to apply a gift card to the cart.
* @returns {Boolean} result.canTogglePromptState - Whether the user should be allowed to switch the prompt state.
* @returns {Object} result.checkBalanceData - The giftCardAccount object of the most recent successful check balance GraphQL query.
* @returns {Function} result.checkGiftCardBalance - A callback to check the balance of a gift card.
* @returns {Boolean} result.errorLoadingGiftCards - Whether there was an error loading the cart's gift cards.
Expand All @@ -46,17 +34,15 @@ const getPromptStateForNumCards = numCards =>
* @returns {Boolean} result.isCheckingBalance - Whether the check gift card balance operation is in progress.
* @returns {Boolean} result.isRemovingCard - Whether the remove gift card operation is in progress.
* @returns {Function} result.removeGiftCard - A callback to remove a gift card from the cart.
* @returns {Boolean} result.shouldDisplayCardBalance - Whether to display the gift card balance to the user.
* @returns {Boolean} result.shouldDisplayCardEntry - Whether to display the gift card entry form.
* @returns {Boolean} result.shouldDisplayCardBalance - Whether to display the gift card balance to the user
* @returns {Boolean} result.shouldDisplayCardError - Whether to display an error message under the card input field.
* @returns {Function} result.submitForm - Submits the form to apply or check balance of the supplied gift card code.
* @returns {Function} result.togglePromptState - A callback to toggle the prompt state.
*/
export const useGiftCards = props => {
const {
setIsCartUpdating,
mutations: { applyCardMutation, removeCardMutation },
queries: { cardBalanceQuery, cartQuery }
queries: { appliedCardsQuery, cardBalanceQuery }
} = props;

// We need the cartId for all of our queries and mutations.
Expand All @@ -67,50 +53,31 @@ export const useGiftCards = props => {
*
* Immediately execute the cart query and set up the other graphql actions.
*/
const [getCartDetails, cartResult] = useLazyQuery(cartQuery);
const [getAppliedCards, appliedCardsResult] = useLazyQuery(
appliedCardsQuery
);
const [checkCardBalance, balanceResult] = useLazyQuery(cardBalanceQuery);
const [applyCard, applyCardResult] = useMutation(applyCardMutation);
const [removeCard, removeCardResult] = useMutation(removeCardMutation);

/*
* useMemo hooks / member variables.
*/
const numCards = useMemo(() => {
return cartResult.data
? cartResult.data.cart.applied_gift_cards.length
: Number.NEGATIVE_INFINITY;
}, [cartResult.data]);

const canTogglePromptState = numCards > 0;
const initialPromptState = getPromptStateForNumCards(numCards);

/*
* useState hooks.
*/
const [formApi, setFormApi] = useState();
const [mostRecentAction, setMostRecentAction] = useState(null);
const [promptState, setPromptState] = useState(initialPromptState);

/*
* useEffect hooks.
*/
// Fire the getCartDetails query immediately and whenever cartId changes.
// Fire the getAppliedCards query immediately and whenever cartId changes.
useEffect(() => {
if (!cartId) {
return;
if (cartId) {
getAppliedCards({
fetchPolicy: 'cache-and-network',
variables: { cartId }
});
}

getCartDetails({
fetchPolicy: 'cache-and-network',
variables: { cartId }
});
}, [cartId, getCartDetails]);

// Update the prompt state whenever the number of cards changes.
useEffect(() => {
const targetPromptState = getPromptStateForNumCards(numCards);
setPromptState(targetPromptState);
}, [numCards]);
}, [cartId, getAppliedCards]);

// Submit the form after the apply or check balance actions are taken.
useEffect(() => {
Expand Down Expand Up @@ -172,16 +139,19 @@ export const useGiftCards = props => {
);

const submitForm = useCallback(
values => {
async values => {
const giftCardCode = values['card'];

if (mostRecentAction === actions.APPLY) {
applyCard({
await applyCard({
variables: {
cartId,
giftCardCode
}
});

// Clear the input form after successful apply.
formApi.reset();
}

if (mostRecentAction === actions.CHECK_BALANCE) {
Expand All @@ -193,25 +163,9 @@ export const useGiftCards = props => {
});
}
},
[applyCard, cartId, checkCardBalance, mostRecentAction]
[applyCard, cartId, checkCardBalance, formApi, mostRecentAction]
);

const togglePromptState = useCallback(() => {
setPromptState(prevState => {
switch (prevState) {
case promptStates.ADD: {
return promptStates.ENTERING;
}
case promptStates.ENTERING:
default: {
return promptStates.ADD;
}
}
});

setMostRecentAction(actions.TOGGLE);
}, []);

const errorApplyingCard = Boolean(applyCardResult.error);
const errorCheckingBalance = Boolean(balanceResult.error);
const shouldDisplayCardBalance =
Expand Down Expand Up @@ -245,24 +199,23 @@ export const useGiftCards = props => {

return {
applyGiftCard,
canTogglePromptState,
checkBalanceData:
balanceResult.data && balanceResult.data.giftCardAccount,
checkGiftCardBalance,
errorLoadingGiftCards: Boolean(cartResult.error),
errorLoadingGiftCards: Boolean(appliedCardsResult.error),
errorRemovingCard: Boolean(removeCardResult.error),
giftCardsData:
(cartResult.data && cartResult.data.cart.applied_gift_cards) || [],
isLoadingGiftCards: cartResult.loading,
(appliedCardsResult.data &&
appliedCardsResult.data.cart.applied_gift_cards) ||
[],
isLoadingGiftCards: appliedCardsResult.loading,
isApplyingCard: applyCardLoading,
isCheckingBalance: balanceResult.loading,
isRemovingCard: removeCardLoading,
removeGiftCard,
setFormApi,
shouldDisplayCardBalance,
shouldDisplayCardEntry: promptState === promptStates.ENTERING,
shouldDisplayCardError,
submitForm,
togglePromptState
submitForm
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,24 @@ export const useCouponCode = props => {
setIsCartUpdating
]);

let applyErrorMessage;

if (applyError) {
if (applyError.graphQLErrors) {
// Apollo prepends "GraphQL Error:" onto the message,
// which we don't want to show to an end user.
// Build up the error message manually without the prepended text.
applyErrorMessage = applyError.graphQLErrors
.map(({ message }) => message)
.join(', ');
} else {
// A non-GraphQL error occurred.
applyErrorMessage - applyError.message;
}
}

return {
applyError,
applyError: applyErrorMessage,
applyingCoupon,
data,
fetchError,
Expand Down
Loading

0 comments on commit c1bc7a6

Please sign in to comment.