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

[feature]: Proposal for a better checkout design #3615

Open
larsroettig opened this issue Dec 11, 2021 · 10 comments
Open

[feature]: Proposal for a better checkout design #3615

larsroettig opened this issue Dec 11, 2021 · 10 comments
Assignees
Labels
Effort: 3-Large Estimated to be a multi-day effort for a community developer. Experience recommended. enhancement New feature or request Partner: TechDivision Progress: ready for grooming Progress: ready for review

Comments

@larsroettig
Copy link
Member

larsroettig commented Dec 11, 2021

Proposal for a better checkout design

After working with an actual project based on PWA Studio, I realized the Checkout page is not adequately prepared for complex international projects. I have been thinking a lot about improving the checkout in the last few days.

I decided to discuss this publicly to get more opinions and develop the PWA Studio developer experience to the next level.

Challenge what I faced in terms of Customer Requirements

Technical proposal for more flexible flow in-context and redirect payment methods.

In my opinion, three main challenges in checkout place order are based on useEffect and not well changeable for developers.

Current Workflow
CheckoutPlaceOrder

Better would be here to use a changeable state machine pattern with default workflow.

// function to demo new API
const delay = delay => {
  var start = new Date().getTime();
  while (new Date().getTime() < start + delay);
}

const cartId = "12233";

const fetchCartDetailOrder = (variables)=> {
 console.log("fetchCartDetailOrder", variables);
 delay(Math.random()*100);
 console.log("fetchCartDetailOrder successfully with ", cartId);
}

const placeOrder = async (variables) => {
console.log("placeOrder", variables);
delay(Math.random() * 100);
const { cartId } = variables;
console.log("Order placed successfully with ", cartId);
};

const removeCart = async () => {
delay(Math.random() * 100);
console.log("Remove Cart ");
};

const clearCartDataFromCache = async () => {
  delay(Math.random() * 100);
console.log("clearCartDataFromCache");
};

// Current Design
async function placeOrderAndCleanup() {
await placeOrder({ cartId });
await removeCart();
await clearCartDataFromCache();
}

// New Design idea
async function placeOrderStateMaschine(placeOrderWorkFlow) {
Object.keys(placeOrderWorkFlow).forEach((key) => {
  placeOrderWorkFlow[key]();
});
}

// schould be returned by useCheckout
const placeOrderWorkFlow = {
fetchCartDetailOrder: () => fetchCartDetailOrder({ cartId }),
placeOrder: () => placeOrder({ cartId }),
// possible to add more workflows action
removeCart,
placeOrderAndCleanup,
};

console.log("----------------- OLD API ----------------");
placeOrderAndCleanup().then(() => {

console.log("----------------- New API ----------------");
placeOrderStateMaschine(placeOrderWorkFlow);
});

API to allow to replace place order Button with a custom

MyCustomPlaceOrderButton

const MyCustomPlaceOrderButton = props => {
    const {handlePlaceOrder,isUpdating,placeOrderLoading,orderDetailsLoading} = props; 
    const PlaceOrderButton = placeOrderButtonCollection[paymentMethod] || null;
    
    return <Button>My Custome Button </Button>
};

placeButtonOrderCollection

const paypal_express = React.lazy(() => import('@my_namespace/components/MyCustomPlaceOrderButton'));

const placeButtonOrderCollection = {
    paypal_express
};

PlaceOrderButton

const PlaceOrderButton = props => {

const { paymentMethod, loading } = usePlaceOrderButton();

const classes = useStyle(defaultClasses, props.classes);
const {handlePlaceOrder,isUpdating,placeOrderLoading,orderDetailsLoading} = props; 

 if (loading) {
        return (
            <LoadingIndicator>
                <FormattedMessage
                    id={'express.place.loading'}
                    defaultMessage={'Collect Order Totals...'}
                />
            </LoadingIndicator>
        );
    }

if (placeButtonOrderCollection[paymentMethod]) {
   return productDetailPageCollection[paymentMethod];
}

 return (
        <Button
            onClick={handlePlaceOrder}
            priority="high"
            className={classes.place_order_button}
            disabled={isUpdating || placeOrderLoading || orderDetailsLoading}
        >
            <FormattedMessage
                id={'checkoutPage.placeOrder'}
                defaultMessage={'Place Order'}
            />
        </Button>
    );
}

A three-step approach makes complex induce own workflow for redirect and in-context. Better go here with one-step or two-step checkouts like shipment as the first step. The second step could be here, then payment and review merged in one step.

@larsroettig larsroettig added the enhancement New feature or request label Dec 11, 2021
@m2-assistant
Copy link

m2-assistant bot commented Dec 11, 2021

Hi @larsroettig. Thank you for your report.
To speed up processing of this issue, make sure that you provided sufficient information.

