Create a new state-driven checkout page#8118
Open
mt3d wants to merge 1 commit intonopSolutions:developfrom
Open
Create a new state-driven checkout page#8118mt3d wants to merge 1 commit intonopSolutions:developfrom
mt3d wants to merge 1 commit intonopSolutions:developfrom
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR fixes #4849.
After over 50 commits (now squashed into a single commit for an easy review), this PR introduces a new checkout page where all the information could be entered in a single view. The goal of this work was to design a simplified and cohesive checkout experience could be achieved without altering the underlying checkout semantics of Nop. While the UI can certainly be further refined and some implementation details may still be open to change, the design has reached a stage where feedback is necessary before proceeding further.
Video previews of the new flow are available here and here.
From a UI perspective, the page is divided into 6 sections: Billing Address, Shipping Address, Shipping Method, Payment Method, Payment Info, and Order Summary. Each section can be updated independently. When the user sets the billing address, the payment method and payment info sections are updated. Similarly, when the user sets the shipping address, the shipping method section is recalculated. Finally, any changes to the shipping and payment methods will be reflected in the order summary section.
How does the page work internally? To understand this, we have to ask what checkout in Nop actually is. This is very important, because the new flow never attempts to change or modify the meaning of checkout in Nop, so that nothing is ever broken in other parts of the system. If we look closely at the current implementation of OPC, we will see that each step aims to to set a single value:
This PR maintains the exact same model. To support a unified page, I've created endpoints for setting each one of the above values, along with a state snapshot endpoint that returns the current aggregate checkout state.. Each section has simply to call the corresponding endpoint to update the state. Additionally, separate rendering endpoints return HTML fragments for each section. This separation of state modification and rendering allows the checkout process to remain identical to OPC while enabling a flexible client experience. These APIs are also structured in a way that could be reused by SPAs or mobile clients in the future.
On the client side, there is a checkout manager that maintains a local state, and whose job is to keep it synced with server. After each update to the state, a dependency graph is consulted to see what sections need to be updated. This ensures that updates are minimal and deterministic rather than full page reloads. Rendering functions are explicitly side effect free when it comes to the state, meaning that UI updates are always derived from server confirmed data. During initialization, the client hydrates the page from the main checkout aggregate endpoint before any interaction occurs. In this design, the server remains the single source of truth for addresses, shipping and payment selections, and requirement evaluation, while the client is responsible only for visibility rules and incremental rendering.
One major change compared to the previous OPC flow is how addresses are handled. Trying to achieve real time updates using the old forms is exceptionally hard (this is what I tried at first). Instead, address creation and editing are performed within isolated modal dialogs. This removes the need for partial live validation and incremental field synchronization, which simplifies both the client and server interaction while while still being fully compatible with the existing checkout model.
Scope and compatibility: this PR does not modify the database schema, existing public APIs, or plugin contracts. No breaking changes are introduced to the customer, shopping cart, or address entities. The implementation is additive and isolated to a new controller (SpCheckoutController). The existing OPC and standard checkout flows remain untouched, and this new checkout can coexist as an alternative implementation.
About the UI: The current UI reuses the existing section markup and styling to isolate architectural changes from visual redesign. The primary goal of this PR is to build a unified checkout and state synchronization model rather than introduce a complete UI overhaul. A more modern layout could further improve the experience, for example by using more compact sections and placing the order summary in a sticky right column for better visibility. Such refinements can be explored in the future once this new design is validated.
I would really appreciate feedback on the architectural direction, particularly regarding the endpoint design and state synchronization strategy, before continuing refinement of the UI layer.