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

[PWA-239] Shipping Method (Cart) #2123

Merged
merged 31 commits into from
Feb 11, 2020
Merged

Conversation

tjwiebell
Copy link
Contributor

Description

When a user (shopper) is in the cart flow for Venia, a shipping method selection/estimate component should display in order to allow a shopper to determine the impact of shipping to their order summary. 

 
Requirements: 

Adhere to design specs/flows
Initial design accounts for unauthenticated cart/checkout, authenticated to be a fast follow
out of scope: 

detecting location based on customer device

Related Issue

Acceptance

Verification Stakeholders

Specification

Verification Steps

If you want to verify that third-party shipping providers are working, you'll need inventory items that have weight, and your shipping methods configured in the backend. I've done this with a staging environment, you'll have to use Carmina Necklace: https://mcstaging-jnz3dtiuj77ca.dummycachetest.com/

  1. Add product to your cart
  2. Navigate to /cart page and verify that estimate shipping fields are displayed (country, state, zip)
  3. Enter values for these fields and shipping methods should be displayed based on available methods
  4. Select a method and verify that PriceSummary is updated to reflect this selection

Screenshots / Screen Captures (if appropriate)

Checklist

  • I have updated the documentation accordingly, if necessary.
  • I have added tests to cover my changes, if necessary.

@tjwiebell tjwiebell added the version: Minor This changeset includes functionality added in a backwards compatible manner. label Jan 28, 2020
@m2-community-project m2-community-project bot added this to Ready for Review in Pull Request Progress Jan 28, 2020
@PWAStudioBot
Copy link
Contributor

PWAStudioBot commented Jan 28, 2020

Messages
📖

Access a deployed version of this PR here. Make sure to wait for the "pwa-pull-request-deploy" job to complete.

📖 DangerCI Failures related to missing labels/description/linked issues/etc will persist until the next push or next nightly build run (assuming they are fixed).
📖

Associated JIRA tickets: PWA-239.

Generated by 🚫 dangerJS against c5cfe68

@tjwiebell tjwiebell marked this pull request as ready for review January 29, 2020 18:28
Copy link
Contributor

@sirugh sirugh left a comment

Choose a reason for hiding this comment

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

Nice work! Nothing major stands out to me other than the ungodly amount of time it can take to perform mutations once you've set a method...

