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 8 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
3 changes: 3 additions & 0 deletions packages/peregrine/lib/Apollo/clearCartDataFromCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ export const clearCartDataFromCache = async client => {
await deleteCacheEntry(client, key =>
key.match(/^\$?AvailableShippingMethod/)
);
await deleteCacheEntry(client, key =>
key.match(/^\$?customerPaymentTokens/)
);
tjwiebell marked this conversation as resolved.
Show resolved Hide resolved
};
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
1 change: 1 addition & 0 deletions packages/venia-ui/i18n/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@
"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.noSavedPayments": "You have no saved payments.",
"savedPaymentsPage.title": "Saved Payments",
"searchBar.heading": "Product Suggestions",
"searchBar.label": " in {label}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ exports[`renders correctly when there are existing saved payments 1`] = `
public_hash="78asfg87ibafv"
/>
</div>
<div
className="noPayments"
/>
</div>
`;

Expand All @@ -41,5 +44,90 @@ exports[`renders correctly when there are no existing saved payments 1`] = `
<div
className="content"
/>
<div
className="noPayments"
>
You have no saved payments.
</div>
</div>
`;

exports[`renders loading indicator when isLoading is true 1`] = `
<div
className="global"
>
<span
className="root"
>
<svg
className="icon"
fill="none"
height={64}
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
width={64}
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="12"
x2="12"
y1="2"
y2="6"
/>
<line
x1="12"
x2="12"
y1="18"
y2="22"
/>
<line
x1="4.93"
x2="7.76"
y1="4.93"
y2="7.76"
/>
<line
x1="16.24"
x2="19.07"
y1="16.24"
y2="19.07"
/>
<line
x1="2"
x2="6"
y1="12"
y2="12"
/>
<line
x1="18"
x2="22"
y1="12"
y2="12"
/>
<line
x1="4.93"
x2="7.76"
y1="19.07"
y2="16.24"
/>
<line
x1="16.24"
x2="19.07"
y1="7.76"
y2="4.93"
/>
</svg>
</span>
<span
className="message"
>
<mock-FormattedMessage
defaultMessage="Fetching Data..."
id="loadingIndicator.message"
/>
</span>
</div>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const talonProps = {
]
};

it('renders correctly when there are no existing saved payments', () => {
test('renders correctly when there are no existing saved payments', () => {
// Arrange.
useSavedPaymentsPage.mockReturnValueOnce({ savedPayments: [] });

Expand All @@ -43,7 +43,7 @@ it('renders correctly when there are no existing saved payments', () => {
expect(instance.toJSON()).toMatchSnapshot();
});

it('renders correctly when there are existing saved payments', () => {
test('renders correctly when there are existing saved payments', () => {
// Arrange.
useSavedPaymentsPage.mockReturnValueOnce(talonProps);

Expand All @@ -53,3 +53,17 @@ it('renders correctly when there are existing saved payments', () => {
// Assert.
expect(instance.toJSON()).toMatchSnapshot();
});

test('renders loading indicator when isLoading is true', () => {
// Arrange.
useSavedPaymentsPage.mockReturnValueOnce({
...talonProps,
isLoading: true
});

// Act.
const instance = createTestInstance(<SavedPaymentsPage {...props} />);

// Assert.
expect(instance.toJSON()).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
grid-template-columns: 1fr 1fr 1fr;
}

.noPayments {
text-align: center;
}

.addButton {
border: 2px dashed rgb(var(--venia-global-color-gray-400));
border-radius: 0.375rem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,58 @@ import { mergeClasses } from '@magento/venia-ui/lib/classify';

import { Title } from '../Head';
import PaymentCard from './paymentCard';
import { fullPageLoadingIndicator } from '../LoadingIndicator';

import defaultClasses from './savedPaymentsPage.css';

const SavedPaymentsPage = props => {
const talonProps = useSavedPaymentsPage();

const { savedPayments } = talonProps;
const { isLoading, savedPayments } = talonProps;

const classes = mergeClasses(defaultClasses, props.classes);

const savedPaymentElements = useMemo(
() =>
savedPayments.map(paymentDetails => (
const { formatMessage } = useIntl();

const savedPaymentElements = useMemo(() => {
if (savedPayments.length) {
return savedPayments.map(paymentDetails => (
<PaymentCard
key={paymentDetails.public_hash}
{...paymentDetails}
tjwiebell marked this conversation as resolved.
Show resolved Hide resolved
/>
)),
[savedPayments]
);
));
} else {
return null;
}
}, [savedPayments]);

const { formatMessage } = useIntl();
const noSavedPayments = useMemo(() => {
if (!savedPayments.length) {
return formatMessage({
id: 'savedPaymentsPage.noSavedPayments',
defaultMessage: 'You have no saved payments.'
});
} else {
return null;
}
}, [savedPayments, formatMessage]);

const title = formatMessage({
id: 'savedPaymentsPage.title',
defaultMessage: 'Saved Payments'
});

if (isLoading) {
return fullPageLoadingIndicator;
}

return (
<div className={classes.root}>
<Title>{title}</Title>
<h1 className={classes.heading}>{title}</h1>
<div className={classes.content}>{savedPaymentElements}</div>
<div className={classes.noPayments}>{noSavedPayments}</div>
</div>
);
};
Expand Down