Add a comment to assign the issue: @magento I am working on this


@larsroettig larsroettig added Progress: ready for review Effort: 3-Large Estimated to be a multi-day effort for a community developer. Experience recommended. Partner: TechDivision labels Dec 11, 2021
@tkacheva
Copy link
Contributor

@larsroettig could you clarify couple of points before we take this to the triage meeting:

  1. applying gift cards and discounts at checkout - do you recommend to move coupon code and gift cards before payment methods to respect subtotal threshold that payment methods might require?
  2. in-context and re-direct payment methods - we have this on roadmap for payment methods extensibility. Will appreciate if you take a look on the proposed scope and provided your feedback
  3. zip, country code, phone are optional based on config - the config setting is not respected currently?

@larsroettig
Copy link
Member Author

  1. applying gift cards and discounts at checkout - do you recommend moving coupon code and gift cards before payment methods to respect the subtotal threshold that payment methods might require?

Yes, would we nice some payments that already preauthorize the total amount to get a valid token.
I added a new endpoint to trigger this later in checkout when the user clicks place order, which makes the checkout complex.

The second Problem is order total is often used to filter unavailable payments out from the collection like COD.
https://docs.magento.com/user-guide/payment/cash-on-delivery.html

  1. in-context and re-direct payment methods - we have this on a roadmap for payment methods extensibility. Will appreciate it if you took a look at the proposed scope and provided your feedback.

Would you be happy where I can read throw it?

  1. zip, country code, phone are optional based on config - the config setting not currently respected?

I reviewed the code looks like this is currently not taken into account but I can test it in lasted dev version will follow up on this.

@fooman
Copy link
Contributor

fooman commented Dec 22, 2021

applying gift cards and discounts at checkout - do you recommend to move coupon code and gift cards before payment methods to respect subtotal threshold that payment methods might require?

The checkout should ideally be flexible enough to cater for any order. Venia then provides a best practice reference implementation. If a payment method becomes unavailable the back-end will communicate this to the frontend, for example removing it from the available payment methods. The checkout should then bring this to the shoppers attention and ask for a different payment method if needed.

zip, country code, phone are optional based on config - the config setting is not respected currently?

The GraphQL schema unfortunately enforces its own requirements which is not respecting the configuration values:

image

Since the schema requires certain inputs PWA Studio has to ask for it too.

@fooman
Copy link
Contributor

fooman commented Jan 8, 2022

One thing to add: the current checkout implementation hard codes shipping address and shipping method selection as a step. This will need to be adjustable so that things like gift card only orders are possible that only need billing info and payment.

@anthoula
Copy link
Contributor

@magento export issue to JIRA project PWA as Story

@github-jira-sync-bot
Copy link

✅ Jira issue https://jira.corp.magento.com/browse/PWA-2544 is successfully created for this GitHub issue.

@anthoula anthoula added the needs-triage A pull request or issue that needs to be triaged prior to being synced to JIRA label Jan 26, 2022
@larsroettig
Copy link
Member Author

One thing to add: the current checkout implementation hard codes shipping address and shipping method selection as a step. This will need to be adjustable so that things like gift card only orders are possible that only need billing info and payment.

Yep good point 👍

@fooman
Copy link
Contributor

fooman commented Feb 7, 2022

I am just going to drop this into this discussion but it may as well be a separate proposal for overhauling just the totals display.

I am currently adding a new total below the subtotal as shown in the below screenshot:

image

To achieve this the following is required:

  1. Back-end module to add to GraphQl response
  2. Make changes to peregrine/lib/talons/CartPage/PriceSummary/usePriceSummary
  3. Make changes to peregrine/lib/talons/CartPage/PriceSummary/priceSummaryFragments.gql.js to make sure data is queried via the same GraphQl query
  4. Make changes to venia-ui/src/components/CartPage/priceSummary

In an ideal world there would be an extension point for totals. This would collect the display component and fragment and then does the rest so we would end up with something like this:

  1. Back-end module to add to GraphQl response
  2. integrate with target for totals

@tkacheva
Copy link
Contributor

tkacheva commented Feb 8, 2022

@fooman and @larsroettig,
we are looking into extending checkout and making shipping step to be removed/replaced to enable virtual products and virtual gift cards like @fooman pointed out. A use case for replacing a shipping step will be in-store pickup. Do you guys have any other use cases in mind for the shipping step extensibility?

@anthoula anthoula added Progress: ready for grooming and removed needs-triage A pull request or issue that needs to be triaged prior to being synced to JIRA labels May 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Effort: 3-Large Estimated to be a multi-day effort for a community developer. Experience recommended. enhancement New feature or request Partner: TechDivision Progress: ready for grooming Progress: ready for review
Projects
None yet
Development

No branches or pull requests

6 participants