const options = items.map(({ label, value }) => (
<Option key={value} value={value}>
const options = items.map(({ id = null, label, value }) => (
<Option key={id || value} value={value}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Add id to items shape. Also why?

Copy link
Contributor

Choose a reason for hiding this comment

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

If this is because of a duplicate value in a response maybe its a bug?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

// TODO: these classes may not be defined!
classes={{
label: classes.radioLabel,
root: classes.radio
Copy link
Contributor

Choose a reason for hiding this comment

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

I looked and couldn't find any other reference to the RadioGroup component outside of your usage in this PR. Perhaps we can just update the styles for it instead of overriding classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These styles were a little opinionated about the label, using grid to flow content based on screen size, which I wouldn't want to make the default style. Decided to leave this as-is.

@@ -40,7 +51,9 @@ export class RadioGroup extends Component {
{options}
</BasicRadioGroup>
</div>
<Message fieldState={fieldState}>{message}</Message>
<Message className={classes.message} fieldState={fieldState}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting -- was this just not using the class?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Inherited some of the UI work from @supernova-at, who made this change, but from what I can tell none of the styles were extensible, which is what was fixed here.

<a href="https://jira.corp.magento.com/browse/PWA-239">
Shipping Methods to be completed by PWA-239.
</a>
<ShippingMethods />
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you set this to isOpen? I accidentally left the coupon code as the default one (and that got merged).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 9c94499. UX would actually prefer this is closed on first render, but given the bug that closes all panels every time an effect is fired, I'm going to suggest leaving open for now.

) {
cart {
id
...PriceSummaryFragment
Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer to refetch the entire cart page fragment (which includes price summary) because we (the shipping mutation) don't know what else may need eventually want to re-render based on the mutation. For example maybe we have a new UI component that needs to show the chosen option.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 9c94499

<Form className={classes.root}>
<ShippingFields
selectedShippingFields={selectedShippingFields}
setIsFetchingMethods={setIsFetchingMethods}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need this state -- you can define the mutations in this component (or talon) and expose the loading state from there. Then you don't need to pass in a callback here and you won't need the effect inside the shipping fields talon, you'd just pass the handleSubmit callback which would invoke the mutation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll look into this. I was constrained by the mutations access to the form fields, but maybe there is another way to gain access outside of the form with a submit handler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Re-factored this state sync prop out in 9c94499.

<TextInput
field="zip"
initialValue={zip}
onBlur={handleZipOnBlur}
Copy link
Contributor

Choose a reason for hiding this comment

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

If this field is required for the methods to be fetched we may want to indicate that somehow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Re-factored to use forms submit handlers, should be more clear what triggers the fetch of methods now.


const handleShippingSelection = useCallback(
value => {
const [carrierCode, methodCode] = value.split('|');
Copy link
Contributor

Choose a reason for hiding this comment

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

Clever, but can value not be an object?

Copy link
Contributor Author

@tjwiebell tjwiebell Jan 29, 2020

Choose a reason for hiding this comment

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

Man, you missed a thrilling discussion in Slack about this. tl;dr - no, we should strive for rendered markup to still be valid, and radio values must be of type DomString. Would love your opinion on this as well.

https://magento.slack.com/archives/G8N21AQTV/p1580161395028400

label: region.name,
value: region.code
}));
formattedStatesData.unshift({ label: '', value: '' });
Copy link
Contributor

Choose a reason for hiding this comment

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

You do this to present an empty state initially, right? Rather than allowing it as an option maybe we should set the initial selection to <option disabled selected value> -- Select a FOO -- </option> inside the Select component as a default (or configurable) UI.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, good catch. I intended to add support for disabled and hidden props to the Select component options and just completely forgot, will get those added.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added these props in 9c94499

}

let formattedStatesData = [];
if (fetchStatesCalled && !isStatesLoading && !statesError) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to have a consensus on loading states at some point. Did UX direct you to intentionally show "loading countries" but not "loading states/regions"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No direction, was waiting on demo to confirm those details. There's a bigger problem here too with non-US countries that don't even have state options, and how to handle that. Will get that lined up for tomorrow.

Copy link
Contributor

@supernova-at supernova-at left a comment

Choose a reason for hiding this comment

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

Graceful handling of shipping methods not loading is really the only thing (see #2123 (comment)).

Great job!

@@ -82,7 +82,7 @@ const ShippingForm = props => {
{!hasMethods ? (
<Button
classes={{ root_normalPriority: classes.submit }}
disabled={setShippingLoading ? true : null}
disabled={setShippingLoading}
Copy link
Contributor

Choose a reason for hiding this comment

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

Took me a second to parse this one because setShippingLoading reads like a function, not a boolean.

Up to you if you want to change it or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, renamed to follow our bool naming convention in cf8fd2e, good call.

supernova-at
supernova-at previously approved these changes Feb 6, 2020
@supernova-at supernova-at dismissed their stale review February 6, 2020 15:20

Want to memoize the showForm function.

supernova-at
supernova-at previously approved these changes Feb 6, 2020
schensley
schensley previously approved these changes Feb 7, 2020
Copy link

@schensley schensley left a comment

Choose a reason for hiding this comment

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

UX approved.
Nice work!

@dpatil-magento
Copy link
Contributor

@tjwiebell Other than shipping option ordering issue rest all looks good.

@sirugh
Copy link
Contributor

sirugh commented Feb 11, 2020

There is an issue with GQL response returning incorrect values for flatrate, but that should be handled separately. If @dpatil-magento made a ticket can you post it here? Thanks!

@dpatil-magento
Copy link
Contributor

@dpatil-magento dpatil-magento merged commit 9346ba2 into develop Feb 11, 2020
@dpatil-magento dpatil-magento deleted the supernova/239_shipping_methods branch February 11, 2020 21:35
@m2-community-project m2-community-project bot moved this from Review in Progress to Done in Pull Request Progress Feb 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg:peregrine pkg:venia-ui version: Minor This changeset includes functionality added in a backwards compatible manner.
Development

Successfully merging this pull request may close these issues.

None yet

7 participants