Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saved payment methods main view. #2882

Merged
merged 34 commits into from
Dec 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2af3f7a
Enabled saved payments link.
revanth0212 Nov 18, 2020
2c505ae
Added payment skeleton.
revanth0212 Nov 18, 2020
b90fe86
Moved stuff around.
revanth0212 Nov 23, 2020
e295112
Snapshot update.
revanth0212 Nov 23, 2020
4098a4c
Added other card types.
revanth0212 Nov 23, 2020
6ac74aa
Cleaned up some css.
revanth0212 Nov 30, 2020
e294ac8
Using INTL.
revanth0212 Nov 30, 2020
7c73950
Minor.
revanth0212 Nov 30, 2020
b1d7f04
Minor css change.
revanth0212 Nov 30, 2020
3a1c7fe
Changed name of payments target to checkoutPagePaymentTypes.
revanth0212 Dec 1, 2020
721a521
Added savedPaymentTypes target.
revanth0212 Dec 1, 2020
e586dbc
Updated target docs.
revanth0212 Dec 1, 2020
8eb9f2c
Minor.
revanth0212 Dec 2, 2020
27234d2
Merge remote-tracking branch 'origin/develop' into revanth/saved_paym…
revanth0212 Dec 2, 2020
6a35ae6
Hide delete text in mobile view.
revanth0212 Dec 3, 2020
d3ea89e
Address PR feedback
tjwiebell Dec 9, 2020
133131c
Snapshot updates.
revanth0212 Dec 15, 2020
229aa67
Merge remote-tracking branch 'origin/develop' into revanth/saved_paym…
revanth0212 Dec 15, 2020
4b85318
Updated snapshots.
revanth0212 Dec 15, 2020
a6d5603
Updated tests.
revanth0212 Dec 15, 2020
b6a62ba
Added new tests.
revanth0212 Dec 15, 2020
1b483cb
Minor
revanth0212 Dec 15, 2020
e00d30d
Hiding delete button till PWA-638 comes in.
revanth0212 Dec 15, 2020
33677e8
Added new tests.
revanth0212 Dec 15, 2020
71a4f64
Minor.
revanth0212 Dec 16, 2020
0320f7f
Merge branch 'develop' into revanth/saved_payment_methods_main_view
dpatil-magento Dec 16, 2020
59672a4
Rendering no payments message.
revanth0212 Dec 16, 2020
9634eed
Clear CustomerPaymentTokens on signout.
revanth0212 Dec 16, 2020
ca5f94a
Rendering fullpageindicator when data is loading.
revanth0212 Dec 16, 2020
e2ab10c
Merge branch 'develop' into revanth/saved_payment_methods_main_view
dpatil-magento Dec 16, 2020
7282748
Snapshot update.
revanth0212 Dec 16, 2020
cfef3f9
Merge branch 'revanth/saved_payment_methods_main_view' of https://git…
revanth0212 Dec 16, 2020
a6a7e18
Merge branch 'develop' into revanth/saved_payment_methods_main_view
dpatil-magento Dec 16, 2020
a607400
Removing unnecessary piece of code.
revanth0212 Dec 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ Object {
},
},
},
"CustomerPaymentTokens": Object {
"keyFields": [Function],
},
"ProductImage": Object {
"keyFields": Array [
"url",
Expand Down
3 changes: 3 additions & 0 deletions packages/peregrine/lib/Apollo/policies/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ const typePolicies = {
}
}
},
CustomerPaymentTokens: {
keyFields: () => 'CustomerPaymentTokens'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a clever solution, just give the collection an identity. I would normally suggest that the PaymentToken type needs an identity, but that may not be necessary since there's no way to mutate it. I also don't like adding these hidden requirements to queries, not sure how Apollo reacts when the field for the key identity is missing.

@sirugh - is there a technical reason we should do something like:

PaymentToken: {
    keyFields: ({ public_hash }) => `CustomerPaymentToken:${public_hash}`
},

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution you are proposing would work on individual tokens, the one I have here is for the whole collection. I feel like adding keyFields to each token would be overkill unless it provides some use. I am not equipped enough to make the call about the apollo types we are using here, I am fine with what the team thinks is the right approach.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If one of your types defines its primary key with a field besides id or _id, you can customize how the InMemoryCache generates unique identifiers for that type. To do so, you define TypePolicy for the type. You specify all of your cache's typePolicies in the options object you provide to the InMemoryCache constructor.

This is from the docs. I wouldn't try to get much more creative that our use case. We only use this because we need a handle on the cache key in order to delete it. If we find that other properties are still cached and not garbage collected after the deletion of these other objects then we may need to identify PaymentTokens with keyFields and delete them too.

},
ProductImage: {
keyFields: ['url']
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`it returns the proper shape 1`] = `
Object {
"isLoading": false,
"savedPayments": Array [],
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const Component = props => {
};

const props = {
queries: {
operations: {
getSavedPaymentsQuery: 'getSavedPaymentsQuery'
}
};
Expand All @@ -80,9 +80,8 @@ test('it returns the proper shape', () => {

// Assert.
const talonProps = log.mock.calls[0][0];
const actualKeys = Object.keys(talonProps);
const expectedKeys = ['savedPayments', 'handleAddPayment', 'isLoading'];
expect(actualKeys.sort()).toEqual(expectedKeys.sort());

expect(talonProps).toMatchSnapshot();
});

test('it returns the savedPayments correctly when present', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { gql } from '@apollo/client';

export const GET_SAVED_PAYMENTS_QUERY = gql`
query getSavedPayments {
query GetSavedPayments {
customerPaymentTokens {
items {
details
Expand All @@ -13,7 +13,5 @@ export const GET_SAVED_PAYMENTS_QUERY = gql`
`;

export default {
queries: {
GET_SAVED_PAYMENTS_QUERY
}
getSavedPaymentsQuery: GET_SAVED_PAYMENTS_QUERY
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { useCallback, useEffect } from 'react';
import { useEffect } from 'react';
import { useHistory } from 'react-router-dom';

import { useQuery } from '@apollo/client';

import { useAppContext } from '@magento/peregrine/lib/context/app';
import { useUserContext } from '@magento/peregrine/lib/context/user';

import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
import defaultOperations from './savedPaymentsPage.gql';

export const normalizeTokens = responseData => {
const paymentTokens =
(responseData && responseData.customerPaymentTokens.items) || [];
Expand All @@ -26,17 +29,16 @@ export const normalizeTokens = responseData => {
* @function
*
* @param {Object} props
* @param {SavedPaymentsPageQueries} props.queries GraphQL queries
* @param {SavedPaymentsPageQueries} props.operations GraphQL queries
*
* @returns {SavedPaymentsPageTalonProps}
*
* @example <caption>Importing into your project</caption>
* import { useSavedPayments } from '@magento/peregrine/lib/talons/SavedPaymentsPage/useSavedPaymentsPage';
*/
export const useSavedPaymentsPage = props => {
const {
queries: { getSavedPaymentsQuery }
} = props;
export const useSavedPaymentsPage = (props = {}) => {
const operations = mergeOperations(defaultOperations, props.operations);
const { getSavedPaymentsQuery } = operations;

const [
,
Expand Down Expand Up @@ -68,14 +70,9 @@ export const useSavedPaymentsPage = props => {
setPageLoading(loading);
}, [loading, setPageLoading]);

const handleAddPayment = useCallback(() => {
// TODO in PWA-637
}, []);

const savedPayments = normalizeTokens(savedPaymentsData);

return {
handleAddPayment,
isLoading: loading,
savedPayments
};
Expand All @@ -90,7 +87,7 @@ export const useSavedPaymentsPage = props => {
*
* @property {GraphQLAST} getSavedPaymentsQuery Query for getting saved payments. See https://devdocs.magento.com/guides/v2.4/graphql/queries/customer-payment-tokens.html
*
* @see [savedPaymentsPage.gql.js]{@link https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/SavedPaymentsPage/savedPaymentsPage.gql.js}
* @see [savedPaymentsPage.gql.js]{@link https://github.com/magento/pwa-studio/blob/develop/packages/peregrine/lib/talons/SavedPaymentsPage/savedPaymentsPage.gql.js}
* for queries used in Venia
*/

Expand Down
40 changes: 21 additions & 19 deletions packages/venia-ui/i18n/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
"categoryLeaf.allLabel": "All {name}",
"categoryList.errorFetch": "Data Fetch Error: ",
"categoryList.noResults": "No child categories found.",
"checkoutPage.additionalText": "You will also receive an email with the details and we will let you know when your order has shipped.",
"checkoutPage.accountSuccessfullyCreated": "Account successfully created.",
"checkoutPage.additionalText": "You will also receive an email with the details and we will let you know when your order has shipped.",
"checkoutPage.billingAddressSame": "Billing address same as shipping address",
"checkoutPage.checkout": "Checkout",
"checkoutPage.couponCode": "Enter Coupon Code",
Expand Down Expand Up @@ -84,8 +84,8 @@
"checkoutPage.quantity": "Qty : {quantity}",
"checkoutPage.quickCheckout": "Quick Checkout When You Return",
"checkoutPage.returnToCart": "Return to Cart",
"checkoutPage.reviewOrder": "Review Order",
"checkoutPage.reviewAndPlaceOrder": "Review and Place Order",
"checkoutPage.reviewOrder": "Review Order",
"checkoutPage.setAPasswordAndSave": "Set a password and save your information for next time in one easy step!",
"checkoutPage.shippingMethodStep": "2. Shipping Method",
"checkoutPage.showAllItems": "SHOW ALL ITEMS",
Expand Down Expand Up @@ -206,8 +206,8 @@
"Live Chat": "Live Chat",
"loadingIndicator.message": "Fetching Data...",
"logo.title": "Venia",
"magentoRoute.routeError": "That page could not be found. Please try again.",
"magentoRoute.internalError": "Something went wrong. Please try again.",
"magentoRoute.routeError": "That page could not be found. Please try again.",
"miniCart.checkout": "CHECKOUT",
"miniCart.editCartButton": "Edit Shopping Bag",
"miniCart.emptyMessage": "There are no items in your cart.",
Expand All @@ -228,6 +228,7 @@
"orderDetails.billingInformationLabel": "Billing Information",
"orderDetails.buyAgain": "Buy Again",
"orderDetails.discount": "Discount",
"orderDetails.noShippingInformation": "No shipping information",
"orderDetails.orderTotal": "Order Total",
"orderDetails.paymentMethodLabel": "Payment Method",
"orderDetails.printLabel": "Print Receipt",
Expand All @@ -240,8 +241,10 @@
"orderDetails.tax": "Tax",
"orderDetails.total": "Total",
"orderDetails.trackingInformation": "<strong>Tracking number:</strong> {number}",
"orderDetails.waitingOnTracking": "Waiting for tracking information",
"orderHistoryPage.emptyDataMessage": "You don't have any orders yet.",
"orderHistoryPage.pageTitleText": "Order History",
"orderItems.itemsHeading": "Items",
"orderProgressBar.deliveredText": "Delivered",
"orderProgressBar.processingText": "Processing",
"orderProgressBar.readyToShipText": "Ready to ship",
Expand All @@ -255,9 +258,10 @@
"orderRow.shippedText": "Shipped",
"Our Story": "Our Story",
"pagination.firstPage": "move to the first page",
"pagination.prevPage": "move to the previous page",
"pagination.nextPage": "move to the next page",
"pagination.lastPage": "move to the last page",
"pagination.nextPage": "move to the next page",
"pagination.prevPage": "move to the previous page",
"postcode.label": "ZIP / Postal Code",
"priceAdjustments.couponCode": "Enter Coupon Code",
"priceAdjustments.giftOptions": "See Gift Options",
"priceAdjustments.shippingMethod": "Estimate your Shipping",
Expand Down Expand Up @@ -295,7 +299,6 @@
"productOptions.selectedLabel": "Selected {label}:",
"productQuantity.label": "product's quantity",
"productSort.sortButton": "Sort",
"postcode.label": "ZIP / Postal Code",
"quantity.buttonDecrement": "Decrease Quantity",
"quantity.buttonIncrement": "Increase Quantity",
"quantity.input": "Item Quantity",
Expand All @@ -305,13 +308,13 @@
"resetPassword.invalidTokenMessage": "Uh oh, something went wrong. Check the link or try again.",
"resetPassword.newPasswordText": "New Password",
"resetPassword.pageTitleText": "Reset Password",
"resetPassword.savePassword": "Save Password",
"resetPassword.savedPasswordText": "Your new password has been saved.",
"resetPassword.savePassword": "Save Password",
"resetPassword.successMessage": "Your new password has been saved. Please use this password to sign into your Account.",
"Returns": "Returns",
"savedPaymentsPage.addButtonText": "Add a credit card",
"savedPaymentsPage.subHeading": "Credit Cards saved here will be available during checkout.",
"savedPaymentsPage.title": "Saved Payments - {store_name}",
"savedPaymentsPage.noSavedPayments": "You have no saved payments.",
"savedPaymentsPage.title": "Saved Payments",
"searchBar.heading": "Product Suggestions",
"searchBar.label": " in {label}",
"searchPage.filterButton": "Filter",
Expand All @@ -330,14 +333,14 @@
"shippingInformation.editTitle": "1. Shipping Information",
"shippingInformation.loading": "Fetching Shipping Information...",
"shippingMethod.continueToNextStep": "Continue to Payment Information",
"shippingMethod.loading": "Loading shipping methods...",
"shippingMethod.heading": "Shipping Method",
"shippingMethod.loading": "Loading shipping methods...",
"shippingMethods.estimateButton": "I want to estimate my shipping",
"shippingMethods.message": "For shipping estimates before proceeding to checkout, please provide the Country, State, and ZIP for the destination of your order.",
"shippingMethods.prompt": "Shipping Methods",
"shippingRadios.errorLoading": "Error loading shipping methods. Please ensure a shipping address is set and try again.",
"shippingSummary.estimatedShipping": "Estimated Shipping",
"shippingSummary.shipping": "Shipping",
"shippingRadios.errorLoading": "Error loading shipping methods. Please ensure a shipping address is set and try again.",
"Sign In": "Sign In",
"signIn.createAccountText": "Create an Account",
"signIn.emailAddressText": "Email address",
Expand All @@ -350,6 +353,8 @@
"sortItem.priceDesc": "Price: High to Low",
"sortItem.relevance": "Best Match",
"stockStatusMessage.message": "An item in your cart is currently out-of-stock and must be removed in order to Checkout.",
"storedPayments.creditCard": "Credit Card",
"storedPayments.delete": "Delete",
"taxSummary.estimatedTax": "Estimated Tax",
"taxSummary.tax": "Tax",
"validation.hasLengthAtLeast": "Must contain at least {value} character(s).",
Expand All @@ -366,21 +371,18 @@
"wishlist.emptyListText": "There are currently no items in this list",
"wishlist.privateText": "Private",
"wishlist.publicText": "Public",
"wishlistConfirmRemoveProductDialog.confirmationPrompt": "Are you sure you want to delete this product from the list?",
"wishlistConfirmRemoveProductDialog.confirmButton": "Delete",
"wishlistConfirmRemoveProductDialog.errorMessage": "There was an error deleting this product. Please try again later.",
"wishlistConfirmRemoveProductDialog.title": "Remove Product from Wishlist",
"wishlistItem.addToCart": "Add to Cart",
"wishlistItem.addToCartError": "Something went wrong. Please refresh and try again.",
"wishlistMoreActionsDialog.copy": "Copy to",
"wishlistMoreActionsDialog.delete": "Remove",
"wishlistMoreActionsDialog.move": "Move to",
"wishlistMoreActionsDialog.title": "Actions",
"wishlistConfirmRemoveProductDialog.confirmButton": "Delete",
"wishlistConfirmRemoveProductDialog.confirmationPrompt": "Are you sure you want to delete this product from the list?",
"wishlistConfirmRemoveProductDialog.errorMessage": "There was an error deleting this product. Please try again later.",
"wishlistConfirmRemoveProductDialog.title": "Remove Product from Wishlist",
"wishlistPage.disabledMessage": "Sorry, this feature has been disabled.",
"wishlistPage.fetchErrorMessage": "Something went wrong. Please refresh and try again.",
"wishlistPage.headingText": "Favorites Lists",
"wishlistPage.wishlistDisabledMessage": "The wishlist is not currently available.",
"orderDetails.waitingOnTracking": "Waiting for tracking information",
"orderItems.itemsHeading": "Items",
"orderDetails.noShippingInformation": "No shipping information"
"wishlistPage.wishlistDisabledMessage": "The wishlist is not currently available."
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* This file is augmented at build time using the @magento/venia-ui build
* target "payments", which allows third-party modules to add new payment component mappings.
* target "checkoutPagePaymentTypes", which allows third-party modules to
* add new payment component mappings for the checkout page.
*
* @see [Payment definition object]{@link PaymentDefinition}
*/
Expand All @@ -17,6 +18,6 @@ export default {};
* @example <caption>A custom payment method</caption>
* const myCustomPayment = {
* paymentCode: 'cc',
* importPath: '@partner/module/path_to_your_component'
* importPath: '@partner/module/path_to_your_component'
* }
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Should render properly 1`] = `
<div>
<div>
<mock-FormattedMessage
defaultMessage="Credit Card"
id="storedPayments.creditCard"
/>
</div>
<div>
**** 1234    Visa
</div>
<div>
Dec. 12
</div>
<div>
<button
disabled={false}
onClick={[Function]}
type="button"
>
<span>
<span>
<svg
fill="none"
height={16}
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
width={16}
xmlns="http://www.w3.org/2000/svg"
>
<polyline
points="3 6 5 6 21 6"
/>
<path
d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
/>
<line
x1="10"
x2="10"
y1="11"
y2="17"
/>
<line
x1="14"
x2="14"
y1="11"
y2="17"
/>
</svg>
</span>
<span>
<mock-FormattedMessage
defaultMessage="Delete"
id="storedPayments.delete"
/>
</span>
</span>
</button>
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Should render properly 1`] = `
<mock-CreditCard
details={
Object {
"expirationDate": "12/12/2022",
"maskedCC": "1234",
"type": "VI",
}
}
payment_method_code="braintree"
/>
`;
Loading